D receiveFrom未收到完整数据包

时间:2016-04-30 20:16:06

标签: sockets networking udp d

我目前正在使用D为游戏编写一个小型UDP服务器。问题是收到的一些数据包与实际数据包的长度不匹配(通过wireshark查看)。

例如,客户端通过网络发送一个110字节的数据包,该数据包显示在wireshark下。但D代码只接收7个字节!从客户端通过网络发送的其他7字节数据包没有。

D中的7个字节与110字节数据包中的前7个字节匹配。我认为这是套接字库的问题,因为我无法想到任何可能导致此问题的其他内容。

问题始终发生在同一点和完全相同的数据包中。如果忽略,则某些数据包的问题仍然存在。

请注意,此项目中有多个文件,因此我在下面提供了以下代码的剪辑:

this(in Logger logger, string bindInterface = "0.0.0.0", ushort bindPort = 19132) {
    this.logger = logger;
    socket = new UdpSocket(AddressFamily.INET);
    bindAddress = new InternetAddress(bindInterface, bindPort);
}

void bind(uint sendBufferSize = 1024 * 1024, uint recvBufferSize = 1024 * 1024) {
    socket.bind(bindAddress);

    socket.setOption(SocketOptionLevel.SOCKET, SocketOption.BROADCAST, true);
    socket.setOption(SocketOptionLevel.SOCKET, SocketOption.SNDBUF, sendBufferSize);
    socket.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVBUF, recvBufferSize);
    socket.blocking = false;
}

bool recv(ref Address address, ref byte[] buffer) {
    auto length = socket.receiveFrom(buffer, SocketFlags.NONE, address);
    if(length > 0) {
        buffer.length = length;
        debug logger.logDebug(to!string(length) ~ " Packet IN: " ~ to!string(cast(ubyte[]) buffer));
        return true;
    }
    buffer = null;
    return false;
}

...

Address a;
    byte[] data = new byte[1024 * 1024];
    while(max-- > 0 && socket.recv(a, data)) {
        handlePacket(a, data);
    }

可以找到完整的来源here.

非常感谢任何帮助。

客户是

1 个答案:

答案 0 :(得分:3)

问题在于这一行:

bool recv(ref Address address, ref byte[] buffer)

使用ref你没有切片,但是你真的修改了原始缓冲区,所以如果以前的数据包长7bytes,你不能再接收超过7个字节

因此,您可以更改代码以删除ref并返回长度而不是plain bool

size_t recv(ref Address address, byte[] buffer);

然后:

Address a;
byte[] data = new byte[1024 * 1024];
size_t len;
while(max-- > 0 && (len = socket.recv(a, data))) {
    handlePacket(a, data[0 .. len]);
}

但由于另一个handlePacket,这可能不适用于您的ref功能,因此另一个变体是不要更改您的recv,而只是改变代码的一部分{{1} }

handlePacket