2012-02-07 3 views
4

Indy TCP 연결에 문제가 있습니다. Indy 10과 함께 Turbo Delphi 2006을 사용합니다. idTCPClient에서 idTCPServer로 여러 TCP 패키지를 보내려고합니다.패키지를 너무 자주 보낼 때 Indy TCPServer가 TCPClient에서 모든 패키지를 수신하지 않습니다.

하나의 패키지 만 보내고 싶거나 두 함수 호출 사이에 sleep (100) 명령을 삽입 할 때 잘 동작합니다. 하지만이 함수를 너무 자주 호출하면 매번 서버의 onExecute를 호출하지 않습니다. 보내는

내 코드 :

procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext); 
var 
    data: TIdBytes ; 
begin 
    AContext.Connection.IOHandler.ReadBytes(data, 4, false) 
    // processing data 
end 
: 나는 (두 번째에 5 ~ 10 회)이 함수를 여러 번 호출하고 내 서버 응용 프로그램에서 이러한 모든 패키지를 처리 ​​할

procedure SendData(var data: TIdBytes) ; 
begin 
    FormMain.IdTCPClient.Connect ; 
    FormMain.IdTCPClient.Socket.Write(data); 
    FormMain.IdTCPClient.Disconnect ; 
end ; 

미리 답변 해 주셔서 감사합니다.

답변

4

Connect()을 호출 할 때마다 새 연결을 만들고 TIdTCPServer은 새 풀을 시작하여 해당 연결을 처리합니다 (스레드 풀링을 사용 가능하게 설정하지 않은 경우). 그게 네가 정말로 원하는거야? 클라이언트가 일정 기간 동안 연결을 열린 상태로두고 가능한 한 많이 기존 연결을 다시 사용하는 것이 더 효율적입니다. 잠시 동안 유휴 상태 일 때와 같이 실제로는 더 이상 필요하지 않을 때만 연결을 끊습니다. 새 연결을 설정하는 것은 양 끝 모두에서 비용이 많이 드는 작업이므로 최대한 오버 헤드를 줄여야합니다. 클라이언트 측에

, 당신은 Write(data)를 호출 할 때, 그것은 전체 TIdBytes 보낼 것이다, 그러나 당신은 많은 바이트를 기대할 어떻게 과학적 이해 있도록 서버에 그 TIdBytes의 길이를 전송하지 않습니다. TIdIOHandler.Write(TIdBytes) 당신을 위해 그렇게하지 않으면 수동으로해야합니다.

서버 측에서는 ReadBytes()에 한 번에 4 바이트 만 읽도록 지시하고 있습니다. 각 블록의 4 바이트 후, OnExecute 이벤트 핸들러를 종료하고 다음 블록의 4 바이트를 읽기 위해 다시 호출되기를 기다리고 있습니다. 클라이언트 소스의 길이가 TIdBytes 인 경우가 4의 짝수 배가 아닌 한 ReadBytes()은 클라이언트의 마지막 블록을 4 바이트 미만으로 읽으려고하면 서버 연결이 끊어 지므로 예외가 발생하므로 서버 코드가 그 블록을받지 못한다.

대신을 시도해보십시오

그와
procedure SendData(var data: TIdBytes) ; 
begin 
    FormMain.IdTCPClient.Connect; 
    try 
    FormMain.IdTCPClient.IOHandler.Write(Longint(Length(data))); 
    FormMain.IdTCPClient.IOHandler.Write(data); 
    finally 
    FormMain.IdTCPClient.Disconnect; 
    end; 
end; 

procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext); 
var 
    data: TIdBytes; 
begin 
    with AContext.Connection.IOHandler do 
    ReadBytes(data, ReadLongint, false); 
    // process data 
end; 

말했다 클라이언트 코드를 변경하면 TIdBytes 길이가 어떤 이유에서 옵션을 선택하지 않습니다 보낼 수 있다면, 대신이 서버 코드를 사용

procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext); 
var 
    LBytes: Integer; 
    data: TIdBytes; 
begin 
    // read until disconnected. returns -1 on timeout, 0 on disconnect 
    repeat until AContext.Connection.IOHandler.ReadFromSource(False, 250, False) = 0; 
    AContext.Connection.IOHandler.InputBuffer.ExtractToBytes(data); 
    // process data 
end; 

또는 :

procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext); 
var 
    strm: TMemoryStream; 
    data: TIdBytes; 
begin 
    strm := TMemoryStream.Create; 
    try 
    // read until disconnected 
    AContext.Connection.IOHandler.ReadStream(strm, -1, True); 
    strm.Position := 0; 
    ReadTIdBytesFromStream(strm, data, strm.Size); 
    finally 
    strm.Free; 
    end; 
    // process data 
end; 

또는 :

procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext); 
var 
    strm: TMemoryStream; 
begin 
    strm := TMemoryStream.Create; 
    try 
    // read until disconnected 
    AContext.Connection.IOHandler.ReadStream(strm, -1, True); 
    // process strm.Memory up to strm.Size bytes 
    finally 
    strm.Free; 
    end; 
end; 
+0

답장을 보내 주셔서 감사합니다. 패키지를 하나의 큰 패키지로 병합했습니다. 스트림으로 읽었고 이제는 작동합니다. 감사! – hunyadym