基于TCP的远程算术程序,使用非阻塞socket。//服务器发送线程
DWORD WINAPI CClient::SendThread(void *pParam)
{
CClient *pClient=(CClient *)pParam; while(pClient->m_isConnected)
{
if(WAIT_OBJECT_0==WaitForSingleObject(pClient->m_hSendEvent,INFINITE))       //等待发送事件
{
if(!pClient->m_isConnected)           //如果连接断开
{
pClient->m_isConnected=false;
break;
} int retval=send(pClient->m_socket,pClient->m_sendData.buf,((pHdr)pClient->m_sendData.buf)->len,0); if(retval==SOCKET_ERROR)            //发送失败
{
int ErrCode=WSAGetLastError();
if(ErrCode==WSAEWOULDBLOCK)
continue;
else if(ErrCode==WSAENETDOWN || ErrCode==WSAECONNRESET || ErrCode==WSAETIMEDOUT)
{
pClient->m_isConnected=false;
pClient->m_isExit=true;
break;
}
} ResetEvent(pClient->m_hSendEvent);        //重置发送事件
}
} return 0;
}
//客户端接收线程
DWORD WINAPI RecvThread(void *pParam)
{
char temp[MAX_BUF_SIZE];           //临时接收缓冲区
memset(temp,0,MAX_BUF_SIZE);
int ival; while(g_isConnected)
{
ival=recv(g_sClient,temp,MAX_BUF_SIZE,0);
if(ival==SOCKET_ERROR)                //接收失败
{
int ErrCode=WSAGetLastError();
if(ErrCode==WSAEWOULDBLOCK)
{
Sleep(500);
continue;
}
else
{
g_isConnected=false;
SetEvent(g_hShowResultEvent);
break;
}
}
else if(ival==0)              //连接关闭
{
g_isConnected=false;
SetEvent(g_hShowResultEvent);
break;
}
else if(ival>HEADERLEN)        //接收成功
{
                        //将接收到的数据解包并拷贝到全局的接收缓冲区中
pHdr pHeader=(pHdr)temp;
memset(g_RecvBuf.buf,0,MAX_BUF_SIZE);
memcpy(g_RecvBuf.buf,temp+HEADERLEN,pHeader->len-HEADERLEN); SetEvent(g_hShowResultEvent);      //通知显示计算结果
} memset(temp,0,MAX_BUF_SIZE);
Sleep(500);
} SetEvent(g_hSendEvent);          //线程退出时设置发送事件为有信号状态,以防发送线程一直等待 return 0;
}测试远程计算1+1=?
问题:经调试发现,服务器发送线程发送的数据包是正确的,其中包头内类型字段值为“E”(算术表达式),长度(包头+数据的总长度)字段为13,包体的数据为“1+1=2”。
而客户端接收到的数据包却完全不一样,调试得知接收到的数据包包头内类型字段值为“D”(未定义这种类型),长度字段为2734738122,包体的数据为“g◆弨螮”。并且接收到的数据长度为29字节,不是发送的13字节!
请问这是什么原因?

解决方案 »

  1.   

    看看send和recv的返回值是多少?正确吗?
      

  2.   

    可能发丢包了 用SELECT模型判断一下缓冲区是否可写
      

  3.   

    1.把receive/send buffer加长
    2.定义好讯息格式,用多次接收然后解析讯息的方式处理(长度判断,或结尾字串都可)
      

  4.   

    send的返回值是13,recv的返回值是29。
      

  5.   

    这个跟buffer长度没关系吧?我定义的发送和接收buffer都远大于实际数据包大小(buffer大小为48,而一般正常的算术表达式在10-30之间)
      

  6.   

    终于发现问题所在了!
    我跟踪调试Client程序,发现接收到的数据开头都是“Drcom...(后面还有一段乱码)”,直到第18个字节开始才是正常发送的数据(包头类型“E”,包头长度13,数据“1+1=2”)。想到“Drcom”这些字符与学校上网认证客户端名字Dr.com一样,是不是接收了Dr.com的数据了?马上关掉Dr.com,重新测试服务器和客户端,一切正确。但是又有了一个疑问,为什么Dr.com会影响我的程序呢?好像Dr.com安装时还附带安装了一个抓包的工具WinPcap,可能是它把网卡设为了“混杂模式”导致的,但是怎么其他的软件(如QQ)就不受影响呢?