我有两个使用Delphy 10.3和Indy 10 idTCPServer和idTCPClient0的程序:
服务器端:
客户端:
问题
问题-这可能是缓冲区问题吗?还是计时器会覆盖已经在缓冲区中但尚未由客户端读取的数据集2?我有什么办法可以克服这种情况?
type
TData1 = record // 11 bytes record
{header:}
MessageStart : Array[1..4] of Char; // 0
MessageID : word; // 4
{content:}
TransactionNo : Integer; // 6
TrackerMsgID : byte; // 10
end;
type
TAcknowledgeData1 = record // 14 bytes record
{Header:}
MessageStart : Array[1..4] of Char; // 0
MessageID : Word; // 4
{content:}
TransactionNo : Integer; // 6
EventID : Integer; // 10
end;
客户端具有一个计时器,该计时器定期将Dataset1发送到服务器,并调用过程SendData1:
procedure TForm1.TimerClientTimer(Sender: TObject); begin SendData1(TransactionNr); TransactionNr := TransactionNr + 1; end; procedure TForm1.SendData1 (Transaction: Integer); var Data1 : TData1; Data1Array : TIDBytes; begin {fill the data1 record:} Data1.MessageStart := '$MSG'; //4 bytes Data1.MessageID := 1; //2 bytes Data1.TransactionNo:= Transaction; //4 bytes Data1.TrackerMsgID := 1; //1 byte {set the length of idBytes to get the dta 1 record:} setLength (Data1Array,11); {move data1 record to idBytes array:} Move (Data1.MessageStart[1],Data1Array[0],1); Move (Data1.MessageStart[2],Data1Array[1],1); Move (Data1.MessageStart[3],Data1Array[2],1); Move (Data1.MessageStart[4],Data1Array[3],1); Move(Data1.MessageID, Data1Array[4],sizeOf(Word)); Move(Data1.TransactionNo,Data1Array[6],sizeOf(Integer)); Move(Data1.TrackerMsgID, Data1Array[10],sizeOf(Byte)); try TCPClient.IOHandler.Write(Data1Array); if chkData.checked then MemoClient.Lines.Add('Client sent Data1:'+inttostr(Data1.TransactionNo)); except on E: Exception do begin {nothing} if chkData.checked then MemoClient.Lines.Add('Exception occured'); end; end; end;
一旦确认数据包从服务器到达,客户端的工作线程正在调用DataReceived:
procedure TForm1.TimerClientTimer(Sender: TObject); begin SendData1(TransactionNr); TransactionNr := TransactionNr + 1; end; procedure TForm1.SendData1 (Transaction: Integer); var Data1 : TData1; Data1Array : TIDBytes; begin {fill the data1 record:} Data1.MessageStart := '$MSG'; //4 bytes Data1.MessageID := 1; //2 bytes Data1.TransactionNo:= Transaction; //4 bytes Data1.TrackerMsgID := 1; //1 byte {set the length of idBytes to get the dta 1 record:} setLength (Data1Array,11); {move data1 record to idBytes array:} Move (Data1.MessageStart[1],Data1Array[0],1); Move (Data1.MessageStart[2],Data1Array[1],1); Move (Data1.MessageStart[3],Data1Array[2],1); Move (Data1.MessageStart[4],Data1Array[3],1); Move(Data1.MessageID, Data1Array[4],sizeOf(Word)); Move(Data1.TransactionNo,Data1Array[6],sizeOf(Integer)); Move(Data1.TrackerMsgID, Data1Array[10],sizeOf(Byte)); try TCPClient.IOHandler.Write(Data1Array); if chkData.checked then MemoClient.Lines.Add('Client sent Data1:'+inttostr(Data1.TransactionNo)); except on E: Exception do begin {nothing} if chkData.checked then MemoClient.Lines.Add('Exception occured'); end; end; end;
一旦服务器发送数据包,客户端的工作线程正在调用DataReceived:
procedure TForm1.Datareceived (Data : TidBytes); var MsgStart : array[1..4] of char; s : string; id : word; Data1: TData1; Data2: TData2; Ack : TAcknowledgeData1; AckArray: TidBytes; begin {get the header:} s := bytestostring(Data,0,4); if s = '' then exit; move (Data[4],id,sizeof(word)); if (s = '$MSG') then begin if (ID=3) then begin move(Data[0],Ack.MessageStart,0); Ack.MessageID := id; Move (Data[6],Ack.TransactionNo,SizeOf(Word)); Move (Data[10],Ack.EventID,SizeOf(Integer)); LastAck := Ack.TransactionNo; end; end; end;
服务器在客户端发送Data1程序包后立即调用DataReceved过程。服务器将确认包发送回客户端:
procedure TForm1.Datareceived (Data : TidBytes); var MsgStart : array[1..4] of char; s : string; id : word; Data1: TData1; Data2: TData2; Ack : TAcknowledgeData1; AckArray: TidBytes; begin {get the header:} s := bytestostring(Data,0,4); if s = '' then exit; move (Data[4],id,sizeof(word)); if (s = '$MSG') then begin {Server received Data1:} if (ID=1) then begin {get data1:} move(Data[0],Data1.MessageStart,0); Data1.MessageID := id; move (Data[6],Data1.TransactionNo,sizeOf(Integer)); move (Data[10],Data1.TrackerMsgID,sizeOf(Byte)); {send Acknowledge to client} Ack.MessageStart := '$MSG'; Ack.MessageID := 3; Ack.TransactionNo:= Data1.TransactionNo; Ack.EventID := LastEventID; LastEventID := LastEventID + 1; SetLength(AckArray,14); Move (Ack.MessageStart[1],AckArray[0],1); Move (Ack.MessageStart[2],AckArray[1],1); Move (Ack.MessageStart[3],AckArray[2],1); Move (Ack.MessageStart[4],AckArray[3],1); Move (Ack.MessageID,AckArray[4],sizeOf(Word)); Move (Ack.TransactionNo,AckArray[6],sizeOf(Integer)); Move (Ack.EventID,AckArray[10],sizeOf(Integer)); try ClientPortIdContext.Connection.IOHandler.Write(AckArray); except end; end;