您好,我有一个在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;
}