【belllab】: readln确实是判断是否有0D 0A,有就是一行结束了 如果你的数据内有0D 0A出现,那就建议用SendBuf这种方式来发送(packed)
【Kalibu】: 很感谢你的解答。 现在的关键问题是接受,如果发送你说建议用sendbuffer,那么接受用readbuffer么?请问你知道有什么相关的例子程序么?因为以前没用过这个,不清楚它的机制和用法,自己用了一下readbuffer发现会把每个长帧分成几个短帧了,不知道这个是什么原因呢? 因为任务急,我又初次用这个很茫然,希望各位不吝赐教,谢谢啦!^_^
【belllab】: 一般的发送包体的这种方式,都是有包头的,包头很简单,一般就是需要读取的包的大小,取了包头之后,就按包头里面的大小来取包体。 例如: THeader=record( Total_Length:UInt; //消息总长度(含消息头及消息体) Command_ID :UInt; //命令标识 Sequence_ID :UInt; //消息流水号,顺序累加,步长为1,循环使用 end; ) ReadBuffer(Header,SizeOf(THeader))//取包头, ReadBuffer(Body,Header.Total_Length-SizeOf(THeader));//根据包头取包体
【Kalibu】: 多谢解答! 请问那个包头THeader是自己定义的么?是不是要像你例举的Theader那样根据自己报文的协议定义这么一个record,每次先读包头,然后从包头里找出长度再读到我要的缓冲区里? 我现在的程序是: procedure TTCP_Client.IdTCPServerExecute(AThread: TIdPeerThread); var connected: boolean; aIn:array[0..2047] of Byte; i,ilen: integer; begin connected:= true; for i:=0 to 2047 do aIn[i]:=0; AThread.Connection.ReadFromStack; ilen := AThread.Connection.InputBuffer.Size;
if ilen<>0 then begin AThread.Connection.ReadBuffer(aIn,ilen); end; end; 这种根据AThread.Connection.InputBuffer.Size来读是不是不对? 另外在这个IdTCPServerExecute在ReadBuffer之前还要作其他动作么?我查help里的ReadBuffer他说要用ReadFromStack从而保证读到的buufer里至少有已经定义的size长度的数据,可是我用了上面写的程序很容易死在那里,出现错误,是不是我的用法还是不对呢?
太菜了,不好意思这么多疑问。
【belllab】: 你之种读法不是太好,很容易出现合包 THeader是自定义的,里面就包含这个包有多大, 然后再读取指定的大小,这样,就不会读多或读少
【sanmaotuo】: 其实你定义好你的传送包数据结构(通常定义为Record),然后直接传送记录就可以了.给你一个我的实例.
注意,在定义RECORD的域类型是STRING时,设计定长为最大长度255, 如果不够就用定义ARRAY STRING.
TArrayString = array[0..99] of String[255]
TClient = packed record Name: string[50]; Time: string[50]; Host: string[50]; IP: string[50]; MAC: string[50]; Msg: TArrayString; end; PTClient = ^TClient;
......写 IdTCPClient.WriteBuffer(FClientSend, SizeOf(FClientSend), True);
......读 AThread.Connection.ReadBuffer(Client, SizeOf(Client));
【Kalibu】: 那么ReadFromStack该怎么用呢?是否可以用它的返回值来判断是不是已经收到我需要的字节数,比如先判断是不是有收到足够字节的包头,然后再把包头读到buffer里? |