2017-04-06 119 views
0

我創建一個套接字連接,並使用一個線程通過套接字連續發送數據使用下面的代碼的數據(德爾福):TCP套接字停止發送

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

這是FSocketSession.Send電話:

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; 

我注意到,在某些電腦,插座簡單地停止的一段時間內(通常它發生約1或2分鐘後),並在其上運行,沒有任何問題的其他電腦發送數據。有沒有人看到可能導致這種情況發生的代碼?如果需要,我可以提供更多信息。

回答

1

我看到你的代碼有幾個問題。

如果JSONEvent是空白的,你會打電話給Connect()即使Connected已經是真實的,你會泄漏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;