2017-04-06 4 views
0

データ(デルファイ)の送信を停止しTCPソケットは、私はソケット接続を作成し、次のコードを使用して継続的にソケットを介してデータを送信するためのスレッドを使用しています

function TSocketSession.Send(const ADataToSend: TBytes): Integer; 
var 
    Stopwatch: TStopwatch; 
    SentBytes: Integer; 
const 
    SleepTimeMS = 10; 
begin 
    SiMain.TrackMethod(Self, 'Send'); 
    {$IFDEF USE_SSL} 
    if FIsSSL then 
    begin 
    SiMain.LogInteger('SslState', Ord(FSocket.SslState)); 
    end; 
    {$ENDIF} 
    FDataSent := False; 
    if FSocket.State = wsConnected then 
    begin 
    SentBytes := FSocket.Send(@(ADataToSend[Low(ADataToSend)]), Length(ADataToSend)); 
    SiMain.LogInteger('SentBytes', SentBytes); 
    Stopwatch := TStopwatch.StartNew; 
    end; 
    while (FSocket.State = wsConnected) and (not FDataSent) do 
    begin 
    FSocket.MessagePump; 
    Sleep(SleepTimeMS); 
    if (Stopwatch.ElapsedMilliseconds >= FTimeout) then 
    begin 
     FError := CErrorCommTimeout; 
     break; 
    end; 
    end; 

    Result := FError; 
end; 

特定のPCでは、ソケットは特定の期間(通常は約1〜2分後に発生します)や問題なく実行される他のPCでデータの送信を停止することに気付きました。誰かがこれを起こす可能性のあるコード内の何かを見ていますか?私は必要に応じてより多くの情報を提供することができます。

答えて

1

コードにいくつかの問題があります。

JSONEventが空白の場合、あなたはConnectedはすでに真である場合でもConnect()を呼び出します、あなたはMsgオブジェクトをリークします。コードは、より多くの代わりにこのようになります。

if FSocketSession.Connected then 
begin 
    if Msg.JSONEvent <> '' then 
    FSocketSession.Send(TEncoding.UTF8.GetBytes(Msg.JSONEvent)); 
    Msg.Free; 
end 
else 
begin 
    FSocketSession.Connect; 
end; 

さて、TSocketSession.Send()の内側に、あなたがループ内FSocket.Send()を呼び出す必要があります。 TCPソケットは、要求した数だけ送信することは保証されていません。返されるバイト数は少なくなります。そのため、実際に送信されたバイト数が返されます。あなたはそれを考慮する必要があります:

function TSocketSession.Send(const ADataToSend: TBytes): Integer; 
const 
    SleepTimeMS = 10; 
var 
    Stopwatch: TStopwatch; 
    SentBytes, BytesToSend: Integer; 
    PData: PByte; 
begin 
    SiMain.TrackMethod(Self, 'Send'); 
    {$IFDEF USE_SSL} 
    if FIsSSL then 
    begin 
    SiMain.LogInteger('SslState', Ord(FSocket.SslState)); 
    end; 
    {$ENDIF} 
    FDataSent := False; 
    if FSocket.State = wsConnected then 
    begin 
    PData := PByte(ADataToSend); 
    BytesToSend := Length(ADataToSend); 
    while BytesToSend > 0 do 
    begin 
     SentBytes := FSocket.Send(PData, BytesToSend); 
     SiMain.LogInteger('SentBytes', SentBytes); 
     if SentBytes <= 0 then 
     begin 
     // error handling ... 
     Result := ...; 
     Exit; 
     end; 
     Inc(PData, SentBytes); 
     Dec(BytesToSend, SentBytes); 
    end; 
    Stopwatch := TStopwatch.StartNew; 
    end; 
    while (FSocket.State = wsConnected) and (not FDataSent) do 
    begin 
    FSocket.MessagePump; 
    Sleep(SleepTimeMS); 
    if (Stopwatch.ElapsedMilliseconds >= FTimeout) then 
    begin 
     FError := CErrorCommTimeout; 
     break; 
    end; 
    end; 

    Result := FError; 
end; 
関連する問題