我目前正在使用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.
非常感谢任何帮助。
客户是
答案 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