现在的问题是,使用猫拨号上线,在广域网中传送,发现一次传送动作传送不能超过1.5K的数据。查看帮助:
send is used to write outgoing data on a connected socket. For message-oriented sockets, care must be taken not to exceed the maximum packet size of the underlying provider, which can be obtained by getting the value of socket option SO_MAX_MSG_SIZE
那么传送100M的文件,得要很多很多次了。如何缩短整个传送时间呢?

解决方案 »

  1.   

    你不是用socket api来写的吧?
    如果不是的话,是用TCP还是UDP协议的控件呢?
    若是TCP的,你不用管,将所需传送的内容放到一个Buffer或Stream,直接传送即可.
    若是UDP的,那么你就要注意数据包的大小不能大于某个值了.
      

  2.   

    用indy servers/client组件面板的
    TIDTcpserver和TIDTcpClient即可
      

  3.   

    To: smokingroom(前世与今生) 
    "若是TCP的,你不用管,将所需传送的内容放到一个Buffer或Stream,直接传送即可."这是不对的。你可以拨号上线试验一下。不管是控件还是API,最后都是使用系统DLL里面的函数来实现发送接受的。
      

  4.   

    同意smokingroom(前世与今生),网络协议是分层的,在TCP层就不要去考虑太多IP层的事情。
    一次SEND调用不应该去管有多少个IP更高层次的东西尽管最终都要一层层下落到硬件层次上处理,但较高层次就只需要。。
    而且是应该只考虑它那一层次的东西。
      

  5.   

    (呵呵。还没有敲完就不小心按了回复键,该死的输入法。)何况‘一次传送动作’????在不同层次上有不同理解的。。!
    TCP层?
    IP层?
    PPP拨号层?
    MODEM载波?一次SEND调用不必也不应该去管有多少个IP包被送出被接收被丢弃速度主要是由你通讯带宽限制,另外,SOCKET通讯有些选项可以调整拨号通讯
    的IP包,只能有限的提高一点点速度。
      

  6.   

    首先感谢大家的回复!
    这么说吧,使用d5的TServerSocket 和TClientSocket。非组塞模式
    假使我在Client发送一个大数据包,按 smokingroom(前世与今生) 和halfdream(哈欠) 的意思,在ServerSocket端就不必理会分包大小及其组合的问题。
    但事实上是,超过了一定大小,请检测ServerSocket触发的ClientRead事件,其中
    Socket.ReceiveLength以及Socket.ReceiveBuf(buf, bufSize);并不是你发送的大小。
    也就是说,不可能不考虑发送的大小问题。
    还请继续指导!谢谢!
      

  7.   

    首先,我在论坛上回贴子也多次说过了。使用Socket.ReceiveLength不可靠。
    连续传送接收的时候,绝对不要用它作为依据。有效的接收大小是判断 Socket.ReceiveBuf(buf, bufSize);的返回值。。在TCP层,它是把发送的数据作为数据流来考虑,也就是说,
    你发送端调用N次SEND,它没有责任为你在接收端触发N次事件,它仅保证在接收端接收的数据流完整无损坏无丢失。
      

  8.   

    找到我以前回复的一个贴子。
    http://expert.csdn.net/Expert/topic/1691/1691527.xml?temp=.1613886
      

  9.   

    http://expert.csdn.net/Expert/topic/1860/1860383.xml?temp=.4346735
      

  10.   

    to halfdream(哈欠) 
    谢谢你的热心帮助!
    我试了一下你的代码,你说的“在TCP层,它是把发送的数据作为数据流来考虑,也就是说,
    你发送端调用N次SEND,它没有责任为你在接收端触发N次事件,
    它仅保证在接收端接收的数据流完整无损坏无丢失。”的确是这样,通过调试,但它也触发了N次事件,每次事件收的大小依然小于某个值。因为我要处理接受到的数据必须等它完全收完才能处理,而且每次数据大小是不确定的。我无法确定是否已经收完了。所以我现在仍然只能发送小于该最值的包,就能一次收完处理,但这样发送次数就太多了,还请你继续帮我分析一下。
      

  11.   

    使用猫拨号上线,在广域网中传送,100M的文件,哈哈哈...是万不得已吗?如果不是就不要用Socket吧
      

  12.   

    TCP层没有提供数据流分段之类的服务,应用程序得自己在数据流里面设置标志之类的
    办法判断,换句话说,会话过程由应用程序实现。
      

  13.   

    在HTTP协议中,下传文件的时候,服务器先发送信息头(两个回车换行人作为结束符)
    在信息头里面包含文件长度等信息,接下来连接的发送文件数据。
    客户端通过信息头取得文件下载长度,判断何时文件传完。
      

  14.   

    在类似RPC之类的协议中,比如DELPHI的MIDAS SOCKET服务器,(源码在SOURCE中)
    它是将数据成块发送,数据块规定标识头,块长度,数据块内容。
    也能保证双方一问一答。。
    这种方式便于交互式控制。用来传文件,象HTTP那样连续无应答要快一些。
      

  15.   

    查看了SOCKET服务器源码:
     P := Result.Memory;
      Inc(Integer(P), Result.BytesReserved);
      while StreamLen > 0 do  //也是根据长度来读取的
      begin
        RetLen := FSocket.ReceiveBuf(P^, StreamLen);
        if RetLen = 0 then
          raise ESocketConnectionError.CreateRes(@SSocketReadError);
        if RetLen > 0 then
        begin
          Dec(StreamLen, RetLen);
          Inc(Integer(P), RetLen);
        end;
      end;
      if StreamLen <> 0 then
        raise ESocketConnectionError.CreateRes(@SInvalidDataPacket);
      InterceptIncoming(Result);我再试试看。
      

  16.   

    请使用“拦截者”技术吧,它是被优化的三层体系通讯协议,能传输大量的图片和语音数据流,更不用说数据和文件了。
    安装很方便,详细看一下delphi中自带的例子吧,有介绍。
      

  17.   

    84175971(cyg) ( ) 
    能说说“拦截者”技术吗?在那里安装?delphi中相关自带的例子名字和路径是?
    请指导,谢谢
      

  18.   

    TO halfdream(哈欠) :
    做到正确的发送和接受数据,但是整个传输时间并不能缩短啊!有什么思路能缩短整个传输时间?请指教。分不够可以另外再开贴加。谢谢!
      

  19.   

    现在采用应答方式,将文件分包传送,当SERVER收到一个包后再发下一个包。
    觉得,不管采取组塞或非组塞的方式,传输的总的时间都会很长。因为每次传输的数据量有限,那么传输次数就有很多很多次。想请教大家,有什么办法能缩短总的传输时间。是不是和SERVER建立很多连接,将文件在这些连接上同时分包发送?然后在SERVER端组合?但个人觉得并不是这样。请大家指导!谢谢
      

  20.   

    1、用多个连接。
    2、改变应答方式,校验正确不回答,校验错误发错误应答。
    3、用UDP方式。
      

  21.   


    传输时间能缩短也是很有限的..能提高几个百分点就已经难得了..
    显然,好象你要的好象不是这么点点...
    换硬件的效果显然明显些...一般传输要稍好些,有几方面可以着手..
    1,减少TCP连接次数..
    2,减少应答...特别是应用层次上的应答.
    3,数据压缩..
    4,在某些情况下(用户多,网络不够通畅),多个连接也许会收到一点效果..(有时候效果相反)
      

  22.   

    如果你用猫的话,建议你用RAs,再用ftp,这样效果不错
      

  23.   

    不是用猫,只是现在用猫测试。
    看到一些P2P软件,下载速度并不慢啊!还有WINDOWS右键下载另存,速度也有100多K。
    不知道有什么思路可以实现。
      

  24.   

    谢谢大家参与,这个问题我解决了。
    其实我的问题是这样的:我想将文件数据和其他命令信息都定义成自己格式的数据包来发送接受。但是,在不同的网络状况下,发送和接受的大小有很大区别,所以,数据包的边界无法确定,不能通过某种手段来识别是文件包还是命令包。很多人的处理方式是应答后就只管接受数据了,不去判断是什么类型的包,也就是说在开始接受文件信息后,就将收到的字节只管写文件就OK了,。我原想可以按自己定义的数据包的长度来接受解包处理,现在发现存在上述的问题,所以采用别的方式了。TO  halfdream(哈欠) :你讲的很详细,谢谢你对这个问题的关注。大家还有什么高见吗?如果能有正确解析包类型和数据的思路请指导,(注意在WWW,发送和接受数据的大小是不确定的。接受端能保证完整的正确的接受到发送端的数据,但是边界就需要自己确定了)
    要是没有的话,等下就给分,谢谢!
      

  25.   

    如果能确定边界,那就只要在包头几个字节加上闭标志就可以区分命令包和数据包。
    char Flag[6];   标志
    int  Index;     数据包编号
    int  Size;      包长度
    int  CRC;       CRC校验码
    char Data[1024] 1K字节的数据包(可以变长)
      

  26.   

    每次收下的数据量是不确定的,局域网里面是看不出效果的,你上WWW试一下就知道了.
    在这种情况下,边界很难确定.你收取下来的数据并不是以包头开始的,那么解包就有问题了.
      

  27.   

    不知道上面的说了没有,但每次发送的数据单元大小不会超过某个值,应该就是1500 BYTE左右大小。
    这是WINDOWS下的TCP/IP协议规定的,不过可以更改。
      

  28.   

    数据包的大小定成1K,应该可以不用进行包的重新组合。参见http://new.playicq.com/dispdocnew.php?id=5455,我用UDP做的文件传送程序。
      

  29.   

    如果只定义成1K,当然就不存在任何问题了。但是,你想想得发多少次啊,呵呵,效率太低了。TCP协议为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据.
    这个问题,只能自己重新组包。
      

  30.   

    呵呵,不明白,既然使用tcp,为什么还要做分包拆包?
    俺以前用modem,同样走tcp,当然不是用delphi,实现的远程数据库同步,也没有分包呀。
    数据量是几十兆,压缩后为5~10兆左右,没有达到100兆,但量级查不多。
      

  31.   

    思路如下:c,s双方处于传送开始状态c 发送一个指示要发送的数据长度的命令(固定格式,要求s“一定”要能解析出来,因为这个命令可能被拆分到达)
    s 接收到命令,得到长度
    c 发送指定长度的数据。不必封包,直接把数据发送出去。
      注意如果send操作返回的数据如果小于要发送的数据长度,那么忽略过刚才已经发送的数据,再次调用send,反复调用send
      一直到已经发送的数据长度等于待发送的数据长度。
    s 接收数据。把接收到的数据放入缓存(当然可以用文件等存储设备),检查总长度,如果长度够了,接收结束。
      注:接收数据操作可能要做许多次
    over了如果使用tcp,根本就不用考虑要发送的数据的封包问题!tcp的作用就是保障数据的正常顺序到达!
    除非,考虑到服务器的缓存等等方面,你自己额外限制每次发送数据的长度。
      

  32.   

    楼上的没有细看我上面的话““很多人的处理方式是应答后就只管接受数据了,不去判断是什么类型的包,也就是说在开始接受文件信息后,就将收到的字节只管写文件就OK了,。””halfdream(哈欠) ( ) 的
    http://expert.csdn.net/Expert/topic/1691/1691527.xml?temp=.1613886里的做法就是你描述的,你这样做,在这个连接上开始传文件后就不能处理其他的信息了,而且不能同时接受多个用户的请求。
      

  33.   

    “你这样做,在这个连接上开始传文件后就不能处理其他的信息了,而且不能同时接受多个用户的请求。”俺可真的不明白了,一个连接,既然已经开始传送文件,当然不可能同时在这个连接上接收到其他数据了(事实上是,在服务器端接收完毕之前,客户端不可能发出新的数据,)!难道这个有问题吗?看你的说法,你似乎想要在传递一个大数据流的同时,可能还会发送一些状态控制之类的命令。如果是这样,你去看看ftp的实现吧!再使用一个端口专门处理命令。当然,这样对每个客户端事实上有两个连接,你的服务器端的实现可能要更复杂些。再,使用自己定义的数据封包格式,也可以保证完整性,并实现控制命令在流传递过程中发送。只要在接收端定义一个数据缓冲管理器就行了。简单思路如下:
    c封包发送
    s接收到数据,把数据追加到缓冲区,解释缓存区中已经有的数据。
       把解析出来的数据放入目标数据中,在缓冲中清除已经解析完的数据, 注意:此时,在缓
       冲管理器中可能还有数据没有解析完成,需要和下次到达的数据组合起来解释。解析出来 
       的数据可能是命令,也可能是数据流的某个段。这样肯定可以保证你自己定义包的封装格式(不用校验),如果你同时传递数据和控制命令,那么做不同的封装
    只要你的缓冲管理器能解释出来就行了。
    注意:封装过程要做封装标识的转义。解释过程做转义的解释。多个客户端有什么问题吗?每个客户端是独立的一个连接呀!你用线程也好,完成端口也好,或者什么其他的东西都好,每个连接都能独立管理起来,难道还能混乱吗?多个客户端的情况在服务器看来,每个连接都是不同的,每个连接都有socket状态。在程序实现的时候当然要考虑多个兵法请求,但不影响对所谓的大数据量的传输的设计模式嘛
    搞不懂........
    再小声地说:有些朋友似乎还没有搞清楚socket的基本概念嘛
      

  34.   

    提供一个思路供诸位参考:
    1、服务端先把有关文件的大小和分块大小信息传送到客户端。
    2、客户端根据文件大小和分块大小建立一个对照表,每一个数据块对应表中一个纪录。
    3、服务端分块发送全部文件,每一块有一个校验码。但不等待客户端返回校验信息而连续发送。
    4、客户端接收经校验正确的数据包后写入文件,同时把对照表相应纪录做标记。
    5、服务端发完文件后通知客户端,客户端把校验错误或未收到的包编号发给服务端。
    6、服务端把按照收到的需要重发的包编号重发数据包。
    7、客户端全部校验正确后通知服务端结束文件传输。以上文件传输思路我的用UDP发送文件程序中已经成功实现。这好像也应该适用于多客户端的文件传送。