一个项目,server是用vc做的,程序运行后,第一次accept()成功,但客户端断开连接后重新连接的时候accept返回的是无效的socket,而别人用dephi做的客户端却显示连接成功.
server代码如下:
BOOL CMainFrame::InitNet()
{
char buf[200];
::GetCurrentDirectory(200,buf);
strcat(buf,"\\set.ini");
int nPort=GetPrivateProfileInt("Net Set","Net Port",0,buf); WSACleanup();
WSADATA wsaData;
int iErrorCode;
if (WSAStartup(MAKEWORD(2,1),&wsaData)) //调用Windows Sockets DLL
{
AddToDataList(IDC_ALARMDATA_LIST,"Winsock无法初始化!");
WSACleanup();
return FALSE;
} AddToDataList(IDC_ALARMDATA_LIST,"服务器开始创建SOCKET。");
closesocket(Client);
closesocket(sendClient[0]);
closesocket(sendClient[1]);
closesocket(ServerSocket);
BOOL optval = TRUE;
int err = setsockopt(ServerSocket,SOL_SOCKET,SO_REUSEADDR,(char *)&optval, sizeof(int));
ServerSocket=socket(PF_INET,SOCK_STREAM,0); //创建服务器端Socket,类型为SOCK_STREAM,面向连接的通信 if(ServerSocket == INVALID_SOCKET)
{
AddToDataList(IDC_ALARMDATA_LIST,"无法创建服务器socket!");
return FALSE;
} m_sockServerAddr.sin_family = AF_INET;
m_sockServerAddr.sin_addr.s_addr = INADDR_ANY; //向所有的IP地址发送消息
m_sockServerAddr.sin_port = htons(nPort);
if (bind(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,sizeof(m_sockServerAddr)) == SOCKET_ERROR) //与选定的端口绑定
{
return FALSE;
} AddToDataList(IDC_ALARMDATA_LIST,"服务器端口:8001."); iErrorCode=WSAAsyncSelect(ServerSocket,m_hWnd,WM_CLIENT_ACCEPT,FD_ACCEPT);
// 产生相应传递给窗口的消息为WM_SERVER_ACCEPT ,这是自定义消息 if (iErrorCode == SOCKET_ERROR)
{
return FALSE;
}
if (listen(ServerSocket,5) == SOCKET_ERROR) //开始监听客户连接请求
{
return FALSE;
}
bInited=TRUE;
AddToDataList(IDC_ALARMDATA_LIST,"服务器绑定监听成功。");
return TRUE;
}
接收函数:
LRESULT CMainFrame::OnAccept(WPARAM wParam, LPARAM lParam)
{
if (WSAGETSELECTERROR(lParam))
{
return 0L;
}
if(WSAGETSELECTEVENT(lParam) == FD_ACCEPT)//如果
{
SOCKADDR_IN client_addr;
ZeroMemory(&client_addr, sizeof(client_addr));
Client = accept(ServerSocket,(LPSOCKADDR)&client_addr,0);
if (Client == INVALID_SOCKET)
{
return 0L;
}
WSAAsyncSelect(Client,m_hWnd,WM_CLIENT_READCLOSE,FD_READ|FD_CLOSE|FD_OOB|FD_CONNECT);//|FD_QOS|FD_GROUP_QOS|FD_ROUTING_INTERFACE_CHANGE|FD_ADDRESS_LIST_CHANGE);
}
return 0L;
}
关闭连接函数:
LRESULT CMainFrame::OnReadClose(WPARAM wParam, LPARAM lParam)
{
switch (WSAGETSELECTEVENT(lParam))
{
case FD_READ:
break;
case FD_WRITE:
AddToDataList(IDC_ALARMDATA_LIST,"FD_WRITE");
break;
case FD_ACCEPT:
AddToDataList(IDC_ALARMDATA_LIST,"FD_ACCEPT");
break;
case FD_OOB:
AddToDataList(IDC_ALARMDATA_LIST,"FD_OOB");
break;
case FD_CONNECT:
AddToDataList(IDC_ALARMDATA_LIST,"FD_CONNECT");
break;
case FD_CLOSE:
shutdown(Client,2);
closesocket(Client);
break;
}
return 0L;
}
server代码如下:
BOOL CMainFrame::InitNet()
{
char buf[200];
::GetCurrentDirectory(200,buf);
strcat(buf,"\\set.ini");
int nPort=GetPrivateProfileInt("Net Set","Net Port",0,buf); WSACleanup();
WSADATA wsaData;
int iErrorCode;
if (WSAStartup(MAKEWORD(2,1),&wsaData)) //调用Windows Sockets DLL
{
AddToDataList(IDC_ALARMDATA_LIST,"Winsock无法初始化!");
WSACleanup();
return FALSE;
} AddToDataList(IDC_ALARMDATA_LIST,"服务器开始创建SOCKET。");
closesocket(Client);
closesocket(sendClient[0]);
closesocket(sendClient[1]);
closesocket(ServerSocket);
BOOL optval = TRUE;
int err = setsockopt(ServerSocket,SOL_SOCKET,SO_REUSEADDR,(char *)&optval, sizeof(int));
ServerSocket=socket(PF_INET,SOCK_STREAM,0); //创建服务器端Socket,类型为SOCK_STREAM,面向连接的通信 if(ServerSocket == INVALID_SOCKET)
{
AddToDataList(IDC_ALARMDATA_LIST,"无法创建服务器socket!");
return FALSE;
} m_sockServerAddr.sin_family = AF_INET;
m_sockServerAddr.sin_addr.s_addr = INADDR_ANY; //向所有的IP地址发送消息
m_sockServerAddr.sin_port = htons(nPort);
if (bind(ServerSocket,(LPSOCKADDR)&m_sockServerAddr,sizeof(m_sockServerAddr)) == SOCKET_ERROR) //与选定的端口绑定
{
return FALSE;
} AddToDataList(IDC_ALARMDATA_LIST,"服务器端口:8001."); iErrorCode=WSAAsyncSelect(ServerSocket,m_hWnd,WM_CLIENT_ACCEPT,FD_ACCEPT);
// 产生相应传递给窗口的消息为WM_SERVER_ACCEPT ,这是自定义消息 if (iErrorCode == SOCKET_ERROR)
{
return FALSE;
}
if (listen(ServerSocket,5) == SOCKET_ERROR) //开始监听客户连接请求
{
return FALSE;
}
bInited=TRUE;
AddToDataList(IDC_ALARMDATA_LIST,"服务器绑定监听成功。");
return TRUE;
}
接收函数:
LRESULT CMainFrame::OnAccept(WPARAM wParam, LPARAM lParam)
{
if (WSAGETSELECTERROR(lParam))
{
return 0L;
}
if(WSAGETSELECTEVENT(lParam) == FD_ACCEPT)//如果
{
SOCKADDR_IN client_addr;
ZeroMemory(&client_addr, sizeof(client_addr));
Client = accept(ServerSocket,(LPSOCKADDR)&client_addr,0);
if (Client == INVALID_SOCKET)
{
return 0L;
}
WSAAsyncSelect(Client,m_hWnd,WM_CLIENT_READCLOSE,FD_READ|FD_CLOSE|FD_OOB|FD_CONNECT);//|FD_QOS|FD_GROUP_QOS|FD_ROUTING_INTERFACE_CHANGE|FD_ADDRESS_LIST_CHANGE);
}
return 0L;
}
关闭连接函数:
LRESULT CMainFrame::OnReadClose(WPARAM wParam, LPARAM lParam)
{
switch (WSAGETSELECTEVENT(lParam))
{
case FD_READ:
break;
case FD_WRITE:
AddToDataList(IDC_ALARMDATA_LIST,"FD_WRITE");
break;
case FD_ACCEPT:
AddToDataList(IDC_ALARMDATA_LIST,"FD_ACCEPT");
break;
case FD_OOB:
AddToDataList(IDC_ALARMDATA_LIST,"FD_OOB");
break;
case FD_CONNECT:
AddToDataList(IDC_ALARMDATA_LIST,"FD_CONNECT");
break;
case FD_CLOSE:
shutdown(Client,2);
closesocket(Client);
break;
}
return 0L;
}
解决方案 »
- Navigate2打开本地html 同时可以穿参数给html吗?
- 多文档 子窗口打开时最大化的问题。视图用的FormView
- 一个小问题
- 结构体能不能有构造函数?
- 关于ODBC打开数据库的问题,在线等
- 就目前的市场情况来看,学C++后从事哪个方向的开发会好一点,作什么样的结构开发;另外想对MSDN作一些了解
- 是我没说明白?征求意见!
- 为什么我通过GetWindow 不能得到mdi的子窗口,但是能得到MDI客户区中DockBar窗口指针
- Linux 网络编程
- 可以在工具栏绘图 或 设置字体颜色吗?
- 怎么实现打印CFromView派生的一部分区域,或者怎么打印出整个CFromView,有没有简单的方法
- 怎么把VARIANT中的数组元素提取出来
SOCKADDR_IN client_addr;
ZeroMemory(&client_addr, sizeof(client_addr));
Client = accept(ServerSocket,(LPSOCKADDR)&client_addr,0);
改为
SOCKADDR_IN client_addr;
int addrlen = sizeof(SOCKADDR_IN );
ZeroMemory(&client_addr, sizeof(client_addr));
Client = accept(ServerSocket,(LPSOCKADDR)&client_addr,&addrlen ); case FD_CLOSE:
shutdown(Client,2);
closesocket(Client);
改为
case FD_CLOSE:
closesocket(Client);
另外每次新创建一个SOCKET来接受连接,不要用原来的那个。自己维护一个SOCKET的队列。
closesocket(Client);Client从哪里来的
是类成员吧
如果这样,那这个服务端只能有一个客房端连上来
同时有两个连上的话会出现问题
如果没有,则肯定不会调用closesocket函数了
还有,你的程序同时只能有一个客户端连上来
建议你把不必要的东西去掉,不必要的网络消息不要注册。从最简单作起,慢慢添加功能。
在下次连接时,是否仍用同一套接字,是否为空
调用closesocket函数后,应将其置空(NULL),下次连接时判断连接是否有效。
再试试。