用socket分包传输数据,只有第一个包能收到,后面的数据包都丢失了,但是在本机上同时运行server端和client端来分包传输数据却没有问题,请问这是怎么回事?以下是分包发送的代码。
SendMsg(BYTE* vIn,DWORD vLen)
{
WaitForSingleObject(m_hSendSema,INFINITE); BYTE  senddata[65535];
SocketMsgHead*  head = (SocketMsgHead*)senddata;
head->ucQxFrameHead = 0x7E;
head->dwTotalLen = vLen;
head->wPacketNum = 1; 
head->wPacketNO = 1;
head->wQxFrameLen = vLen;
if(vLen<=1024*60)
{
memcpy(senddata+sizeof(SocketMsgHead),vIn,vLen);
if(m_LinkState == TRUE)
{
if(Send(senddata,vLen+sizeof(SocketMsgHead)) == 0) 
{
m_LinkState = FALSE;
}
}
}///
else  //拆包发送
{
int i= 0;
head->wPacketNum = vLen/(1024*60) +1;
head->wQxFrameLen = 1024*60;
        for(i=0;i<vLen/(1024*60);i++)
{
head->wPacketNO = i+1;
memcpy(senddata+sizeof(SocketMsgHead),vIn + i*1024*60,1024*60);
if(m_LinkState == TRUE)

if(Send(senddata,1024*60+sizeof(SocketMsgHead)) == 0)
{
m_LinkState = FALSE;
}
else
{
// Sleep(100);
continue;
}
}

} ///for 
////下面发送最后一包

head->wPacketNO = i+1;
head->wQxFrameLen = vLen-i*1024*60;
memcpy(senddata+sizeof(SocketMsgHead),vIn + i*1024*60,vLen-i*1024*60);
Send(senddata,vLen-i*1024*60+sizeof(SocketMsgHead));
}
ReleaseSemaphore(m_hSendSema,1,NULL);
}

解决方案 »

  1.   

    if(vLen<=1024*60) 60K做为分包大小?在网络中一次不一定能成功发送,需要检查send的返回值,以便得到到底发了多少数据。hSendSema在这里有什么用?它有没有只要能造成死锁?
      

  2.   

    Send的返回值我检测过,是都发送成功了的。m_hSendSema只在这个函数中用到,应该不会造成死锁。是不是只要Send发送成功的话,OnReceive就能收到数据?
      

  3.   

    //向客户端发送数据的函数。
    int SendInfo(SOCKET m_fsocket,char *buffer,int len)
    {
    int cnt;
    int rc;
    cnt=len;
    while(cnt>0)
    {
    rc=send(m_fsocket,buffer,cnt,0);
    if(rc==SOCKET_ERROR)
    {
    AfxMessageBox("发送数据失败!");
    return -1;
    }
    if(rc==0)
    return len-cnt;
    //发送完了一批数据后,缓冲区指针当然要向后移了。如果指定数量的数据已经发送完了,则
    //bp就指向缓冲区的末尾了。
    buffer+=rc;
    //发送完了一批数据,则cnt(用来记录还没发送完的数据)的数值当然需要减去已经发送了的了。
    cnt-=rc;
    }
    return len;
    }
      

  4.   

    刚才我弄错了,发送第二个包的时候send返回socket_error,失败的原因似乎是socket没有准备好,请问有什么办法能够判断socket已经准备就绪了再进行数据发送吗?
      

  5.   

    if(Send(senddata,1024*60+sizeof(SocketMsgHead)) int nRet= Send(senddata,1024*60+sizeof(SocketMsgHead);
    可以看看到底发了多少字节出去了int nLeft = vLen;
    int nRet, nIndex = 0 ;
    while (nLeft > 0)
    {
       nRet = Send(&senddata[nIndex], nLeft);
       if(nRet == SOCKET_ERROR)
       {
          // Error..
       }
       nLeft  -= nRet;
       nIndex += nRet;
    }
      

  6.   

    SOCKET s;
    fd_set fdWrite = {0};
    FD_SET(s, &fdWrite);        // add socket s to the socket set
    int ret = select(0, NULL, &fdWrite, NULL, NULL);
    if (ret == SOCKET_ERROR) 
    {
    // error condition ,socket not ready to write
    }
    if (ret > 0)
    {
    // At least 1 socket ready to write, in this case only s
    }
      

  7.   

    楼主应该是用了异步套接字.
    异步发送当发送缓冲区被塞满之后就会返回错误.
    你要判断每次发送多少,60K的数据第一次能发送完,下一次就未必,可能只发送一部分,因为每次发送都是把数据投递到发送缓冲区,缓冲区满了就返回ERROR.
    所以你要判断发送出错的错误码,wsagetlasterror(),如果是wsaewouldblock,你就要sleep.
    如果用了同步套接字,就不会出现这种问题.