从德尔福IdTCPServer连接读取的字节数量不明

问题描述 投票:0回答:1

我设立一个客户机/服务器程序在我的应用程序发送和接收的字节数量不明。如何接收未知缓冲区大小在我的计划?

我把我的数据TIdBytes变量,这条线将其发送:

IdTCPClient.IOHandler.Write(TIdBytes_Var);

TIdBytes_Var的第一字节确定分组大小和变化由于其它条件。我照顾包的大小不超过1024字节。

在接收端(IdTCPServerExecute)我加入这行读取所有字节:

var
  byte_buffer: TIdBytes;
begin
  AContext.Connection.IOHandler.ReadBytes(byte_buffer,-1,false); 
end;

在调试模式,之后我从客户端发送第一个数据包到服务器,则会引发异常情况:

有消息“””引发的异常类EConvertError不是有效的浮点值

以及运行模式,唯一的损失我的连接。

问题出在哪里,我怎么能收到来自印第安纳波利斯的输入缓冲区中的所有字节?

这里是我的最少的代码:

在客户端进行传递给其他线程包,最后设置的事件

//create packet. Buffer_to_send is a TIdBytes variable on unit of network thread (U_network_thread).
SetLength(U_network_thread.Buffer_to_send,(6 + (tmp_ints * 12)));//set buffer lenght dynamically, tmp_ints is my record counter(shortint)
tmp_int:= 2;//tmp_int is the integer variable
U_network_thread.Buffer_to_send[0]:= $1;//header sign
U_network_thread.Buffer_to_send[1]:= tmp_ints;//tmp_ints is my record counter as short integer
while tmp_ints > 0 do
begin
  Read(My_File,tmp_rec);//read record from bin file
  Move(tmp_rec,U_network_thread.Buffer_to_send[tmp_int],12);//12 is record lenght
  tmp_int:= tmp_int + 12;   //add pointer
  dec(tmp_ints);
end;
tmp_int2:= zone_i;//integer info
Move(tmp_int2,U_network_thread.Buffer_to_send[tmp_int],4); //add info to the packet
Frq_Evt.SetEvent;   //set event to triger sending on other thread

在net_thread,通过ReadLn命令连接到服务器并接收ACK标志后,我等待事件

procedure TNetThread.Execute;
  .//create IdTCPClient1 and connect to server
  .//receive ack from server by IdTCPClient1.IOHandler.ReadLn command
  .//wait for event
  while(true) do
    if (FEvent.WaitFor(200) = wrSignaled) then//Buffer_to_send fill on main thread
    begin
      //send buff
      if sending_buf(Buffer_to_send) then
      begin
        //sending ok
      end
      else
      begin
        //sending error
      end;
    end;
  end;
end;

function TNetThread.sending_buf(T_Buffer: TIdBytes): boolean;
begin
  try
    IdTCPClient1.IOHandler.Write(T_Buffer)
    result := true;
  except
    result := false;
  end;
end;

在服务器端,连接后,通过WriteLn指令发送ACK标志,并在IdTCPServerExecute我尝试做

procedure Tmain_form.IdTCPServerExecute(AContext: TIdContext);
var
  byte_buffer: TIdBytes;
begin
  AContext.Connection.IOHandler.ReadBytes(byte_buffer,-1,false);
  //do something else
end;

所有的工作很好,通过连接和服务器发送ACK标志的客户端。客户接受它,并等待事件。事件发生后,客户端组成数据包,并把它传递给net_thread。包好,送过。但是在服务器端提高的问题。

indy10 delphi-10.2-tokyo
1个回答
0
投票

TIdBytes_Var的第一字节确定分组大小和变化由于其它条件。

因此,然后只需读取1个字节,然后再阅读了多少额外的字节表示,如:

AContext.Connection.IOHandler.ReadBytes(byte_buffer, AContext.Connection.IOHandler.ReadByte, false);

我照顾包的大小不超过1024字节。

一个字节不能超过255个,所以你的最大数据包大小是256,包括大小字节。

在调试模式后,我送第一个数据包从客户端到服务器的上涨问题时收到了:“出现的异常类EConvertError与消息‘’”是不是有效的浮点值”

有没有办法,你已经证明可以提高该异常的代码。

更新

这里是我的最少的代码

现在看到你的代码,我可以看到,尽管你刚才的要求,你的数据包的第一个字节是不是一个数据包的大小,它总是$01。事实上,是存储在数据包完全没有数据包大小。该第二字节包含的存储在分组12字节记录的数目,并且分组具有6个固定字节,因此最大分组大小实际上是3066个字节。

尝试更多的东西是这样的:

传递给其他线程

// create packet. Buffer_to_send is a TIdBytes variable on unit of network thread (U_network_thread).
SetLength(U_network_thread.Buffer_to_send, (6 + (tmp_ints * 12))); // set buffer length dynamically, tmp_ints is my record counter(shortint)
tmp_int := 2; // tmp_int is the integer variable
U_network_thread.Buffer_to_send[0] := $1; //header sign
U_network_thread.Buffer_to_send[1] := tmp_ints; // tmp_ints is my record counter as short integer
while tmp_ints > 0 do begin
  Read(My_File, tmp_rec); // read record from bin file
  Move(tmp_rec, U_network_thread.Buffer_to_send[tmp_int], 12); // 12 is record length
  Inc(tmp_int, 12); // add pointer
  Dec(tmp_ints);
end;
tmp_int2 := GStack.HostToNetwork(UInt32(zone_i)); // integer info, in network byte order
Move(tmp_int2, U_network_thread.Buffer_to_send[tmp_int], 4); // add info to the packet
Frq_Evt.SetEvent; // set event to trigger sending on other thread

procedure Tmain_form.IdTCPServerExecute(AContext: TIdContext);
var
  byte_buffer: TIdBytes;
  Header: Byte;
  Count: Word;
  Zone: Integer;
begin
  Header := AContext.Connection.IOHandler.ReadByte; // should always be $01
  Count := AContext.Connection.IOHandler.ReadByte; // record counter
  AContext.Connection.IOHandler.ReadBytes(byte_buffer, Count * 12); // records
  Zone := AContext.Connection.IOHandler.ReadInt32; // zone
  // process as needed...
end;
© www.soinside.com 2019 - 2024. All rights reserved.