Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Winsock blocking recv()不会返回,而WireShark表示TCP流中有传入的段_Tcp_Winsock_Wireshark - Fatal编程技术网

Winsock blocking recv()不会返回,而WireShark表示TCP流中有传入的段

Winsock blocking recv()不会返回,而WireShark表示TCP流中有传入的段,tcp,winsock,wireshark,Tcp,Winsock,Wireshark,我正在使用VC++2013社区的Windows 10 pro上使用一些协议,基本上包括三个步骤: 客户端发送GET头(例如身份验证等) 服务器返回HTTP头(例如,如果一切正常,状态代码为200) 然后服务器在HTTP头之后继续发送二进制数据流 我发送报头,并在阻塞模式下调用recv(),以通过TCP流从服务器接收数据。但是,recv()阻塞,永远不会返回 我使用WireShark来“跟踪”TCP流,它表明服务器确实一直在发送二进制数据,并且我确实看到了来自客户端的ACK消息,以确认它接收到

我正在使用VC++2013社区的Windows 10 pro上使用一些协议,基本上包括三个步骤:

  • 客户端发送GET头(例如身份验证等)
  • 服务器返回HTTP头(例如,如果一切正常,状态代码为200)
  • 然后服务器在HTTP头之后继续发送二进制数据流
我发送报头,并在阻塞模式下调用recv(),以通过TCP流从服务器接收数据。但是,recv()阻塞,永远不会返回

我使用WireShark来“跟踪”TCP流,它表明服务器确实一直在发送二进制数据,并且我确实看到了来自客户端的ACK消息,以确认它接收到的每个段。但是,recv()仍然会阻塞,并且永远不会返回

我尝试使用:

  • WinSock上的纯C实现
  • C#使用TcpClient
  • C++与Boost-Asio
  • 非阻塞WinSock(如中所示)
  • 第一个版本是在WinHTTP中实现的,最终得到了超时
他们都不能接收任何数据。然而,WireShark仍然可以判断出服务器一直在发送二进制数据

我试图关闭防火墙,但问题仍然存在

最奇怪的是,大约两天前,我的第一个实现确实成功地从recv()获取了数据。那天,recv()返回了三次,然后再次被阻止。第二天,同一个实现recv()将永远无法返回任何内容

我真的很困惑。谢谢大家!

以下是阻止Winsock版本的代码:

WSADATA wsaData;
int iResult;

SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in clientService;


char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;

//----------------------
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
    printf("WSAStartup failed: %d\n", iResult);
    return 1;
}

//----------------------
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET) {
    printf("Error at socket(): %ld\n", WSAGetLastError());
    WSACleanup();
    return 1;
}

//----------------------
// The sockaddr_in structure specifies the address family,
// IP address, and port of the server to be connected to.
clientService.sin_family = AF_INET;

auto ip = gethostbyname(name);
clientService.sin_addr = *(reinterpret_cast<struct in_addr *>(ip->h_addr));
clientService.sin_port = htons(DEFAULT_PORT);

//----------------------
// Connect to server.
iResult = connect(ConnectSocket, (SOCKADDR*)&clientService, sizeof(clientService));
if (iResult == SOCKET_ERROR) {
    closesocket(ConnectSocket);
    printf("Unable to connect to server: %ld\n", WSAGetLastError());
    WSACleanup();
    return 1;
}

// Send an initial buffer
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR) {
    printf("send failed: %d\n", WSAGetLastError());
    closesocket(ConnectSocket);
    WSACleanup();
    return 1;
}

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("Bytes received: %d\n", iResult);
    else if (iResult == 0)
        printf("Connection closed\n");
    else
        printf("recv failed: %d\n", WSAGetLastError());

} while (iResult > 0);

// cleanup
closesocket(ConnectSocket);
WSACleanup();

return 0;
WSADATA-WSADATA;
国际结果;
SOCKET ConnectSocket=无效的_套接字;
clientService中的结构sockaddr_;
char recvbuf[默认值];
int recvbuflen=默认值;
//----------------------
//初始化Winsock
iResult=WSAStartup(MAKEWORD(2,2)和wsaData);
如果(iResult!=无错误){
printf(“WSAStartup失败:%d\n”,iResult);
返回1;
}
//----------------------
//创建用于连接到服务器的套接字
ConnectSocket=socket(AF\u INET、SOCK\u STREAM、IPPROTO\u TCP);
if(ConnectSocket==无效的_套接字){
printf(“套接字()处的错误:%ld\n”,WSAGetLastError());
WSACleanup();
返回1;
}
//----------------------
//结构中的sockaddr_指定地址族,
//要连接到的服务器的IP地址和端口。
clientService.sin_family=AF_INET;
自动ip=gethostbyname(名称);
clientService.sin_addr=*(重新解释(ip->h_addr));
clientService.sin_port=htons(默认_端口);
//----------------------
//连接到服务器。
iResult=connect(ConnectSocket,(SOCKADDR*)&clientService,sizeof(clientService));
if(iResult==SOCKET\u错误){
闭合插座(连接插座);
printf(“无法连接到服务器:%ld\n”,WSAGetLastError());
WSACleanup();
返回1;
}
//发送初始缓冲区
iResult=send(ConnectSocket,sendbuf,(int)strlen(sendbuf),0);
if(iResult==SOCKET\u错误){
printf(“发送失败:%d\n”,WSAGetLastError());
闭合插座(连接插座);
WSACleanup();
返回1;
}
printf(“发送的字节数:%ld\n”,iResult);
//由于不再发送数据,请关闭连接
iResult=关机(ConnectSocket,SD_发送);
if(iResult==SOCKET\u错误){
printf(“关闭失败:%d\n”,WSAGetLastError());
闭合插座(连接插座);
WSACleanup();
返回1;
}
//接收,直到对等方关闭连接
做{
iResult=recv(ConnectSocket,recvbuf,recvbuflen,0);
如果(iResult>0)
printf(“收到的字节数:%d\n”,iResult);
else if(iResult==0)
printf(“连接关闭\n”);
其他的
printf(“recv失败:%d\n”,WSAGetLastError());
}而(iResult>0);
//清理
闭合插座(连接插座);
WSACleanup();
返回0;

因为关闭代码是microsoft页面()的复制/粘贴-我想这就是它们表示发送已完成的方式。我相信这就解释了你的问题(从上一页):


注意发出阻塞Winsock调用(如recv)时,Winsock可能需要等待网络事件,然后才能完成调用。在这种情况下,Winsock会执行可警报的等待,这可能会被安排在同一线程上的异步过程调用(APC)中断。在中断同一线程上正在进行的阻塞Winsock调用的APC内发出另一个阻塞Winsock调用将导致未定义的行为,Winsock客户端决不能尝试


实际上,我刚刚意识到我只使用过非阻塞套接字,并且总是在自己的线程上接收代码。因此,请尝试添加以下内容: iResult=ioctlsocket(m_socket、FIONBIO和iMode)

从这里开始:


注意:从套接字接收数据的尝试大多会失败,因此您需要处理这些失败的尝试,也不希望出现死结。

我会发布一些代码,特别是您的套接字创建和接收代码。然后停止尝试手动实现HTTP,并开始使用现有的库或API,例如libcurl、WinInet/WinHTTP等,让它们为您完成所有的艰苦工作。@RemyLebeau是的,我确实使用了WinHTTP,同样的问题,最终我得到了一个超时。@Tim谢谢,我用Winsock阻止版本的代码进行了更新。如果您对WinHTTP有同样的问题,那么您在代码中做了一些根本错误的事情,或者您的网络设置有问题。此代码正是我至少三次成功从recv()获取数据返回的版本。我在以后的版本中注释掉了,但什么也没有得到。Wireshark显示,在我关闭()之后,TCP段会持续出现一段时间。