本帖最后由 VisualEleven 于 2010-12-27 14:34:04 编辑

解决方案 »

  1.   

    还加一个问题  服务器有静态IP 外网,内网IP  如 192.168.2..... 服务器接收时要怎么才能知道是内网的哪个IP发来的数据???
      

  2.   

    connect成功 是成功了的,Send 也是成功了的,你原来也说过,send 返回成功,并不代表服务器接收成功
      

  3.   

    ACK?这个底层已经做了。 3次握手你不需要关心。 
    客户端如果发送出去了, 一般服务器就接收到了。 除非发送失败
      

  4.   

    connect成功,就表示服务器accept了连接了,send成功是表示将要发送的数据copy到系统发送缓冲区剩余的空间中,然后协议稍后才将数据发送
      

  5.   

    你的客户端是用外网IP链接的,那服务器获得的就是外网IP;客户端用内网IP链接的,服务器获得的就是内网IP
      

  6.   

    我做了测试的,客户端是发送成功的,服务器,Recv的时候是失败.而且是阻塞方式.开的一个单线程做接收
      

  7.   


    嗯,是的,你原来说服务器发一个ACK包回来,怎么发?
      

  8.   

    一般.. 那说明服务器还是有可能会接收失败的,同时有可能会有1000个并发的Send 给服务器.
      

  9.   


    对。
    如果是重要的控制信令,可以在应用层回传确认。
    如果是传输数据,可以在应用层做CRC校验。
      

  10.   

    如果是重要的控制信令,可以在应用层回传确认。
    如果是传输数据,可以在应用层做CRC校验。如何实现?还是用Send Recv吗?
      

  11.   


    对,就用send/recv 相当于在应用层自己搞一个协议来确认
      

  12.   


    就是发一个  if(SOCKET_ERROR==recv(sockConn,recvBuf,1000,0))
    {
    TRACE("失败原因是=%s \n",GetLastError());
    TRACE("失败!%d\n",htons(addrClient.sin_port));

    if(SOCKET_ERROR==send(sockConn,"服务器接收失败",strlen("服务器接收失败")+1,0))
    {
    pParam->m_ListError.InsertItem(0,"服务器接收请求失败 返回客户端 发送失败\n");
    }
    else
    {
    pParam->m_ListError.InsertItem(0,"服务器接收失败 返回客户端 发送成功\n");
    }
    }
    else//接收成功
    {
    .................................是不是这样?如果服务器告知,客户端,即色部分.那是不是客户端又得问服务器有没有成功接收呢?那不是一需要一个循环来做双方是否接收成功?
      

  13.   


    你可以仿造TCP的重传机制做一个发送队列,每个数据包都有个编号,如果接收方回传了编号就说明发送成功了,否则超时了就重发。当然还可以进一步改进。
      

  14.   

    还是有传输不完整的,定时检查,好像有点不现实,数据太多,客户端也很多.服务器给了客户端数据,客户端一定要成功的把结果返回给服务器.试验了近一个月没有一个完美的解决方案.....ACK返回客户端如何接收?如果客户端没收到就重新发.多长时间重新发?会不会重复?
      

  15.   

    上面说了一大堆的东西,就看了3条.按照我的思路给你说一下.首先connect成功表示3次握手成功了
    send成功返回,正常情况下(SO_SNDBUF不为0)表示数据被投递到了发送缓冲,此时并不意味着已经发送给了服务端,并且回应ACK了,何时真正发送过去,你并不知道,因为TCP都一套控制机制.如果发送缓冲区为0,那么send返回,表明你的数据确实已经发送到了服务端上,并且它已经回应了ACK,你也成功确认了,但一般来说不会把发送缓冲设置为0,除非有特殊需求.
    因此你如果想确定服务端已经收到,最好的方式是通过你的应用级别,进行确认,也就是一旦你发送了某个指令,则必须服务端回发一个数据给你,表示确认成功.
      

  16.   

    现在是,Send数据后就等待 
    if(SOCKET_ERROR==recv(sockClientResult,recvBuf,1000,0))
    有一个问题,如果服务器Send回来的数据客户端并没有recv 即上面的 
    服务器端send失败.当然此处说的失败,不是程序已经知道send失败,send成功不一定就客户端就收到了
    Recv会一直等待.造成线程一直等待
      

  17.   

    recv怎么让它超时,如果没有超时的设定,线程里很容易一直recv处等待服务器返回 服务器接收成功的确定信息
      

  18.   

    是不可能做这个确认的:
    客户端只能确认自己的消息是成功发出去 但是服务器是否收到客户端是无法得知的
    如果客户端需要服务端告诉自己收到了前面那个消息 那服务端又怎么知道自己send成功后客户端是否收到呢?
    关于这个可以看个小故事:
    http://blogold.chinaunix.net/u3/114095/showart_2343652.html
      

  19.   

    就是如果客户端recv一直等待到一定时间后就失败。又重新发送数据到服务器。服务器也可以判断是否是重复数据。一直到发送成功为止这样好像效率并不高。。有其它更保险的方法吗?
      

  20.   

    在应用层上实现:
    和服务端确定在收到客户端的一定消息后需要发回相应的确认,这个时候客户端再去recv这个信息就可以了
    这样就可以让客户端确认服务端收到了这个消息
      

  21.   

    上面我已经把原理说了一遍,不知道你有没仔细看.
    你如果要超时:1.使用setsockopt的SO_RCVTIMEO选项,在recv前设置,具体查MSDN,它只对阻塞有效.
    2.使用select模型,里面有超时参数可以设置,查MSDN
    3.使用异步IO模型,如大家常喜欢说的IOCP模型,就不会有阻塞问题了.
      

  22.   


    服务器不知道内网IP。之所以内网和服务器能通讯,因为在内网网关上做了NAT。
      

  23.   


    这个已经解决,只需要把自己的IP传到服务器就知道内网IP了