现在的问题是,使用猫拨号上线,在广域网中传送,发现一次传送动作传送不能超过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的文件,得要很多很多次了。如何缩短整个传送时间呢?
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的文件,得要很多很多次了。如何缩短整个传送时间呢?
如果不是的话,是用TCP还是UDP协议的控件呢?
若是TCP的,你不用管,将所需传送的内容放到一个Buffer或Stream,直接传送即可.
若是UDP的,那么你就要注意数据包的大小不能大于某个值了.
TIDTcpserver和TIDTcpClient即可
"若是TCP的,你不用管,将所需传送的内容放到一个Buffer或Stream,直接传送即可."这是不对的。你可以拨号上线试验一下。不管是控件还是API,最后都是使用系统DLL里面的函数来实现发送接受的。
一次SEND调用不应该去管有多少个IP更高层次的东西尽管最终都要一层层下落到硬件层次上处理,但较高层次就只需要。。
而且是应该只考虑它那一层次的东西。
TCP层?
IP层?
PPP拨号层?
MODEM载波?一次SEND调用不必也不应该去管有多少个IP包被送出被接收被丢弃速度主要是由你通讯带宽限制,另外,SOCKET通讯有些选项可以调整拨号通讯
的IP包,只能有限的提高一点点速度。
这么说吧,使用d5的TServerSocket 和TClientSocket。非组塞模式
假使我在Client发送一个大数据包,按 smokingroom(前世与今生) 和halfdream(哈欠) 的意思,在ServerSocket端就不必理会分包大小及其组合的问题。
但事实上是,超过了一定大小,请检测ServerSocket触发的ClientRead事件,其中
Socket.ReceiveLength以及Socket.ReceiveBuf(buf, bufSize);并不是你发送的大小。
也就是说,不可能不考虑发送的大小问题。
还请继续指导!谢谢!
连续传送接收的时候,绝对不要用它作为依据。有效的接收大小是判断 Socket.ReceiveBuf(buf, bufSize);的返回值。。在TCP层,它是把发送的数据作为数据流来考虑,也就是说,
你发送端调用N次SEND,它没有责任为你在接收端触发N次事件,它仅保证在接收端接收的数据流完整无损坏无丢失。
http://expert.csdn.net/Expert/topic/1691/1691527.xml?temp=.1613886
谢谢你的热心帮助!
我试了一下你的代码,你说的“在TCP层,它是把发送的数据作为数据流来考虑,也就是说,
你发送端调用N次SEND,它没有责任为你在接收端触发N次事件,
它仅保证在接收端接收的数据流完整无损坏无丢失。”的确是这样,通过调试,但它也触发了N次事件,每次事件收的大小依然小于某个值。因为我要处理接受到的数据必须等它完全收完才能处理,而且每次数据大小是不确定的。我无法确定是否已经收完了。所以我现在仍然只能发送小于该最值的包,就能一次收完处理,但这样发送次数就太多了,还请你继续帮我分析一下。
办法判断,换句话说,会话过程由应用程序实现。
在信息头里面包含文件长度等信息,接下来连接的发送文件数据。
客户端通过信息头取得文件下载长度,判断何时文件传完。
它是将数据成块发送,数据块规定标识头,块长度,数据块内容。
也能保证双方一问一答。。
这种方式便于交互式控制。用来传文件,象HTTP那样连续无应答要快一些。
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);我再试试看。
安装很方便,详细看一下delphi中自带的例子吧,有介绍。
能说说“拦截者”技术吗?在那里安装?delphi中相关自带的例子名字和路径是?
请指导,谢谢
做到正确的发送和接受数据,但是整个传输时间并不能缩短啊!有什么思路能缩短整个传输时间?请指教。分不够可以另外再开贴加。谢谢!
觉得,不管采取组塞或非组塞的方式,传输的总的时间都会很长。因为每次传输的数据量有限,那么传输次数就有很多很多次。想请教大家,有什么办法能缩短总的传输时间。是不是和SERVER建立很多连接,将文件在这些连接上同时分包发送?然后在SERVER端组合?但个人觉得并不是这样。请大家指导!谢谢
2、改变应答方式,校验正确不回答,校验错误发错误应答。
3、用UDP方式。
传输时间能缩短也是很有限的..能提高几个百分点就已经难得了..
显然,好象你要的好象不是这么点点...
换硬件的效果显然明显些...一般传输要稍好些,有几方面可以着手..
1,减少TCP连接次数..
2,减少应答...特别是应用层次上的应答.
3,数据压缩..
4,在某些情况下(用户多,网络不够通畅),多个连接也许会收到一点效果..(有时候效果相反)
看到一些P2P软件,下载速度并不慢啊!还有WINDOWS右键下载另存,速度也有100多K。
不知道有什么思路可以实现。
其实我的问题是这样的:我想将文件数据和其他命令信息都定义成自己格式的数据包来发送接受。但是,在不同的网络状况下,发送和接受的大小有很大区别,所以,数据包的边界无法确定,不能通过某种手段来识别是文件包还是命令包。很多人的处理方式是应答后就只管接受数据了,不去判断是什么类型的包,也就是说在开始接受文件信息后,就将收到的字节只管写文件就OK了,。我原想可以按自己定义的数据包的长度来接受解包处理,现在发现存在上述的问题,所以采用别的方式了。TO halfdream(哈欠) :你讲的很详细,谢谢你对这个问题的关注。大家还有什么高见吗?如果能有正确解析包类型和数据的思路请指导,(注意在WWW,发送和接受数据的大小是不确定的。接受端能保证完整的正确的接受到发送端的数据,但是边界就需要自己确定了)
要是没有的话,等下就给分,谢谢!
char Flag[6]; 标志
int Index; 数据包编号
int Size; 包长度
int CRC; CRC校验码
char Data[1024] 1K字节的数据包(可以变长)
在这种情况下,边界很难确定.你收取下来的数据并不是以包头开始的,那么解包就有问题了.
这是WINDOWS下的TCP/IP协议规定的,不过可以更改。
这个问题,只能自己重新组包。
俺以前用modem,同样走tcp,当然不是用delphi,实现的远程数据库同步,也没有分包呀。
数据量是几十兆,压缩后为5~10兆左右,没有达到100兆,但量级查不多。
s 接收到命令,得到长度
c 发送指定长度的数据。不必封包,直接把数据发送出去。
注意如果send操作返回的数据如果小于要发送的数据长度,那么忽略过刚才已经发送的数据,再次调用send,反复调用send
一直到已经发送的数据长度等于待发送的数据长度。
s 接收数据。把接收到的数据放入缓存(当然可以用文件等存储设备),检查总长度,如果长度够了,接收结束。
注:接收数据操作可能要做许多次
over了如果使用tcp,根本就不用考虑要发送的数据的封包问题!tcp的作用就是保障数据的正常顺序到达!
除非,考虑到服务器的缓存等等方面,你自己额外限制每次发送数据的长度。
http://expert.csdn.net/Expert/topic/1691/1691527.xml?temp=.1613886里的做法就是你描述的,你这样做,在这个连接上开始传文件后就不能处理其他的信息了,而且不能同时接受多个用户的请求。
c封包发送
s接收到数据,把数据追加到缓冲区,解释缓存区中已经有的数据。
把解析出来的数据放入目标数据中,在缓冲中清除已经解析完的数据, 注意:此时,在缓
冲管理器中可能还有数据没有解析完成,需要和下次到达的数据组合起来解释。解析出来
的数据可能是命令,也可能是数据流的某个段。这样肯定可以保证你自己定义包的封装格式(不用校验),如果你同时传递数据和控制命令,那么做不同的封装
只要你的缓冲管理器能解释出来就行了。
注意:封装过程要做封装标识的转义。解释过程做转义的解释。多个客户端有什么问题吗?每个客户端是独立的一个连接呀!你用线程也好,完成端口也好,或者什么其他的东西都好,每个连接都能独立管理起来,难道还能混乱吗?多个客户端的情况在服务器看来,每个连接都是不同的,每个连接都有socket状态。在程序实现的时候当然要考虑多个兵法请求,但不影响对所谓的大数据量的传输的设计模式嘛
搞不懂........
再小声地说:有些朋友似乎还没有搞清楚socket的基本概念嘛
1、服务端先把有关文件的大小和分块大小信息传送到客户端。
2、客户端根据文件大小和分块大小建立一个对照表,每一个数据块对应表中一个纪录。
3、服务端分块发送全部文件,每一块有一个校验码。但不等待客户端返回校验信息而连续发送。
4、客户端接收经校验正确的数据包后写入文件,同时把对照表相应纪录做标记。
5、服务端发完文件后通知客户端,客户端把校验错误或未收到的包编号发给服务端。
6、服务端把按照收到的需要重发的包编号重发数据包。
7、客户端全部校验正确后通知服务端结束文件传输。以上文件传输思路我的用UDP发送文件程序中已经成功实现。这好像也应该适用于多客户端的文件传送。