关于TServerSocket与TClientSocket的一个问题(20分)

  • 主题发起人 主题发起人 amdcwf
  • 开始时间 开始时间
A

amdcwf

Unregistered / Unconfirmed
GUEST, unregistred user!
程序中C端要向S端发送的消息有不同种类的,所以一般发送的消息是不定长的,比如有时候用SendText()来发送,有时又是用SendBuffer()来发送,所以在接收时S端怎么知道该用ReceiveBuffer()来收还是用ReceiveText()呢?
或着如果都用ReceiveBuffer来收,那又怎么知道应该接收多大的字节数呢。
(receiveLength这个属性没有用,因为它只能用来返回说当前接收缓冲有多少个未接收的字节)
那么在S端该如何以统一的方式来接收这些消息?
对于这个问题,我在程序中用了双端口,一个用来接状态消息,一个用来接收数据消息
也就是说,在C端要发送数据时,先通过状态端口发送一个状态消息说,即将开始发送数据
并且这个消息含有要发送数据的大小,此时,S端检查数据端口是否忙,如果忙则通过状态端口给C端发送一个忙消息。这样发送数据端口与发送状态的端口就分开了,也就解决了问题。
不过,我想肯定有更简单的方法
请大侠们发挥一下
 
receiveLength就是当前缓冲区未就收的字节,随后的receiveBuffer()会读取缓冲区这些字节并清空缓冲区!!!清空以后又接收的字节难道不是网络中传送过来的?不会是电脑自动胡乱产生的吧,哈
 
你没听懂我的意思,
我是说ReceiveLength只是表明当前接收缓冲区未接收的字节数
它总是小于等于我在C端发送的字节数,举个例子:
C端:SendBuf(p,20000);
那么一般情况下,S端在一次OnClientRead事件里将不会收到全部的20000字节
也就是说,在S端会产生多次的OnClientRead事件,直到所有的20000字节都放在了接收缓冲区中,那么我在OnClientRead事件中的处理程序将不只执行一次。而原本的意图是想在C端发送一次,在S端也只产生一次OnClientRead事件,这样才能符合我的程序逻辑!
要不然,在异步方式下,由于多次激发OnclientRead事件那么在事件处理程序中的ReceiveBuf()将只收到最后一次激发OnClientRead事件的数据
大侠们说说,是不是这样的啊!
 
tcp/ip协议在物理上一次最多能发送几个字节?据我试验,好像是1024(1K),任何逻辑处理总是以物理事实作为基础的吧,所以你把每次发送的字节数控制在1K以内,>1K就用自定义逻辑处理。
 
统一用Buffer来发送和接收,Buffer中可以加一些控制字,请参看:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1564635
 
还一种更好的方法,采用结构包的方式,可以很好的处理TCP粘包问题,我有这样的例子,前两天才做出来的,如果需要我发给你
 
我来跟你提供一些意见,你可以把你们的传输协议完善一下,比如我发的数据包中,以FF为数据包开始的标示,FD为数据包结束,这样我在receivebuf 就不用担心他的长度,而只要判断它是否为数据包结束。这样你在client端把你的数据包头和包尾 加上标示就可以咯,当然还的定义一下协议,比如如果你的数据包中有 出现FF,FD的话,用两个FF来表示
 
先定义一个结构:
SendR=Record
_Mark:Array [1..4] Of Char;
SendString : Boolean;
End;

Procedure SendCommandBuf(_SendString:Boolean;_Buf:Pointer;_Size:Integer);
Var
_SendR:SendR;
_IBuf:Packed Array [1..4096] Of Char;
Begin
Move(String('HEI!')[1],__SendR._Mark,4); // 命令头
_SendR.SendString:=_SendString;
If (_SendString) Then
ClientSocket1.SendText(String(PChar(_Buf)))
Else
Begin
Move(_Buf^,_IBuf,_Size);
ClientSocket1.SendBuffer(_IBuf,_Size);
End;
End;

例如SendCommandBuf(True,Pointer(@String('GetScreen'#0)[1]),9);
例如SendCommandBuf(False,@SendBuf,1024);
 
后退
顶部