D receiveFrom 没有收到完整的数据包

D receiveFrom not recieving full packet

我目前正在使用 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.

如有任何帮助,我们将不胜感激。

客户是

这一行有问题:

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

使用 ref 你不会制作切片,但你确实修改了原始缓冲区,所以如果前一个数据包的长度超过 7 个字节,你将无法再接收超过 7 个字节的数据

因此您可以更改代码以删除 ref 和 return 长度而不是普通的 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 但仅更改部分代码 handlePacket

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