本人正在写一个文件上传的程序,模拟http协议实现文件上传。 我的实现机制是客户端每次发送一个文件块1K大小,然后sleep(10),当发送50个包后,如果服务端接收没问题,则回应一个包,客户端收到这个包后,则继续发下50个包。当网络状况较好的时候,server 和 client 收发都没什么问题,但是当网络比较慢,延时达到200ms以上时,则出现问题,接收文件的时候就会出错,总是提示收到的数据与要求的数据不服,要求客户端重传。调试了很久,不知原因在哪里。(我也改成传一个包回应一次,老问题依然出现)
自己的疑问是:1、网络慢会对接收方造成什么样的影响,会影响tcp的包的重组和socket缓冲区里面包的顺序吗?
              2、当客户端send一批数据,是怎样往服务端的socket 缓冲区写入?谢谢指教!!!

解决方案 »

  1.   

    Boost socket performance on Linux
    -- Four ways to speed up your network applications
    http://www-128.ibm.com/developerworks/linux/library/l-hisock.html
      

  2.   

    你还是检查你自己的代码吧
    问题不是出在网络延迟
    而是你的发送或者接收代码容错存在问题
    检查你的代码中的发送和接受部分,是否确实检查了每一次发送的返回值并进行了处理
    TCP连接不会出现你说的这种问题
    与网络无关
      

  3.   

    楼上说的就是每次接收之后都检查是否接收到了正确的内容,如果不正确则直接返回SOCKET_ERROR,然后关闭套接字,在重新等待连接进行传送吗?
    但是网络速度慢会造成包的丢失和不完整吗?
      

  4.   

    setsockopt
    在send(),recv()过程中有时由于网络状况等原因,发收不能预期进行,而设置收发时限:
    int nNetTimeout=1000;//1秒
    //发送时限
    setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));
    //接收时限
    setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int)); 
      

  5.   

    我不知道你是用阻塞还是非阻塞
    是用异步还是同步?
    看你的描述和相关
    象是使用阻塞
    那么你就应该一次性不要发送和接收那么多数据
    发送端 send->其实是首先发到本地缓冲,然后有TCP/IP将缓冲中数据组合成TCP包,通过IP层[IP包]发送到目的地
    接受端 RECV-》同样是读本地缓冲,
    在阻塞模式下,你一次发送太多的数据,例如好几M,遇到网络不好的情况就会出现发送或者接收失败
    默认情况下,你调用的SEND的TCP默认超时时间大概是几百秒这样,如果超过这是时间,还没有被完全发送或者接收
    就认为网络出问题,返回失败
    所以阻塞模式下,一次性发送的包不要太大,建议改用非阻塞或者异步
      

  6.   

    网络慢的情况下,会导致你服务器收数据并不是1k(可能缓冲区只有几十字节或者积攒了几k).
    tcp是流数据,不像UDP一样一个一个包的,TCP做应用协议的话需要加包头什么的封装。
    你这个至少也要判断一下一次接收的返回值,可能不到1k,够一k了再校验。
      

  7.   

    谢谢5楼
    偶也遇到了网络断了自动互连的问题 现在解决了
    唉 学mfc之前最好先学sdk 要不连些概念都搞不明白 mfc老多默认 呵呵
      

  8.   

    谢谢大家的指点,问题找到了,也解决的,但是不知道有没有更好的解决方法。
    我采用的是事件选择模型,但是在接收数据的时候,使用的是recv(socket,&ch,1,0),在这个时候,总是出现接收失败,返回SOCKET_ERROR的错误,产生的错误原因是由于要接收数据的缓冲区中没有数据(这是由于网络太慢,还有部分数据没有传到造成的),所以我在此就设定一个sleep(10),等会儿再取,如果还没取道,再循环,一直等到有数据为止。这可能是解决网络慢的一个很笨的方法。看到上面5、6楼的提示,是否可以用setsockopt函数实现循环sleep的功能呢?
    还有,就是我对阻塞和非阻塞还是比较迷茫,请大家赐教。
      

  9.   

    刚刚查看了些资料,非阻塞socket会返回SOCKET_ERROR,并可取得WSAEWOULDBLOCK的错误码。这样说来,recv是非阻塞还是阻塞取决于socket是非阻塞还是阻塞,我选择的是时间选择模型,是否意味这建立的套节字自动设为了非阻塞,要不recv收不到数据就不会返回SOCKET_ERROR。而再我这个程序的要求当中,需要使用阻塞的recv,一直到数据完全收到才返回,所以我的程序才会出错,那么,如何将socket设置为阻塞的呢?设置为阻塞的socket对事件选择模型会有影响吗??希望高人指点。
      

  10.   

    api 和 CSocket 都由设置的方式的 你自己找找吧
    阻塞模式就是让线程阻塞 直到接收结束 一般开单独的接收线程 用阻塞模式
    非阻塞本线程继续运行 让当数据到了buffer时 发出一个Notification 进入OnReceive() 做处理 一般在只有一个主线程时用这种方式