原贴内容见:
http://expert.csdn.net/Expert/topic/2860/2860889.xml?temp=.307934既客户端接收数据量大时,该如何接收?具体如何解决?是否是多次解发onRead事件?通过“postren(小虫)”与“ zjqyb(风清扬*任它溺水三千,我只取一瓢饮*) ”、“ halfdream(哈欠)”等高手们的例程与提示,问题基本得到解决,但是还是不很明的其中的处理流程,想弄清其中之处理流程、原理等!
欢迎大家参于讨论!

解决方案 »

  1.   

    NonBlocking一定会多次触发OnRead事件的, 但只要你读取的数量是一定的, 不会影响后面的读取的, 也就是说: 当你调用Socket.Receive方法的时候, 读取出来多少字节就自动清空已经读取的缓冲区, 在缓冲区没有溢出的情况下, 你什么时候去读都可以, 只要网络没有断开.另外一个简单的例子, 假如一次发送了9000个字节, 超过了默认的8K(8192), 而你每次读取一个字节, 当你第一次读取一个字节之后, 继续触发OnRead事件,可以继续读取下一个字节, 而不必担心是不是上次触发OnRead事件时, 没有把缓冲区的数据全部读取出来会影响后面的OnRead事件.
      

  2.   

    NonBlocking一定会多次触发OnRead事件的
    所以在Onread事件中就不应该用循环repeat
        reveivebuf...
    until之所以你用了sleep(1)就好了,那只是运气,在其他机器可能就不行了
    用死循环receievebuf ,主线程就很忙,用了sleep当然主线程会交出一点控制权
    所以应该考虑多次触发OnRead来组合一个完整packet
      

  3.   

    到底我应该用循环repeat
        reveivebuf...
    until还是考虑多次触发OnRead来组合一个完整packet请大家谈谈各自的看法。
      

  4.   

    以上他们回答的已经不错了,若你的程序不是很复杂,你就试试用NMStrmServ,NMStrm
    它好像不受文件大小限制,我试过5M的文件,一次就穿过去了。你试试,帮你顶。
      

  5.   

    你说的是流?
    因为服务端不是我写的,只能基于对方所采用的ReceiveBuf方法来实现,程序不是很复杂, 
    我做的是客户端,只连中间介(也就是SERVER端),完全不连数据库,就是说我的操作都要通过socket来实现,所以不能出一点差错。
      

  6.   


       winsock 有他的局限,在大量数据发送的情况下会有溢出或丢包的情况。
       一般来说需要在客户端接受到一定量的数据时候发包到服务端,
       服务端在接收到此请求后继续发送剩余数据。
      

  7.   

    我现在也正为这些事而郁闷啊,我也是用ClientSocket的 NonBlocking方式,可当我客户端发送数据过快,可能大于服务端的接收速度,就会丢包!
    请问这种现像要处理啊
    ??
      

  8.   

    这里小虫写的一个例程,你看看type
      TMsgHeader = record
        cmdLength: Longword;
        cmdID: Longword;
        cmdStatus: LongWord;
        cmdSequence: LongWord;
      end;procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    var
      Len, L, CommandLength: Integer;
      Head: TMsgHeader;
    begin
      Len := 0;
      repeat       //读取一个LongWord, 利用repeat循环是避免还
                   //没有读到完整的LongWord网络就断开了
        L := Socket.ReceiveBuf(BufServer[Len], SizeOf(LongWord) - Len);
        if L > 0 then
        begin
          Inc(Len, L);
        end;
        if L < 0 then Exit; //可能网络断开
      until (Len = SizeOf(LongWord));
      CopyMemory(@CommandLength, @BufServer[0], SizeOf(LongWord));
      repeat               //循环读取剩余的数据, 直到长度为包头中的长度, 或网络断开
        L := Socket.ReceiveBuf(BufServer[Len], CommandLength - Len);
        if L > 0 then
        begin
          Inc(Len, L);
        end;
        if L < 0 then Exit; //可能网络断开
      until (Len = CommandLength);
      CopyMemory(@Head, @BufServer, SizeOf(TMsgHeader));
    //  DecodeMsg(@BufServer[0], CommandLength);
    end;
      

  9.   

    楼主:我试了,怎么不行啊
    一连上去,马上就把我的Socket断开了
    怎么回事啊?
      

  10.   

    ClientSocket用在线程里不太好吧?
      

  11.   

    >> winsock 有他的局限,在大量数据发送的情况下会有溢出或丢包的情况。
    >>   一般来说需要在客户端接受到一定量的数据时候发包到服务端,
    >>   服务端在接收到此请求后继续发送剩余数据。上面这种想法是初学者常常产生的错误理解之一,
    TCP提供了可靠的,数据流服务.
    对于发送端,
    当使用阻塞SOCKET时,发送函数返回值就是传到对端SOCKET实际的数据.
    这种情况下,发送端程序可以通过判断返回值完全确定数据已经发送到对端.当非阻塞SOCKET时情况复杂些..
    发送函数将数据写入SOCKET内部缓冲区,由协议栈处理发出.
    因为发送函数只是写缓冲区,不会阻塞,这样就会出现内部缓冲区被写满情况,
    SEND函数就会返回失败,应用程序则延时重发..这种方式也是不需要应用层请求回应
    来确保数据可靠传送的.