Здравствуйте, у меня есть приложение, которое играет роль сервера в 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;
}