2013-09-25 17 views
1

我想在Delphi 2007中使用Indy10 ReadBytes()來讀取格式爲[#bytes] \ r \ n的一系列數據段的大量下載,其中#bytes指示字節數。我的算法是:Indy 10 IdTCPSever讀取字節加擾數據

  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 |開始 線| A033167 | B033167 | C033167 | D033167 | E033167 | F033167 | G033167 | H033167 | ENDL \ r |開始 線| 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); 
+1

請顯示一些代碼。 –

+1

爲什麼在步驟1中使用ReadBytes()而不是ReadLn()?當[#]是負值時,這意味着什麼? –

回答

0

嵌入式數據像你描述的,尤其是在隨機時間,當你從同時在多個線程在同一插座他們之間沒有足夠的同步讀取通常發生。一個線程可能會接收一部分傳入數據,而另一個線程可能會接收另一部分數據,並且它們最終會以錯誤的順序將其數據存儲在InputBuffer中。很難肯定地說,如果你的問題沒有提供任何代碼。最好的選擇是確保你永遠不會從多個線程中的同一套接字讀取數據。這包括對Connected()的任何調用,因爲它在內部執行讀取操作。你應該在單個線程中完成所有的閱讀。如果這不是一個選項,那麼至少用一些線程間鎖定來封裝你的套接字I/O,比如臨界區或互斥鎖。

更新:你是通過你自己的AClientDebugSocketContext變量訪問TIdContext對象。代碼正在被使用到哪裏?如果不是在服務器的OnConnectOnDisconnectOnExecute,或OnException事件的情況下,那麼你是從多個線程在同一插座讀書,因爲TIdTCPServer內部調用Connected()(其中不讀)的調用之間的OnExecute事件爲那個TIdContext對象。

+0

感謝您的回覆。我們在一個線程中進行套接字讀取,並且不要調用Connected()。下面是相關的代碼片段: '...... text.Connection.Socket.ReadBytes(inBuffer,byteCount,True);' 'numBytes:= Length(inBuffer);' 'Logger.WriteToLogFile(BytesToString(inBuffer,0, numBytes),0);' 'Move(inBuffer [0],Pointer(Integer(Buffer))^,numBytes);' –

+0

我更新了我的答案。 –

+0

感謝您的更新。看起來我們可能正在執行OnExecute()事件處理程序之外的ReadBytes()調用。我正在進一步調查。 –