我有一个数据传输程序,服务端采用overlapped模型接收数据,客户端采用tcp协议发送数据,客户端和服务端数据都必须入到本地数据库中,客户端硬件定时采集数据后先入本地库,再向服务端发送,服务端收到数据后入本地库.客户端如果本次发送数据不成功,先保存在文件中,下次采集到数据后再发送。共有8个客户端发送数据,每次发送数据约1M(我在发送时作了处理,把这1M数据分成多次发送,每次数据量不大于1k),服务端一般都可以收到数据,但是有时候服务端收不到某个客户端某时段的数据,后来的数据却可以收到,而那一段时间的数据却永远收不到了.可是,由于我在客户端程序中对发送不成功的数据保存了,下一段时间应该重新发送,服务端在以后的某个时段中应该可以收到,而实际上这些数据却永远收不到了,这是怎么回事,如果我的程序有错,错误可能在什么地方,如果我的程序没有错误,又可能是什么问题.

解决方案 »

  1.   

    贴代码.
    既然收不到,肯定是数据掉了.
    recv这函数不保证你一次就收到你想要的长度.
      

  2.   

    对不起,我的代码很长,不能完全贴在这里。我采用的是完成例程来接收数据的,使用了wsareceive,我的WorkerRoutine(完成例程)代码大致如下
        if (0 != Error || 0 == BytesTransferred )//套接字io错误或者客户端已发出了关闭连接的信息 则必须关闭套接字
        {
            closesocket(SI->Socket);
            GlobalFree(SI);
            return;
        }
        ...处理接收到的数据的代码
    //重新投递接收请求
        Flags = 0;
        ZeroMemory(&(SI->Overlapped), sizeof(WSAOVERLAPPED));//overlapped结构清空
        
    //定义接收缓冲区,及其长度
        SI->DataBuf.len = DATA_BUFSIZE;
        SI->DataBuf.buf = SI->Buffer;    if (WSARecv(SI->Socket, &(SI->DataBuf), 1, &RecvBytes, &Flags,
           &(SI->Overlapped), WorkerRoutine) == SOCKET_ERROR)
        {
            if (WSAGetLastError() != WSA_IO_PENDING )
            {
                closesocket(SI->Socket);
                GlobalFree(SI);
                return;
            }
        }workThread代码大致如下(处理接收的线程)
        EventArray[0] = (WSAEVENT) lpParameter;    while(TRUE)
        {
            //等候客户端连接信号同时也处理workroutine的返回
            while(TRUE)
    {
        //等待EVENTARRAY中某个事件的完成,或者某个告警IO的完成
               Index = WSAWaitForMultipleEvents(1, EventArray, FALSE, WSA_INFINITE, TRUE);           if (Index == WSA_WAIT_FAILED)//出现错误
       {
                   return FALSE;
       }           if (Index != WAIT_IO_COMPLETION)//如果不是由完成例程来处理,表明他是一个客户端的连接请求
       {
                   break;
       } 
    }        //结束接收事件
            WSAResetEvent(EventArray[Index - WSA_WAIT_EVENT_0]);        //创建一个新的客户端socket信息
            if ((SocketInfo = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,
                sizeof(SOCKET_INFORMATION))) == NULL)//内存不足
    {
                return FALSE;
    }         // 填充客户端socket的详细信息
            SocketInfo->Socket = AcceptSocket;
        SocketInfo->ClientAddr=ClientAddr;
            ZeroMemory(&(SocketInfo->Overlapped), sizeof(WSAOVERLAPPED));  
            SocketInfo->BytesRECV = 0;
    SocketInfo->Buffer2Size = 0;
            SocketInfo->DataBuf.len = DATA_BUFSIZE;
            SocketInfo->DataBuf.buf = SocketInfo->Buffer;        Flags = 0;
             
        //向完成例程投递一个接收请求
            if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags,
                &(SocketInfo->Overlapped), WorkerRoutine) == SOCKET_ERROR)
    {
       //返回错误WSA_IO_PENDING表明重叠io初始化已经完成
               if (WSAGetLastError() != WSA_IO_PENDING)
       {
       closesocket(SocketInfo->Socket);
                   GlobalFree(SocketInfo);
                   continue;
       }
    } }
      

  3.   

    据我的经验,只要网络是通的,不可能收不到;
    还有,可以自己做一个发送队列,然后把要发送的数据填入队列的一端,而只在另一端取数据send.对于recv,建立一个recv队列,把接收到的数据存入接受缓冲队列的一端,而只在另一端取数据。这样的模型可能更加直观