Winsock сервер, как переслушивать на тот же порт - PullRequest
0 голосов
/ 09 декабря 2018

Здравствуйте, у меня есть приложение, которое играет роль сервера в TCP-соединении.Я использую асинхронные сокеты и слушаю методом listen ().Мой вопрос заключается в том, как снова прослушивать тот же порт, когда клиент отключится.Теперь мне нужно выйти из приложения вручную, чтобы начать прослушивание через мой порт.Когда клиент подключается в первый раз, все в порядке.Соединение работает - отправка с сервера на клиент.Но проблема в том, когда тот же клиент отключается и пытается подключиться снова.Как закрыть правильные сокеты для повторного прослушивания на том же порту?

Когда есть обратный вызов FD_CLOSE, я закрываю сокеты и пытаюсь запустить еще раз

winsock.listenOnPort(21000, windowHwnd);

Но проблема связана сSOCKET_ERROR.

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

Это условие истинно и сокет не может быть связан.

Класс WinSockImpl:

Конструктор:

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();
  }
}

Деструктор:

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

Функция, которая прослушивает порт:

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;
 }

Функция, которая закрывает соединение:

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

Обратный вызов основного класса:

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;
}

Основной класс 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;
}
...