【发布时间】:2021-04-02 15:09:05
【问题描述】:
我正在尝试使用 Winsock 接收数据包,并且我能够从 recvfrom() 命令获得返回,但是当我尝试打印缓冲区中保存的数据时,我只得到 E。
这是我使用 recvfrom 命令的地方:
i = 0;
while (i < 25) {
data_len = recvfrom(raw_socket, rcvbuf, sizeof(rcvbuf), 0, (SOCKADDR*)&sender_addr, &sender_addr_size);
std::cout << "Iteration: " << (i);
printf("\nReceived packet from %s:%d\n", inet_ntoa(sender_addr.sin_addr), ntohs(sender_addr.sin_port));
printf("Length of bytes received: %d\n", data_len);
printf("Data: %s\n", rcvbuf);
std::cout << "\n\n";
i = i + 1;
}
运行代码时的示例返回:
迭代次数:21
从隐藏 IP 收到的数据包:0
收到的字节长度:1385
数据:E
这不是缓冲区大小的错误,在网上搜索了几个小时后,我找不到任何描述我的问题的东西。 如果有人知道这里发生了什么,我将非常感谢您的解释甚至更好的修复。
其他可能有用的代码:
char rcvbuf[10000];
...
// create a raw socket
raw_socket = socket(AF_INET, SOCK_RAW, 0);
if (raw_socket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
...
// Bind the IPv4 address to the socket
if0.sin_addr.S_un.S_addr = inet_addr(local_ip);
if0.sin_family = AF_INET;
if0.sin_port = htons(14996);;
if (bind(raw_socket, (SOCKADDR*)&if0, sizeof(if0)) == SOCKET_ERROR) {
printf("bind() failed with error code %d\n", WSAGetLastError());
return -1;
}
else printf("bind() is OK!\n");
感谢每一位帮助过的人 :) 我为打印缓冲区中的二进制数据所做的更改(不考虑字节序):
// receive all packages in a while loop
std::cout << "Connected on IPv4 Address: " << local_ip << "\n";
i = 0;
while (i < 2) {
data_len = recvfrom(raw_socket, rcvbuf, sizeof(rcvbuf), 0, (SOCKADDR*)&sender_addr, &sender_addr_size);
std::cout << (i);
printf("\nReceived packet from %s:%d\n", inet_ntoa(sender_addr.sin_addr), ntohs(sender_addr.sin_port));
printf("Length of bytes received: %d\n", data_len);
printf("Data: ");
//std::cout.write(rcvbuf, data_len);
std::string s = rcvbuf;
for (int i2 = 0; i2 < data_len;) {
std::cout << std::bitset<8>(s[i2]) << " ";
i2 = i2 + 1;
}
std::cout << "\n--------------------------\n";
memset(rcvbuf, 0, 10000);
i = i + 1;
}
【问题讨论】:
-
这可能是二进制数据恰好有 0 作为第二个字节。回想一下,
printf("Data: %s\n", rcvbuf);假定rcvbuf指向一个以 nul 结尾的字符串,因此会在遇到的第一个零字节处停止打印。 -
啊是的,这是有道理的,我已将字符串类型更改为其他类型,并且得到了不同的结果。谢谢。
-
无需将
rcvbuf转换为std::string即可将其打印出来。可以直接打印rcvbuf的内容。特别是因为您的转换存在与原始printf相同的错误 - 假设rcvbuf是一个以空字符结尾的字符串,而实际上它不是。
标签: c++ visual-studio winapi networking winsock