1

我正在尝试在 Delphi 2007 中使用 Indy10 ReadBytes() 来读取格式为 [#bytes]\r\n 的一系列数据段的大量下载,其中 #bytes 表示字节数。我的算法是:

  1. 使用 ReadBytes() 获取 [#]\r\n 文本,通常为 10 个字节。
  2. 使用 ReadBytes() 获取指定的 # 个数据字节。
  3. 如果需要处理更多的数据段,即#为负数,则转至步骤1。

这很好用,但我经常在第 1 步没有得到预期的文本。下面是 330 个成功数据段后的简短示例:

从上一步 2 ReadBytes() 收到的数据。注意嵌入的步骤 1 [-08019]\r\n 文本。

Line|A033164|B033164|C033164|D033164|E033164|F033164|G033164|H033164|EndL\r|Begin 
Line|A033165|B033165|C033165|D033165|E033165|F033165|G033165|H033165|EndL\r|Begin 
Line|A033166|B033166|C033166|D033166|E033166|F033166|G033166|H033166|EndL\r[-08019]

\r\n|Begin Line|A033167|B033167|C033167|D033167|E033167|F033167|G033167|H033167|EndL\r|Begin Line|A033168|B033168|C033168|D033168|E033168|F033168|G033168|H033168|EndL\r |开始

WireShark 捕获的套接字数据。

0090 30 33 33 31 36 36 7c 42 30 33 33 31 36 36 7c 43 033166|B033166|C
00a0 30 33 33 31 36 36 7c 44 30 33 33 31 36 36 7c 45 033166|D033166|E
00b0 30 33 33 31 36 36 7c 46 30 33 33 31 36 36 7c 47 033166|F033166|G
00c0 30 33 33 31 36 36 7c 48 30 33 33 31 36 36 7c 45 033166|H033166|E
00d0 6e 64 4c 0d ndL.

编号 时间 源 目的地 协议 长度 信息

2837 4.386336000 000.00.247.121 000.00.172.17 TCP 1514 40887 > 57006 [ACK] Seq=2689776 Ack=93 Win=1460 Len=1460
Frame 2837: 1514 bytes on wire (12112 bits), 1514 bytes captured (12112 bits) on interface 0
Ethernet II, Src: Cisco_60:4d:bf (e4:d3:f1:60:4d:bf), Dst: Dell_2a:78:29 (f0:4d:a2:2a:78:29)
Internet Protocol Version 4, Src: 000.00.247.121 (000.00.247.121), Dst: 000.00.172.17 (000.00.172.17)
Transmission Control Protocol, Src Port: 40887 (40887), Dst Port: 57006 (57006), Seq: 2689776, Ack: 93, Len: 1460
Data (1460 bytes)

0000 5b 2d 30 38 30 31 39 5d 0d 0a 7c 42 65 67 69 6e [-08019]..|Begin
0010 20 4c 69 6e 65 7c 41 30 33 33 31 36 37 7c 42 30 Line|A033167|B0
0020 33 33 31 36 37 7c 43 30 33 33 31 36 37 7c 44 30 33167|C033167|D0
0030 33 33 31 36 37 7c 45 30 33 33 31 36 37 7c 46 30 33167|E033167|F0

有谁知道为什么会这样?谢谢

更多信息。我们从单个线程进行套接字读取,并且在读取时不调用 Connected()。这是相关的代码片段:

AClientDebugSocketContext.Connection.Socket.ReadBytes(inBuffer,byteCount,True);
numBytes := Length(inBuffer);
Logger.WriteToLogFile(BytesToString: '+BytesToString(inBuffer,0,numBytes),0);
Move(inBuffer[0], Pointer(Integer(Buffer))^, numBytes);
4

1 回答 1

0

像您描述的嵌入式数据,尤其是在随机时间,通常发生在您同时从多个线程中的同一个套接字读取而它们之间没有足够的同步时。一个线程可能会接收部分传入数据,而另一个线程可能会接收另一部分数据,最终它们InputBuffer以错误的顺序存储数据。很难确定这是否是您的问题,因为您没有提供任何代码。最好的选择是确保您根本不会在多个线程中从同一个套接字读取。这包括任何调用Connected(),因为它在内部执行读取操作。您应该在一个线程中完成所有阅读。如果这不是一个选项,那么至少使用某种线程间锁来包装您的套接字 I/O,例如临界区或互斥锁。

更新:您正在TIdContext通过自己的AClientDebugSocketContext变量访问对象。该代码到底在哪里使用?如果它不在服务器的OnConnectOnDisconnectOnExecuteOnException事件的上下文中,那么您正在跨多个线程从同一个套接字读取,因为在调用该对象的事件之间进行TIdTCPServer内部调用Connected()(执行读取) 。OnExecuteTIdContext

于 2013-09-25T17:18:38.667 回答