0

Hello I have an application which has a role of server in TCP connection. I use async sockets and I listen by listen() method. My question is how to listen again on the same port when client will disconnect. Now I have to quit application manually to start listening on my port. When client connect first time it's ok. Connection is working - sending from server to client. But the problem is when the same client disconnect and try to connect again. How to close proper sockets to listen again on the same port?

When there is callback FD_CLOSE I close sockets and I try to run one more time

winsock.listenOnPort(21000, windowHwnd);

But the problem is binding and SOCKET_ERROR.

bind(asyncSocket, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR

This condition is true and socket cannot be binded.

WinSockImpl class:

Constructor:

struct addrinfo *result = NULL;
WinSockImpl::WinSockImpl()
{
  WSADATA w;
  int error = WSAStartup(0x0202, &w);// Fill in WSA info
  if (error)
  {}
  if (w.wVersion != 0x0202)//Wrong Winsock version?
  {
    WSACleanup();
  }
}

Destructor:

WinSockImpl::~WinSockImpl()
{
  WSACleanup();
}

Function which listen on port:

int WinSockImpl::listenOnPort(int portno, HWND hwnd) {

  // The address structure for a TCP socket
  asyncSocket = INVALID_SOCKET;
  addr.sin_family = AF_INET;// Address family
  addr.sin_port = htons(portno);// Assign port to this socket
  addr.sin_addr.s_addr = htonl(INADDR_ANY);
  asyncSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
  // Create socket
  if (asyncSocket == INVALID_SOCKET){
    return 0; 
    //Don't continue if we couldn't create a socket!!
  }
  if (bind(asyncSocket, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
    {
      return 0;
    }

  listen(asyncSocket, SOMAXCONN);
  WSAAsyncSelect(asyncSocket, hwnd, TCP_CONNECTION_PARAMETER,FD_READ | FD_CONNECT | FD_CLOSE | FD_ACCEPT); //Switch to Non-Blocking mode
  return 1;
 }

Function which close Connection:

void WinSockImpl::closeConnection() {
  shutdown(this->asyncSocket, 1);
  closesocket(this->asyncSocket);
  //WSACleanup();
}

Main class callback:

WinSockImpl winsock; // WinSocket
#define TCP_CONNECTION_PARAMETER 1045
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
case TCP_CONNECTION_PARAMETER:
    switch (lParam) {
    case FD_CONNECT: {
        string str = "FD_CONNECT";
        startLogger->addInfo("FD_CONNECT");
        SendMessage(list_messages, LB_ADDSTRING, 0, (LPARAM)str.c_str());
        break;
    }
    case FD_CLOSE: {
        string str = "FD_CLOSE";
        startLogger->addInfo("FD_CLOSE");
        winsock.closeConnection();
        SendMessage(list_messages, LB_ADDSTRING, 0, (LPARAM)str.c_str());
        connected = false;
        //winsock = WinSockImpl();
        SetWindowText(tcp_connected, "TCP Connected: FALSE ");
        winsock.listenOnPort(21000, windowHwnd);
        break;
    }
    case FD_READ: {
        break;
    }
    case FD_ACCEPT: {
        string str = "FD_ACCEPT";
        startLogger->addInfo("FD_ACCEPT");
        SendMessage(list_messages, LB_ADDSTRING, 0, (LPARAM)str.c_str());
        int len = sizeof(winsock.addr);
        SOCKET TempSock = accept(winsock.asyncSocket, (struct sockaddr*)&winsock.addr, &len);
        winsock.asyncSocket = TempSock;
        connected = true;
        SetWindowText(tcp_connected, "TCP Connected: TRUE");
        char szAcceptAddr[100];
        wsprintf(szAcceptAddr, "Connection from [%s] accepted.",inet_ntoa(winsock.addr.sin_addr));
        SendMessage(list_messages, LB_ADDSTRING, 0, (LPARAM)szAcceptAddr);
        break;
    }
    }
    break;
default:
    return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}

Main class WinMain:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow){
windowHwnd = initWindow(hInstance);
winsock = WinSockImpl();
winsock.listenOnPort(21000, windowHwnd);
while (GetMessage(&Msg, NULL, 0, 0)>0)
{
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
}
return Msg.wParam;
}
Kutti
  • 486
  • 1
  • 6
  • 17
  • I looks like you are missing [closesocket](https://learn.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-closesocket) in your dtor. The phrasing of the question is very difficult to read =S – Chris Mc Dec 09 '18 at 16:09
  • Ok, thanks. Sorry for my english. I found a problem. In FD_ACCEPT after SOCKET TempSock = accept(winsock.asyncSocket, (struct sockaddr*)&winsock.addr, &len); I am closing the socket and assign new socket: closesocket(winsock.asyncSocket); winsock.asyncSocket = TempSock; – Kutti Dec 09 '18 at 16:18
  • Looks like you found an issue, you overwrite the server socket with the new one you accept – Chris Mc Dec 09 '18 at 16:50
  • @Kutti `asyncSocket` is your listening server socket, `TempSock` is the accepted client socket. Don't replace one with the other. Do your I/O with `TempSock`, and close it when the client disconnects, but leave `asyncSocket` open so you can call `accept()`on it again. Consider wrapping `TempSock` in a second `WinSockImpl` object of its own – Remy Lebeau Dec 09 '18 at 18:25

0 Answers0