2014-01-15 95 views
0

我對TIdTCPServer組件有問題。我用它來讀取遠程服務器發送的數據。TIdTCPServer OnExecute在無限循環中運行

下面是我使用的代碼:

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); 
const 
    START_PACKET = #11; 
    END_PACKET = #10; 
var 
    IO : TIdIOHandler; 
    c : Char; 
    a : AnsiString; 
begin 
    a := ''; 
    IO := AContext.Connection.IOHandler; 

    while (IO.InputBuffer.Size > 0) do 
    begin 
    c := IO.ReadChar; 

    if c = START_PACKET then 
    begin 
     repeat 
     c := IO.ReadChar; //(TEncoding.ASCII); 
     a := a + c; 
     until (c = END_PACKET) or (IO.InputBufferIsEmpty); 
    end; 
    end; 

    if a <> '' then 
    begin 
    //let's send replay to server 
    IO.Write(CreateReply(a)); 

    //now we need to save what we received to database 
    //I use critical section 
    try 
     EnterCriticalSection(LockDB); 

     with DataModule2.results do 
     begin 
     Close; 
     Params[0].AsDateTime := Today; 
     Params[1].AsString := a; 
     ExecSQL; 
     end; 
    finally 
     LeaveCriticalSection(LockDB); 
    end; 
    end; 
end; 

的問題是,一旦我的TIdTCPServer得到了一些數據則開始一個無限循環,並採取100%的CPU。

我在這裏做錯了什麼?

回答

2

一個問題是您從未實際讀取任何數據,因此InputBuffer將始終爲空,因此a將始終爲空。 OnExecute事件本身是循環的,所以你沒有做任何事情來使它週期性地產生CPU時間片。

另一個問題是您的字符逐字符讀取和連接效率非常低,並且它沒有考慮到SizeOf(Char)在Delphi 2009+中爲2或者ReadChar()是Unicode感知的。

試試這個:

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); 
const 
    START_PACKET = #11; 
    END_PACKET = #10; 
var 
    IO : TIdIOHandler; 
    a, buf : AnsiString; 
    buflen : Integer; 
    c : AnsiChar; 
begin 
    a := ''; 
    IO := AContext.Connection.IOHandler; 

    IO.WaitFor(START_PACKET); 

    // this is just one example of how to append characters using 
    // buffering. use whatever is more comfortable for you... 

    SetLength(buf, 1024); 
    buflen := 0; 

    repeat 
    c := AnsiChar(IO.ReadByte); 
    if buflen = Length(buf) then 
    begin 
     a := a + buf; 
     buflen := 0; 
    end; 
    buf[buflen+1] := c; 
    Inc(buflen); 
    until (c = END_PACKET) or (IO.InputBufferIsEmpty); 

    if buflen > 0 then 
    begin 
    SetLength(buf, buflen); 
    a := a + buf; 
    end; 
    buf := ''; 

    //let's send replay to server 
    IO.Write(CreateReply(a)); 

    //now we need to save what we received to database 
    //I use critical section 
    EnterCriticalSection(LockDB); 
    try 
    with DataModule2.results do 
    begin 
     Close; 
     Params[0].AsDateTime := Today; 
     Params[1].AsString := a; 
     ExecSQL; 
    end; 
    finally 
    LeaveCriticalSection(LockDB); 
    end; 
end; 

或者:

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext); 
const 
    START_PACKET = #11; 
    END_PACKET = $#10; 
var 
    IO : TIdIOHandler; 
    a : AnsiString; 
    c : AnsiChar; 
    i : Integer; 
begin 
    IO := AContext.Connection.IOHandler; 

    IO.WaitFor(START_PACKET); 

    if IO.InputBufferIsEmpty then 
    begin 
    IO.CheckForDataOnSource(IdTimeoutDefault); 
    IO.CheckForDisconnect; 
    end; 

    i := IO.InputBuffer.IndexOf(END_PACKET); 
    if i = -1 then i := IO.InputBuffer.Size; 

    a := IO.ReadString(i); 

    if a <> '' then 
    begin 
    //let's send replay to server 
    IO.Write(CreateReply(a)); 

    //now we need to save what we received to database 
    //I use critical section 
    EnterCriticalSection(LockDB); 
    try 
     with DataModule2.results do 
     begin 
     Close; 
     Params[0].AsDateTime := Today; 
     Params[1].AsString := a; 
     ExecSQL; 
     end; 
    finally 
     LeaveCriticalSection(LockDB); 
    end; 
    end; 
end; 
+0

'PKT:= IO.ReadLn(END_PACKET,Indy8BitEncoding)+ END_PACKET;'將它從服務器讀取所有的口袋?我使用D7與'indy10.1.5_d7',我相信它沒有ReadLn(END_PACKET,Indy8BitEncoding),在這種情況下我應該怎麼做?可以使用IO.ReadLn嗎? –

+0

'ReadLn()'讀取直到指定的終止符到達,然後它返回終止符之前的所有內容並丟棄終止符本身。您的原始代碼保留了您的'AnsiString'中的終止符,在我的示例中是'+ END_PACKET'部分。你是否真的需要保留終結者取決於你。至於Indy 10.1.5,它還不支持Unicode,所以只需省略「Indy8BitEncoding」部分,但仍然會將'END_PACKET'終止符傳遞給'ReadLn()'。或者升級到最新的10.6.0版本(你應該考慮從10.1.5開始做任何事情都很古老)。 –

+0

程序永遠不會傳遞下面這行代碼:'pkt:= IO.ReadLn(END_PACKET)+ END_PACKET;'好像'END_PACKET'永遠不會出現。 –