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[];
}
我目前正在使用 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[];
}