ZLMediaKit / ZLToolKit

一个基于C++11的轻量级网络框架,基于线程池技术可以实现大并发网络IO
MIT License
1.94k stars 581 forks source link

UDP data may be misread. #216

Open kongxa opened 7 months ago

kongxa commented 7 months ago

In UdpServer.cpp, after UdpServer receives the first data packet from the peer, it creates a new socket based on the local address and peer address. When creating a new socket, bindUdpSock is executed first. Will other data packets from the peer be received in the moment before bindPeerAddr?

From my current program, it seems that this situation exists.

Running environment: debian11
Address used: 127.0.0.1
Testing method: 1 UdpServer, 500 udp clients sending data simultaneously
        lock_guard<std::recursive_mutex> lck(*_session_mutex);
        auto it = _session_map->find(id);
        if (it != _session_map->end()) {
            return it->second;
        }
        assert(_socket);
        socket->bindUdpSock(_socket->get_local_port(), _socket->get_local_ip());
        socket->bindPeerAddr((struct sockaddr *) addr_str.data(), addr_str.size());
        auto helper = _session_alloc(server, socket);
        helper->session()->attachServer(*this);

在UdpServer.cpp中,UdpServer在接收到对端发送的首个数据后,会根据本地地址和对端地址创建新的socket。在创建新socket的时候首先执行bindUdpSock,在bindPeerAddr之前的这一瞬间会不会接收其他对端的数据包? 从我当前的程序看是存在这种情况的。 运行环境:debian11 使用地址:127.0.0.1 测试方式:1个UdpServer,500个udp client同时发送数据

lock_guard<std::recursive_mutex> lck(*_session_mutex);
auto it = _session_map->find(id);
if (it != _session_map->end()) {
return it->second;
}
assert(_socket);
socket->bindUdpSock(_socket->get_local_port(), _socket->get_local_ip());
socket->bindPeerAddr((struct sockaddr *) addr_str.data(), addr_str.size());
auto helper = _session_alloc(server, socket);
helper->session()->attachServer(*this);

TRANS_BY_GITHUB_AI_ASSISTANT

xia-chu commented 7 months ago

Possibly, so the code later made a judgment:

socket->setOnRead([weak_self, weak_helper, id](const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len) {
            auto strong_self = weak_self.lock();
            if (!strong_self) {
                return;
            }

            //快速判断是否为本会话的的数据, 通常应该成立
            if (id == makeSockId(addr, addr_len)) {
                if (auto strong_helper = weak_helper.lock()) {
                    emitSessionRecv(strong_helper, buf);
                }
                return;
            }

            //收到非本peer fd的数据,让server去派发此数据到合适的session对象
            strong_self->onRead_l(false, id, buf, addr, addr_len);
        });

可能 所以后面代码做了判断:


socket->setOnRead([weak_self, weak_helper, id](const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len) {
auto strong_self = weak_self.lock();
if (!strong_self) {
return;
}
        //快速判断是否为本会话的的数据, 通常应该成立
        if (id == makeSockId(addr, addr_len)) {
            if (auto strong_helper = weak_helper.lock()) {
                emitSessionRecv(strong_helper, buf);
            }
            return;
        }

        //收到非本peer fd的数据,让server去派发此数据到合适的session对象
        strong_self->onRead_l(false, id, buf, addr, addr_len);
    });


`TRANS_BY_GITHUB_AI_ASSISTANT`