我有一段接收的程序                                s.Send(Encoding.Default.GetBytes("sendfile"));
                                Array.Resize(ref bytes, n);
                                s.ReceiveBufferSize = n;
                                s.Receive(bytes, n, 0);
                                System.IO.FileStream f = new System.IO.FileStream("tmp.jpg", System.IO.FileMode.Create, System.IO.FileAccess.Write);
                                f.Write(bytes, 0, n);
                                f.Close();约定好接收N个字节,其实是一个图形文件的大小,用s.Receive(bytes, n, 0)收数据后,把Bytes中的文件写到磁盘再画出来,有时候会发现图像的下半截没有,为什么?
但是我用下面的语句就没发现少数据的问题了                                s.Send(Encoding.Default.GetBytes("sendfile"));
                                Array.Resize(ref bytes, n);
                                s.ReceiveBufferSize = n;
                                for (int i = 0; i < 1000; i++)
                                {
                                    Application.DoEvents();
                                    System.Threading.Thread.Sleep(10);
                                    if (s.Available >= n) break;                                }
                                s.Receive(bytes, n, 0);
                                System.IO.FileStream f = new System.IO.FileStream("tmp.jpg", System.IO.FileMode.Create, System.IO.FileAccess.Write);
                                f.Write(bytes, 0, n);
                                f.Close();就是在接收前加一段延时,就能把数据收完整了。我的疑问是s.Receive(bytes, n, 0)方法,本来不就应会等到N个数据才会返回吗?那段延时按道理是没有意义的吗?
我的Socket设置了12秒的超时,如果不写延时,无论写不写延时,均未发现超时.

解决方案 »

  1.   

    我的Socket设置了12秒的超时,如果不写延时,无论数据完整不完整,均未发现超时.
      

  2.   

    难道这里没人用Socket传送文件啊?我的文件很小,只有几十K。
      

  3.   

    睡了个午觉,刚看到有人用Socket传文件的,一般很少会这样的,直接操作底层Socket传文件,呵呵。话说回来了,你那个Array.Resize(ref bytes, n);做什么用的
      

  4.   

    啊,我知道了,你不是直接创建一个n大小的bytes,而是先创建了一个不足n大小的bytes而且改变它的大小。
    我怎么感觉画蛇添足啊。关于你那个问题,估计就是你的ReceiveBufferSize太大的缘故了,如果数据不是一次性连续读入,中间有断续,它就读不完ReceiveBufferSize的大小就返回了,你需要下次继续读取。其实何必如此呢,你完全可以设置个小点的Buffer,比如1024。然后循环读取,判断读取的总长度正好为文件长度,就停止接收。
      

  5.   

    几乎不用看完就可以断定,你用的是TCP协议吧!
    送完数据记得压出啊,压出啊!Flush之TCP(在半双工模式下),网卡会维持一个缓冲区,网卡设备认为合适的时候,就会发出。而不是你把数据灌进去的时候他就发出(简单的说Socket象网卡里灌数据,不代表网卡“立刻”发出去了)某些数据会在下一个tcp包里发送。明白了?嗯,全双工模式更复杂一点,不过好在Socket代码操作没有任何区别。
      

  6.   


    那个n就是文件的大小啊,要传的文件长度事先又不知道,不用Array.Resize你说怎么办?又怎么会画蛇添足呢?我看了MSDN 关于Socket.Receive的介绍,如果在Receive中指定了要接收的字节数,Receive会等到字节数够了才返回的,难道Msdn说的不对?如果没接收完就返回,那和不指定字节数的那个重载又和分别?
      

  7.   

    为什么一直等待不可能呢?Socket的ReceiveTimeout属性决定等待多长时将啊,ReceiveTimeout=0就表示一直等待了,除非微软的Socket有Bug,否则我真的不能理解了。有人说修改接收缓冲区大小的方法不可靠,那么有什么理由呢?是不是很多人都发现这样做不行呢?我毕竟刚用C#,不是很清楚,如果没被人证明是不可靠的,那么微软提供这个功能,我们只要相信它,否则还有什么理由继续使用.net写程序呢?
      

  8.   

    这是有前提的,前提是没有收到任何数据的情况下就一直等待,但如果收到了数据但是缓冲区没满,就不一定会一直等下去了,不然如果定义的缓冲区在最后一次数据接收时就是无法填满,难道就永远不接收那未满的数据了吗?别告诉我还有flush()方法,MSDN上说了,那个没任何作用,对网络上的流是无效的。