none
Winsock close SYN_SENT状态的socket RRS feed

  • 问题

  • Hi,

    请教一下,在winsock中close一个非阻塞方式connect的socket,不会导致该socket进入CLOSE状态,这样在xp等限制half open connection数量的环境下会导致后续connect一直处于排队中,请问是什么原因?另外,winsock specification在哪里可以找到?

    十分感谢!

    2016年10月10日 3:42

答案

  • Hi MilesDong,

    当closesocket()尝试正常关闭非阻塞socket时,它将尝试创建一个工作线程来执行关闭。 工作线程将尝试通知通信通道的另一端套接字正在关闭。 如果通道的另一端无响应,则工作线程将等待超时到期; 然后做一个中止操作。

    所以最好在closesocket之前,调用shutdown或者WSASendDisconnect函数。

    详细情况参考以下文档。

    https://support.microsoft.com/en-us/kb/2770054

    Best Regards,
    Sera Yu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.

    • 已建议为答案 Baron Bi 2016年10月24日 6:06
    • 已标记为答案 Baron Bi 2016年10月24日 9:29
    2016年10月18日 9:13

全部回复

  • test code 如下:#include <stdio.h>
    #include "stdafx.h"
    #include <WinSock2.h>

    int non_block_connect(char* ip, int port);

    int _tmain(int argc, _TCHAR* argv[])
    {
        WSADATA wsaData;
        int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (iResult != NO_ERROR) {
            wprintf(L"WSAStartup function failed with error: %d\n", iResult);
            return 1;
        }
        int fds[1024];
        for (int i = 0; i < 40; ++i)
        {
            char buf[64];
            sprintf(buf, "8.8.9.%d", i);
            fds[i] = non_block_connect(buf, 80);
            printf("conn\n");
        }

        for (int i = 0; i < 40; ++i)
        {
            shutdown(fds[i], SD_BOTH);
            int ret = closesocket(fds[i]);
            printf("closesocket %d, err:%d, fd:%d\n", ret, WSAGetLastError(), fds[i]);
        }
        getchar();

        WSACleanup();
        return 0;
    }

    int non_block_connect(char* ip, int port)
    {
        //----------------------
        // Create a SOCKET for connecting to server
        SOCKET ConnectSocket;
        ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (ConnectSocket == INVALID_SOCKET) {
            wprintf(L"socket function failed with error: %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.
        sockaddr_in clientService;
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr(ip);
        clientService.sin_port = htons(port);

        u_long block = 1;
        ioctlsocket(ConnectSocket, FIONBIO, &block);

        //----------------------
        // Connect to server.
        int iResult = connect(ConnectSocket, (SOCKADDR *) & clientService, sizeof (clientService));
        if (iResult == SOCKET_ERROR) {
            wprintf(L"connect function failed with error: %ld\n", WSAGetLastError());
        }
        return ConnectSocket;
    }

    2016年10月10日 3:43
  • Hi MilesDong,

    感谢在MSDN论坛发帖。

    >>请教一下,在winsock中close一个非阻塞方式connect的socket,不会导致该socket进入CLOSE状态,这样在xp等限制half open connection数量的环境下会导致后续connect一直处于排队中,请问是什么原因?

    根据这篇文档,如果你在linger 结构体中将l_onoff 设置为非0的整数,并且 l_linger 对非阻塞方式connect的socket设置了非0的timeout, closesocket 会立即返回失败。请检查是否有这些设置。

    >>另外,winsock specification在哪里可以找到?

    可以在Microsoft's Internet server(ftp://ftp.microsoft.com/) 中找到。

    希望对你有所帮助。

    Best Regards,

    Sera Yu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.

    2016年10月10日 9:09
  • Hi Sera

    感谢您的回复。

    根据linger close的定义,linger应该只在send buffer存在数据时有效。我在上面给出了一个可以复现的代码,在代码中并没有发送任何数据,也没有开启linger close。在closesocket执行后,通过procexp工具可以看到此时进程已经关闭了所有socket句柄,单netstat中连接状态仍然处于SYN_SENT。

    另外我在测试中发现通过connectex连接的socket是可以正确关闭的。

    2016年10月11日 6:28
  • Hi MilesDong,

    当closesocket()尝试正常关闭非阻塞socket时,它将尝试创建一个工作线程来执行关闭。 工作线程将尝试通知通信通道的另一端套接字正在关闭。 如果通道的另一端无响应,则工作线程将等待超时到期; 然后做一个中止操作。

    所以最好在closesocket之前,调用shutdown或者WSASendDisconnect函数。

    详细情况参考以下文档。

    https://support.microsoft.com/en-us/kb/2770054

    Best Regards,
    Sera Yu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.

    • 已建议为答案 Baron Bi 2016年10月24日 6:06
    • 已标记为答案 Baron Bi 2016年10月24日 9:29
    2016年10月18日 9:13