2017-04-06 110 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;