之前tcp方面写的很少,udp写的倒是不少,所以这次写网络版程序的时候遇到了很大的问题,开始认为网络并发方面iocp完成端口肯定是最有优势架构,于是开始拜读王艳平《windows网络与通信程序设计》那本书,看个8成懂,开始进行测试--iocpsys,发现线程池处理时包的顺序在设置线程数2以上的时候出错,即如果客户端不等待发送大量数据包,书中给的链表数据结构包括其处理不能够处理好包号排序的问题,不知有没有具体调试过这个程序的大虾,codeproject上有个巨复杂的,而且不能判断恶意连接;继而测试IOCPDemo这个单线程程序,包的顺序不会出错了,但是经过50000-1000000的数据包的测试发现会有少量数据包丢失,非常郁闷,测试环境局域网,不应该呀,反复调整程序结果依然,网上查了下,有大虾遇到有此种问题存在,但没有找到可行的解决方案;弃之使用最简单的WSAAsyncSelect模型,windows消息大大削弱了网络接收的能力,太慢了,丢包倒是没有发现;弃之使用select模型,发现此种模型在效率和丢包上都是不错的,测试发现没有丢包发生。关于tcp的完成端口,有哪位大侠解决了服务器端接受包的顺序问题及丢包问题,参考哪个例子,msdn上代码好像比较少多,欢迎指教,[email protected]、qq:313668429

解决方案 »

  1.   

    看经典的书《winodws网络编程》第二版。
      

  2.   


    大概看了一下,也看了一下里边的例子,但没有调试,在网上找了几个例子还是存在包序问题,即多个工作线程开启,客户端for循环无等待发包,不知是否和TCP的粘包问题有关,包括丢包,有可能是有的数据未解析出来
      

  3.   

    tcp 要处理粘包,丢包跟你一点关系都没有。
      

  4.   

    TCP是不会丢包的.
    应该是对方发送时候就出现错误没有发过来,并不是才传输过程丢的,检查对方对发送结果有错误判断.
      

  5.   

    如果你还是在用这本书《windows网络与通信程序设计》上原来那个例子,注意一下里面的链表的处理
    我就发现在GetNextReadBuffer这个函数里面是有错的,我改了一下,成下面这样
    CIOCPBuffer *CIOCPServer::GetNextReadBuffer(CIOCPContext *pContext, CIOCPBuffer *pBuffer)
    {
    if(pBuffer != NULL)
    {
    // 如果与要读的下一个序列号相等,则读这块缓冲区
    if(pBuffer->nSequenceNumber == pContext->nCurrentReadSequence)
    {
    return pBuffer;
    }

    // 如果不相等,则说明没有按顺序接收数据,将这块缓冲区保存到连接的pOutOfOrderReads列表中 // 列表中的缓冲区是按照其序列号从小到大的顺序排列的 pBuffer->pNext = NULL;

    CIOCPBuffer *ptr = pContext->pOutOfOrderReads;
    CIOCPBuffer *pPre = NULL;
    while(ptr != NULL)
    {
    if(pBuffer->nSequenceNumber < ptr->nSequenceNumber)
    break;

    pPre = ptr;
    ptr = ptr->pNext;
    }

    if(pPre == NULL) // 应该插入到表头
    {
    pBuffer->pNext = pContext->pOutOfOrderReads;
    pContext->pOutOfOrderReads = pBuffer;
    }
    else // 应该插入到表的中间
    {
    pBuffer->pNext = pPre->pNext;
    //原来的代码是下面这一行
    //pPre->pNext = pBuffer->pNext; //改成现在这样
    pPre->pNext = pBuffer;
    }
    } // 检查表头元素的序列号,如果与要读的序列号一致,就将它从表中移除,返回给用户
    CIOCPBuffer *ptr = pContext->pOutOfOrderReads;
    if(ptr != NULL && (ptr->nSequenceNumber == pContext->nCurrentReadSequence))
    {
    pContext->pOutOfOrderReads = ptr->pNext;
    return ptr;
    }
    return NULL;
    }但是这个例子怎么说,就是比较简单