2009-06-19 32 views
0

第一個問題:爲什麼我在Indy套接字9 IdTcpServer ServerExecute中獲得AccessViolation?

以下例程是否正確實現了Indy 9 IdTcpServer.OnExecute例程?

procedure TMyConnServer.ServerExecute(AContext: TIdPeerThread); 
var 
    buffSize: integer; 
    str:  string; 
begin 
    AContext.Connection.ReadFromStack(True, 600, False); 
    buffSize := AContext.Connection.InputBuffer.Size; 
    if (buffSize > 0) then 
    { Extract input buffer as string } 
    str := AContext.Connection.ReadString(buffSize); 

    { Notify connection object of received data } 
    if (AContext.Data <> nil) then 
    begin 
     TConnectionHandler(AContext.Data).Read(str); 
    end; 
    end; 
end; 

二(實際上更重要的)問題:

現在有偶爾訪問衝突(從地址000000讀)。顯然在行中:

AContext.Connection.ReadFromStack(True, 600, False); 

但是檢查AContext/Connection/InputBuffer/IOHandler = nil BEFORE是否爲false。 調用之後(並且在異常發生後),IOHandler爲零。

我們正在使用的RAD Studio /德爾福2007年

回答

0

像你描述的IOHandler可以成爲零的唯一方法是,如果在你的應用程序),另一個線程調用斷開(上工作線程仍在運行時的連接。

0

好,最簡單的onExecute處理我已經是這樣的。 (藉口C++而不是德爾福,但你會得到的想法。

void __fastcall MyPanel::DoTCPExecute(TIdPeerThread * AThread) 
{ 
    AnsiString text =AThread->Connection->ReadLn(); 
    // now do something with text 
} 

唯一明顯的問題,我可以看到的是,你要使用的數據的「時機」,以確定當你有一個完整的字符串,這對TCP來說是一個真正的禁忌,你可能只有一個字符串的第一個字節,或者你可能有多個字符串一起發送,但對TCP而言,並不能保證每個「發送」都以單個「接收」結束「

您需要以其他方式」分隔「您的字符串Readln使用換行符作爲終止符 - 另一種方法是在每個數據塊的前面添加一個長度字段。 ,然後讀取其餘的數據。

+0

嗨,恐怕ReadLn()是沒有選擇,因爲數據沒有換行分隔符。 我知道數據可能不完整(通常不是),但重新構建稍後在.Read(str)方法中完成。 實際上,數據類型'string'僅用於傳輸原始字節(因爲這是我們以後需要的數據)。 除了:ReadLn()可以在內部也調用ReadFromStack(),這將再次導致一個EAccessViolation ... – Tarnschaf 2009-06-19 13:06:19

+0

如果數據有任何類型的分隔符,可以將該分隔符傳遞給ReadLn(),它不是僅限於CR/LF字符。如果數據以另一種方式分隔(例如通過指定如何讀取其餘數據的前一個標題),則必須單獨處理。使用字符串作爲原始字節緩衝區並不是一個好主意,特別是如果您升級到字符串行爲已更改的D2009。如果您需要對原始字節進行操作,則使用實際的原始字節緩衝區,如TBytes。 Indy有可用於讀取/寫入原始字節的方法。 – 2009-07-02 20:59:20

0

代碼工作這樣的,但我不認爲這是一個乾淨的選項:

if (AContext.Connection.Connected) then 
    begin 
    try 
     AContext.Connection.ReadFromStack(false, 1, false); 
    except on E: EAccessViolation do 
     // ignore 
    end; 
    end; 
    buffSize := AContext.Connection.InputBuffer.Size; 
+1

Indy在內部爲您處理Connected()呼叫。如果InputBuffer中仍有未讀數據(這是設計),則即使套接字可能已經關閉,Connected()也會返回True。你應該去掉對Connected()的調用以及異常處理程序(因此TIdTCPServer可以爲你處理錯誤(這對於正確的套接字管理是必需的),只需調用ReadFromStack()並讓它報告任何錯誤 – 2009-07-02 21:02:33

相關問題