讨论:如何保障ServerSocket/ClientSocket通讯中数据不丢失?(300分)

  • 主题发起人 主题发起人 chimney
  • 开始时间 开始时间
C

chimney

Unregistered / Unconfirmed
GUEST, unregistred user!
这个问题在论坛上经常有人问,好像没有好的、真正能解决问题的建议,我在写网络软件时也碰到了这些问题,希望大家能够探讨一下。
我主要是采用非阻塞模式,数据格式定义如下:
TFrameData=Packet Record
TransCode:TTransCode//主要是判断数据包该作什么操作
Data:Array[0..BufferSize] of Char//数据单元
end;
在发送前根据具体操作给TransCode赋值,将数据压入Data中,然后用SendBuf将数据包发出去:While SendBuffLength = -1 do
SendBuffLength:=ServerSocket.Socket.SendBuf(FrameData,DataSize)//这里的DataSize不一定等于SizeOf(FrameData),而是根据数据的实际长度+SizeOf(TransCode)
接收时:
While RecieveBufReturn < Socket.ReceiveLength Do
RecieveBufReturn:=Socket.ReceiveBuf(FrameData,Socket.ReceiveLength);
然后根据TransCode的直执行相应的操作:
Case TransCode of
a://相应操作
b:
end;
但时实际运行中总有数据没有收到,特别是在发送端发送频率比较高的时候,我想作为TCP协议,数据肯定是已经发送到目的地了,应该是接收时出现问题,会不会是因为多段数据同时到达而Socket只触发一次Read事件而导致后一段数据虽然接收了但在Case这一步被丢弃了?如果这样,在每一段数据的后面加一个分隔符,同时在Read的事件中用一个循环应该是可以解决的。
有些人提出可以用Sleep进行延迟,可能可以解决一些问题,但我想应该不是好办法,特别对于时间要求比较高的系统,我想应该在协议定义和系统逻辑处理上下功夫,不知道各位有什么想法,希望讨论。
 
把包的长度限定在操作系统Tcp/Ip所允许的能一次发送的范围内,我采用不大于1024Byte和应答办法,没什么问题。
不知道有没有高手能完美的解决这个问题!
 
我每次send的包大小是4K,用猫也没看见有包丢失,[:D]
 
张无忌说得对,每次发送的包不能太大,2K或4K,最好不要超过4K,ServerSocket/ClientSocket
采用Tcp/IP协议,你不要担心包丢失。
 
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2140578
 
我还是喜欢线程阻塞模式,数据发没发走,有没有接收到数据,一目了然。
 
每次发送的数据不要太大。
 
自定义一个小协议,每次收发包都有一个确认,最好还加上超时重发处理。
 
firstrose
支持!
 
哈哈,听课
 
呵呵,张无忌大侠也来了。
对于TCP而言,只要发送时系统没有报错,数据包应该都会到达目的地,我想问题应该还是出在接收端,我想问:
1、有没有可能发送端发送两段数据,接收端只触发一次接收事件,比如,在极短时间内发送‘aaa’和‘bbb’,如果接收端只触发一次事件,那么接收到的就是‘aaabbb’。
2、有没有可能如1中的一次事件中收到‘aaabb’这样的数据?
3、有没有可能如1中的一次事件中收到‘bbbaaa’这样的数据?
以上这些情况,如果没有在接收是加以判断,接收端就有可能处理时把数据抛弃而照成数据丢失的假象。
To firstrose:
你的帖子我以前看过,是不是与我的接收、发送办法类似:
While SendBuffLength = -1 do
SendBuffLength:=ServerSocket.Socket.SendBuf(FrameData,DataSize)

While RecieveBufReturn < Socket.ReceiveLength Do
RecieveBufReturn:=Socket.ReceiveBuf(FrameData,Socket.ReceiveLength);
这种办法应该是确保发送时把数据全部发出去、接收时能够将缓存的数据全部收回来,不知道我的想法是否正确。
希望有经验的朋友谈谈看法。
 
试试,shutdown这个函数吧,

服务器端刚刚发送完数据就断开,
是会发生客户端无法受到最后发送的数据的现象
应该等待客户端主动断开,等待超时后才断开
 
非阻塞模式,如果数据传输错误则产生SocketError事件;
阻塞模式,如果数据传输错误则产生超时,并汇报错误类型;
比尔盖茨和他的手下可不是吃干饭的!
你向缓冲区疯狂填数据,网卡那点可怜的带宽受得了么?
While SendBuffLength = -1 do
SendBuffLength:=ServerSocket.Socket.SendBuf(FrameData,DataSize)
试试这样做:
Count:=0;
While SendBuffLength = -1 do
begin
SendBuffLength:=ServerSocket.Socket.SendBuf(FrameData,DataSize);
Inc(C);
end;
看看C值是不是有可能〉1的数字

 
没发全当然不可能收全:

n := ServerSocket.Socket.SendBuf(xxxx, len);
if (n >0) and (n<len) then
showmessage('你个白痴')
else
showmessage('Another_eYes是白痴');

 
呵呵,公司终于放假了,可以好好陪陪女友了。

无忌兄,今年收成怎么样?好久没有见到你了。
 
就是这样!!!
 
过完年了,各位请继续讨论。
 
》》对于TCP而言,只要发送时系统没有报错,数据包应该都会到达目的地
对于局域网来说,网络环境比较好,TCP应该能够保证数据包的正确收发;但如果是较复杂的广域网,TCP也会丢包的。
 
后退
顶部