C WINAPI recv() 在接收到所有数据之前返回 0
我正在使用 中的代码MSDN 的 recv() 页面,但我更改了发送的数据以及目标端口和 IP 地址,以发送 HTTP GET 请求来获取 google.com/index.php。每次我运行它时,recv() 在获取大部分页面后返回 0,但不是全部。我用wireshark验证了整个页面都已收到,但它在之后停止,后跟一个非ASCII符号。
这是我正在使用的代码,我删除了大部分注释和错误检查,但其他方面与上面的链接相同:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
int main() {
WSADATA wsaData;
int iResult;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
char *sendbuf = "GET /index.php\r\nHost: www.google.com\r\n\r\n";
char recvbuf[512];
int recvbuflen = 512;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "74.125.224.180" );
clientService.sin_port = htons( 80 );
iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 ){
printf("%512s", recvbuf);
//printf("recv returned %d... got %d bytes\n", iResult, recvbuflen);
}
else if ( iResult == 0 )
printf("\n\nConnection closed\n");
else
printf("\n\nrecv failed: %d\n", WSAGetLastError());
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
我正在使用 mingw32 版本 4.2.1 在 linux 上进行编译。
I'm using the code from MSDN's recv() page, but I changed the data being sent and destination port and IP address to send a HTTP GET request to get google.com/index.php. Every time I run it, recv() returns 0 after getting most of the page, but not all. I verified with wireshark that the entire page is received, but it stops after <a href=//google.co
, followed by a non-ASCII symbol.
Here's the code I'm using, I took out most of the comments and error checking but otherwise it's the same as the link above:
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
int main() {
WSADATA wsaData;
int iResult;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;
char *sendbuf = "GET /index.php\r\nHost: www.google.com\r\n\r\n";
char recvbuf[512];
int recvbuflen = 512;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( "74.125.224.180" );
clientService.sin_port = htons( 80 );
iResult = connect( ConnectSocket, (SOCKADDR*) &clientService, sizeof(clientService) );
iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
printf("Bytes Sent: %ld\n", iResult);
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 ){
printf("%512s", recvbuf);
//printf("recv returned %d... got %d bytes\n", iResult, recvbuflen);
}
else if ( iResult == 0 )
printf("\n\nConnection closed\n");
else
printf("\n\nrecv failed: %d\n", WSAGetLastError());
} while( iResult > 0 );
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
I'm compiling on linux with mingw32 version 4.2.1.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我只看了一眼,但最明显的错误是:
没有人会为你编写使 C 字符串起作用的 NUL 字符。特别是,由于打印字符串意味着搜索 NUL 字符,并且没有通过网络发送任何字符,因此在
recv
之后的最后一个printf
也可能会吐出一些垃圾它位于上一次循环迭代的缓冲区中。你可以尝试这样的事情:这样你就只打印
recv
告诉你在缓冲区中的字符。I've only glanced, but the most glaring error is this:
Nobody will write that NUL character for you that makes C strings work. In particular, since printing strings means searching for NUL characters, and there aren't any sent over the wire, your last
printf
after arecv
will likely also spit out some garbage that was in the buffer from the previous loop iteration. You can try something like this:This way you only print characters that
recv
told you were in the buffer.