0

Recently my code meet some issue. My programme work as server and listen to ONE client to connect, then send some commands to my programme. Then I will handle this command and return the value to client side. But now I got the issue accept() method will get 10093(WSANOTINITIALISED) error and seems accept() method didn't block there. It is not always happened. I tested the programme. Sometimes it works very well. Client side connected to my programme and send first command. Then my programme handle the command and send back return value. Then stopped the connection(closesocket(sClient);). Then Client side connected to my programme again and send second command...While time to time it happened accept() get 10093(WSANOTINITIALISED) error and client side will fail to connect to my programme any more. and the while loop(while (true && !m_bExitThread)) also didn't block. My questions are:

  1. Why did it happen? did someone meet the same issue? I believe my code should be correct, otherwise why most of time it works well.
  2. If this 10093 error comes, how should I handle it? Do I need to closesocket and wait for Client side connect again? or do I need to WSACleanup(); and try to start this socket Thread totally again? Below is the code. it is a thread I start it when my programme start up and stop it when programme stopped.

UINT CMainFrame::RunSocketThread()
{
        m_bExitThread = false;
        WORD wSockVersion = MAKEWORD(2, 2);
        WSADATA wsaData;
        if (WSAStartup(wSockVersion, &wsaData) != 0) // Here always success, no problem
        {
            LOGL(ILoggingSink::LogLevel::Error, _T("WSAStartup error !"));
            return 0;
        }

        SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (slisten == INVALID_SOCKET)
        {
            LOGL(ILoggingSink::LogLevel::Error, _T("socket error !"));
            return 0;
        }

        sockaddr_in stSocketAddr;
        stSocketAddr.sin_family = AF_INET;
        stSocketAddr.sin_port = htons(7700);
        stSocketAddr.sin_addr.S_un.S_addr = INADDR_ANY;
        if (bind(slisten, (LPSOCKADDR)&stSocketAddr, sizeof(stSocketAddr)) == SOCKET_ERROR)
        {
            LOGL(ILoggingSink::LogLevel::Error, _T("bind error !"));
            return 0;
        }

        if (listen(slisten, 5) == SOCKET_ERROR)
        {
            LOGL(ILoggingSink::LogLevel::Error, _T("listen error !"));
            return 0;
        }

        SOCKET sClient;
        sockaddr_in remoteAddr;
        int nAddrlen = sizeof(remoteAddr);
        char revData[255];
        while (true && !m_bExitThread)
        {
            // Waiting for connection
            sClient = accept(slisten, (SOCKADDR*)&remoteAddr, &nAddrlen);
            if (sClient == INVALID_SOCKET) // Here I can get error code 10093(WSANOTINITIALISED)
            {
                LOGL(ILoggingSink::LogLevel::Error, _T("accept error %d!"), WSAGetLastError());
                continue;
            }

            // revice data
            int ret = recv(sClient, revData, 255, 0);
            if (ret > 0)
            {
                revData[ret] = 0x00;
                ParseJsonCommand(revData);
            }

            // send data
            // Here I wait for programme finished handling the income command and return a value, otherwise just sleep and wait
            while (CmdLineInfo::m_eReturn == ReturnTypeEnum::kNull)
            {
                Sleep(100);
            }
            const char* sendData;
            CString strData;
            strData = "{\"Command\":\"";
            strData += CmdLineInfo::s_sLFODCommandName;
            strData += "\", \"ReturnValue\":\"";
            if(CmdLineInfo::m_eReturn == ReturnTypeEnum::kSuccess)
                strData +="1\"} "; 
            else
                strData += "0\"} ";

            CStringA strAData(strData);
            sendData = strAData;
            send(sClient, sendData, strlen(sendData), 0);
            closesocket(sClient);
        }

        closesocket(slisten);
        WSACleanup();
        return 0;

}
drescherjm
  • 10,365
  • 5
  • 44
  • 64
Penny
  • 606
  • 1
  • 7
  • 15
  • Unrelated future bug: In `int ret = recv(sClient, revData, 255, 0);`, `ret` can contain more information than merely the number of bytes read. On 0, connection closed. On <0 an error has occurred.. It's important to candle all of the cases. – user4581301 Aug 08 '22 at 14:48
  • 2
    You solve WSA NOT INITIALISED by initialising WSA. Since it worked one time - did the program perhaps call WSACleanup before it called accept? – user253751 Aug 08 '22 at 14:49
  • 2
    `CMainFrame::RunSocketThread()` Do you run several threads? *In a multithreaded environment, `WSACleanup` terminates Windows Sockets operations for all threads.* – 273K Aug 08 '22 at 14:50
  • 1
    Generally you should call `WSAStartup` once at the beginning of the program and `WSACleanup` once at the end. I make a simple [RAII wrapper class](https://stackoverflow.com/q/2321511/4581301 that calls `WSAStartup` in the constructor and `WSACleanup` in the destructor then have a single instance somewhere with sufficiently wide scope. – user4581301 Aug 08 '22 at 14:55
  • @273K maybe you are correct. That is the reason that I got 10093 error. Actually in this Thread RunSocketThread() I will invoke another socket thread(ParseJsonCommand(revData);) to send data to client side. In thread ParseJsonCommand(), time to time I will invoke WSAStartup/WSACleanup to re-establish the connection. So it means if WSACleanup actually terminates all threads' socket, then the socket in RunSocketThread() also be terminated. right? – Penny Aug 08 '22 at 23:08
  • 1
    @Penny According to the Doc:[WSACleanup function (winsock.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsacleanup) When WSACleanup is called, any pending blocking or asynchronous Windows Sockets calls issued by any thread in this process are canceled without posting any notification messages or without signaling any event objects. – Jeaninez - MSFT Aug 09 '22 at 07:03

0 Answers0