采用事件选择Socket模型,为什么有时候会出现客户端发数据服务器端收不到的现象?

时间:2021-02-12 19:55:49
采用事件选择Socket模型,为什么有时候会出现客户端发数据服务器端收不到的现象?

现象:
  1.客户端连接服务器一切正常
  2.服务器端发送数据到客户端正常
  3.客户端发送数据到服务器端时,发送数据正常,但服务器端有时候会收不到

9 个解决方案

#1


没有人知道怎么解决吗?

#2


up

#3


首先:
检查你的客户端发送代码:你是否检查了send的返回值
其次:
检查服务端:是否有缓冲区溢出的问题

#4


把code贴出来,是不是有死锁呀!

#5


up

#6


因为代码比较多,我在这里只能够贴出一部分代码,如果想看全部代码的朋友
下面地址下载:
http://j16.103.cn/temp/ANetworking.rar
http://j16.103.cn/temp/NetTest.rar

#7


//--------------------------------------------
// 处理客户连接数据(线程)
//--------------------------------------------
DWORD ATcpServer::DumpConnection()
{
HANDLE hEvents[2] = {m_eventStop[0],m_eventConnection};
WSANETWORKEVENTS wnes;
CClient client;

while(1)
{
DWORD dwResult = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);

// 服务停止或操作失败,退出关闭线程
if( dwResult==(DWORD)-1 || 
dwResult==WAIT_OBJECT_0)
{
break;
}
// 无效事件
if(dwResult!=WAIT_OBJECT_0+1)
{
continue;
}
WSAEnumNetworkEvents(m_winSocket.m_hSocket,m_eventConnection,&wnes);

//----------------------
// 处理连接请求
//----------------------
if(wnes.lNetworkEvents & FD_ACCEPT)
{
DWORD dwIp;
  VARIANT_BOOL bAccept = FALSE;
sockaddr_in rsockaddr;
int namelen = sizeof( rsockaddr );

// 接收请求,建立连接
if( m_winSocket.Accept(m_winSocket.m_hSocket, &client.s_client) == SOCKET_ERROR )
{
continue;
}
if( getpeername( client.s_client, (SOCKADDR*)&rsockaddr, &namelen ) == SOCKET_ERROR )
{
m_winSocket.Close(client.s_client);
continue;
}
// 最大能有(MAX_CONNECT)个连接
if(m_ClientList.GetCount()>MAX_CONNECT)
{
m_winSocket.Close(client.s_client);
continue;
}
// 触发接收事件,如果返回FALSE值,则断开刚才建立的连接
dwIp = rsockaddr.sin_addr.S_un.S_addr;
_IATcpServerEvents_Accept(dwIp,&bAccept);
if(!bAccept)
{
m_winSocket.Close(client.s_client);
continue;
}
// 获取客户端参数,填充client对象
client.strClientIp = inet_ntoa(rsockaddr.sin_addr);

//char sztmp[_MAX_PATH];
//memset(sztmp,0,sizeof(sztmp));
//if(m_winSocket.get_RemoteHost(sztmp,nMaxLen)==S_OK)
//{
// client.strClientHost = sztmp;
//}

// 设置Socket事件
int i=0,j=0;
// 客户端Socket,跟事件一一对应
for(i=0;i<ClientThreadCount;i++)
for(j=0;j<MaxClientInThread;j++)
if(m_sockClients[i][j]==NULL) goto FindNull;

FindNull:

ATLASSERT(i<ClientThreadCount);
ATLASSERT(j<MaxClientInThread);

WSAEVENT clientevent = m_eventClients[i][j];
if(m_winSocket.eventSelect(clientevent,FD_READ|FD_WRITE|FD_CLOSE)!=ERR_SUCCESS)
{
closesocket(client.s_client);
continue;
}
m_sockClients[i][j] = client.s_client;

// 添加客户端到连接列表,并激发Connected事件
client.SetNewId();
m_ClientList.AddHead(client);
_IATcpServerEvents_Connected(client);
}
//----------------------
// 连接Socket被意外关闭
//----------------------
if(wnes.lNetworkEvents & FD_CLOSE)
{
break;
}
}

for(int i=0;i<ClientThreadCount;i++)
for(int j=0;j<MaxClientInThread;j++)
{
WSAResetEvent(m_eventClients[i][j]);
m_sockClients[i][j]=NULL; // 客户端Socket,跟事件一一对应
}
SetEvent(m_eventStoped[0]);
return 0;
}

//--------------------------------------------
// 处理客户连接数据(线程)
//--------------------------------------------
DWORD ATcpServer::DumpClients(int id)
{
WSAEVENT hEvents[MaxClientInThread+1] = {m_eventStop[id+1]};
memcpy(&(hEvents[1]),(void*)m_eventClients[id],sizeof(HANDLE)*MaxClientInThread);

WSANETWORKEVENTS wnes;

while(1)
{
DWORD dwResult = WSAWaitForMultipleEvents(MaxClientInThread+1,hEvents,FALSE,WSA_INFINITE,FALSE);

// 服务停止或操作失败,退出关闭线程
if( dwResult==(DWORD)-1 || 
dwResult==WAIT_OBJECT_0)
{
break;
}
SOCKET s = m_sockClients[id][dwResult-WAIT_OBJECT_0-1];
WSAEnumNetworkEvents(s,hEvents[dwResult],&wnes);
//WSAResetEvent(hEvents[dwResult]);

CClient client;
POSITION pos = m_ClientList.GetHeadPosition();
while( pos != NULL )
{
const CClient& cli = m_ClientList.GetNext(pos);
if( cli.s_client == s )
{
client = cli;
break;
}
}

//--------------------
// 处理客户端关闭事件
//--------------------
if(wnes.lNetworkEvents & FD_CLOSE)
{
if(client != long(-1))
{
_IATcpServerEvents_Disconnected(client,0);
HRESULT hr;
DisconnectClient(client,&hr);
// 更新Socket列表
m_sockClients[id][dwResult-WAIT_OBJECT_0-1]=NULL;
}
}
//--------------------
// 接收客户端数据处理
//--------------------
if(wnes.lNetworkEvents & FD_READ)
{
m_csRecv.Lock();
int nret = m_winSocket.Receive(s,(char*)m_pRecvBuf,MAX_RECV_BUF);
if(nret>10) // 数据包最少是10字节
{
BYTE *p = m_pRecvBuf;
NET_PACK_HEAD nph;
while(p-m_pRecvBuf<nret)
{
memcpy(&nph,p,sizeof(NET_PACK_HEAD));
p+=sizeof(NET_PACK_HEAD);
if(int(p+nph.nLen+1-m_pRecvBuf)>nret)
break;

DumpRecvData(client,nph,p);

p+=(nph.nLen+1);
}
}
m_csRecv.Unlock();
}
}
SetEvent(m_eventStoped[id+1]);
return 0;
}

#8


问题出在服务端,检查服务断的代码。。

#9


客户端send返回成功.
如果客户端在连接成功后第一次发送数据服务器接收成功的话,那在以后发送操作服务器都将可以接收得到.
但如果第一次发送服务器接收失败,无论客户端send多少次,服务器的将再也收不到数据.

xiaohyy(醉大饿极),能帮我看看究竟是哪出问题了吗?我实在找不到原因了

#1


没有人知道怎么解决吗?

#2


up

#3


首先:
检查你的客户端发送代码:你是否检查了send的返回值
其次:
检查服务端:是否有缓冲区溢出的问题

#4


把code贴出来,是不是有死锁呀!

#5


up

#6


因为代码比较多,我在这里只能够贴出一部分代码,如果想看全部代码的朋友
下面地址下载:
http://j16.103.cn/temp/ANetworking.rar
http://j16.103.cn/temp/NetTest.rar

#7


//--------------------------------------------
// 处理客户连接数据(线程)
//--------------------------------------------
DWORD ATcpServer::DumpConnection()
{
HANDLE hEvents[2] = {m_eventStop[0],m_eventConnection};
WSANETWORKEVENTS wnes;
CClient client;

while(1)
{
DWORD dwResult = WaitForMultipleObjects(2,hEvents,FALSE,INFINITE);

// 服务停止或操作失败,退出关闭线程
if( dwResult==(DWORD)-1 || 
dwResult==WAIT_OBJECT_0)
{
break;
}
// 无效事件
if(dwResult!=WAIT_OBJECT_0+1)
{
continue;
}
WSAEnumNetworkEvents(m_winSocket.m_hSocket,m_eventConnection,&wnes);

//----------------------
// 处理连接请求
//----------------------
if(wnes.lNetworkEvents & FD_ACCEPT)
{
DWORD dwIp;
  VARIANT_BOOL bAccept = FALSE;
sockaddr_in rsockaddr;
int namelen = sizeof( rsockaddr );

// 接收请求,建立连接
if( m_winSocket.Accept(m_winSocket.m_hSocket, &client.s_client) == SOCKET_ERROR )
{
continue;
}
if( getpeername( client.s_client, (SOCKADDR*)&rsockaddr, &namelen ) == SOCKET_ERROR )
{
m_winSocket.Close(client.s_client);
continue;
}
// 最大能有(MAX_CONNECT)个连接
if(m_ClientList.GetCount()>MAX_CONNECT)
{
m_winSocket.Close(client.s_client);
continue;
}
// 触发接收事件,如果返回FALSE值,则断开刚才建立的连接
dwIp = rsockaddr.sin_addr.S_un.S_addr;
_IATcpServerEvents_Accept(dwIp,&bAccept);
if(!bAccept)
{
m_winSocket.Close(client.s_client);
continue;
}
// 获取客户端参数,填充client对象
client.strClientIp = inet_ntoa(rsockaddr.sin_addr);

//char sztmp[_MAX_PATH];
//memset(sztmp,0,sizeof(sztmp));
//if(m_winSocket.get_RemoteHost(sztmp,nMaxLen)==S_OK)
//{
// client.strClientHost = sztmp;
//}

// 设置Socket事件
int i=0,j=0;
// 客户端Socket,跟事件一一对应
for(i=0;i<ClientThreadCount;i++)
for(j=0;j<MaxClientInThread;j++)
if(m_sockClients[i][j]==NULL) goto FindNull;

FindNull:

ATLASSERT(i<ClientThreadCount);
ATLASSERT(j<MaxClientInThread);

WSAEVENT clientevent = m_eventClients[i][j];
if(m_winSocket.eventSelect(clientevent,FD_READ|FD_WRITE|FD_CLOSE)!=ERR_SUCCESS)
{
closesocket(client.s_client);
continue;
}
m_sockClients[i][j] = client.s_client;

// 添加客户端到连接列表,并激发Connected事件
client.SetNewId();
m_ClientList.AddHead(client);
_IATcpServerEvents_Connected(client);
}
//----------------------
// 连接Socket被意外关闭
//----------------------
if(wnes.lNetworkEvents & FD_CLOSE)
{
break;
}
}

for(int i=0;i<ClientThreadCount;i++)
for(int j=0;j<MaxClientInThread;j++)
{
WSAResetEvent(m_eventClients[i][j]);
m_sockClients[i][j]=NULL; // 客户端Socket,跟事件一一对应
}
SetEvent(m_eventStoped[0]);
return 0;
}

//--------------------------------------------
// 处理客户连接数据(线程)
//--------------------------------------------
DWORD ATcpServer::DumpClients(int id)
{
WSAEVENT hEvents[MaxClientInThread+1] = {m_eventStop[id+1]};
memcpy(&(hEvents[1]),(void*)m_eventClients[id],sizeof(HANDLE)*MaxClientInThread);

WSANETWORKEVENTS wnes;

while(1)
{
DWORD dwResult = WSAWaitForMultipleEvents(MaxClientInThread+1,hEvents,FALSE,WSA_INFINITE,FALSE);

// 服务停止或操作失败,退出关闭线程
if( dwResult==(DWORD)-1 || 
dwResult==WAIT_OBJECT_0)
{
break;
}
SOCKET s = m_sockClients[id][dwResult-WAIT_OBJECT_0-1];
WSAEnumNetworkEvents(s,hEvents[dwResult],&wnes);
//WSAResetEvent(hEvents[dwResult]);

CClient client;
POSITION pos = m_ClientList.GetHeadPosition();
while( pos != NULL )
{
const CClient& cli = m_ClientList.GetNext(pos);
if( cli.s_client == s )
{
client = cli;
break;
}
}

//--------------------
// 处理客户端关闭事件
//--------------------
if(wnes.lNetworkEvents & FD_CLOSE)
{
if(client != long(-1))
{
_IATcpServerEvents_Disconnected(client,0);
HRESULT hr;
DisconnectClient(client,&hr);
// 更新Socket列表
m_sockClients[id][dwResult-WAIT_OBJECT_0-1]=NULL;
}
}
//--------------------
// 接收客户端数据处理
//--------------------
if(wnes.lNetworkEvents & FD_READ)
{
m_csRecv.Lock();
int nret = m_winSocket.Receive(s,(char*)m_pRecvBuf,MAX_RECV_BUF);
if(nret>10) // 数据包最少是10字节
{
BYTE *p = m_pRecvBuf;
NET_PACK_HEAD nph;
while(p-m_pRecvBuf<nret)
{
memcpy(&nph,p,sizeof(NET_PACK_HEAD));
p+=sizeof(NET_PACK_HEAD);
if(int(p+nph.nLen+1-m_pRecvBuf)>nret)
break;

DumpRecvData(client,nph,p);

p+=(nph.nLen+1);
}
}
m_csRecv.Unlock();
}
}
SetEvent(m_eventStoped[id+1]);
return 0;
}

#8


问题出在服务端,检查服务断的代码。。

#9


客户端send返回成功.
如果客户端在连接成功后第一次发送数据服务器接收成功的话,那在以后发送操作服务器都将可以接收得到.
但如果第一次发送服务器接收失败,无论客户端send多少次,服务器的将再也收不到数据.

xiaohyy(醉大饿极),能帮我看看究竟是哪出问题了吗?我实在找不到原因了