退出阻塞的recv()调用

时间:2015-04-20 00:56:03

标签: c sockets winsock

我想退出阻止recv()来电。基于此question,我应该执行以下操作:

shutdown(s, SD_RECEIVE);

但它不起作用,recv()仍在阻止!


修改

这是我使用的代码:

#include <stdio.h>
#include <WinSock2.h>
#include <Windows.h>
#include <process.h>
#pragma comment(lib, "ws2_32.lib")

unsigned int __stdcall recvThread(void *p)
{
    SOCKET s = *((SOCKET*)p);

    char buffer[2048];
    int size;

    do
    {
        size = recv(s, buffer, 2048, 0);

        if (size > 0)                               
        {
            printf("Some data received\n");
        }
        else if (size == 0)
        {
            printf("Disconnected\n");
        }
        else
        {
            printf("Disconnected, error occured\n");
        }

    } while (size > 0);

    return 0;
}

int main()
{
    // Initialize Winsock
    WSADATA wsa;
    WSAStartup(MAKEWORD(2, 2), &wsa);

    // Create socket
    SOCKET s = socket(AF_INET, SOCK_STREAM, 0);

    // Connect
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("192.168.1.4");
    addr.sin_port = htons(atoi("12345"));
    if (connect(s, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
    {
        printf("Unable to connect\n");
    }
    else
    {
        printf("Connected\n");
    }

    // Start recv() thread
    HANDLE hRecvThread = (HANDLE)_beginthreadex(0, 0, recvThread, &s, 0, 0);

    Sleep(3000);

    // Exit blocking recv()
    shutdown(s, SD_RECEIVE);

    getchar();
    return 0;
}

1 个答案:

答案 0 :(得分:1)

您需要按照链接到的问题中提到的方式关闭输入。 请参阅msdn上的shutdown()文档以及此处:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms738547%28v=vs.85%29.aspx

文件中的相关引用:

  

关闭功能用于所有类型的插座,以禁用接收,传输或两者兼而有之   如果how参数是SD_RECEIVE,则不允许对套接字上的recv函数进行后续调用。这对较低协议层没有影响。对于TCP套接字,如果仍有等待接收的套接字上排队的数据,或者数据随后到达,则重置连接,因为无法将数据传递给用户。对于UDP套接字,接受传入的数据报并排队。在任何情况下都不会生成ICMP错误包   如果how参数是SD_SEND,则不允许后续调用send函数。对于TCP套接字,在接收方发送并确认所有数据后,将发送FIN   如上所述,设置SD_BOTH如何禁用发送和接收。

关键是发送FIN。这将由服务器处理,它将关闭套接字,导致你的recv()调用返回。