当客户端连接时,Indy TCPServer 给出“Connection reset by peer”错误

Indy TCPServer is giving `Connection reset by peer` error when client connects

我正在尝试使用 Delphi firemonkey 应用程序创建 TCP 服务器。

我的资源文件Unit1.fmx如下。

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  OnActivate = FormShow
  OnCreate = FormCreate
  DesignerMasterStyle = 0
  object Label1: TLabel
    Position.X = 504.000000000000000000
    Position.Y = 248.000000000000000000
    Text = 'Label1'
  end
  object TCPServer: TIdTCPServer
    Bindings = <>
    DefaultPort = 0
    OnAfterBind = TCPServerAfterBind
    OnConnect = TCPServerOnConnect
    OnExecute = TCPserverExecute
    Left = 560
    Top = 184
  end
end

我的代码文件在这里。

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Platform,
  IdCustomTCPServer, IdTCPServer, IdBaseComponent, IdComponent, IdUDPBase, IdContext,
  IdSocketHandle, IdUDPServer, FMX.Controls.Presentation, FMX.StdCtrls, Windows;

type
  TForm1 = class(TForm)
    TCPServer: TIdTCPServer;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure TCPserverExecute(AContext: TIdContext);
    procedure TCPServerOnConnect(AContext: TIdContext);
    procedure TCPServerAfterBind(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  TMyLoggingService = class(TInterfacedObject, IFMXLoggingService)
  public
    procedure Log(const Format: string; const Params: array of const);
  end;

var
  Form1: TForm1;
  MyLoggingService: IFMXLoggingService;

implementation

{$R *.fmx}

procedure TMyLoggingService.Log(const Format: string; const Params: array of const);
begin
  // do whatever you want...
  OutputDebugString(PChar(Format));
end;


procedure TForm1.FormCreate(Sender: TObject);
var
  Binding : TIdSocketHandle;
begin
  MyLoggingService := TMyLoggingService.Create;
  if TPlatformServices.Current.SupportsPlatformService( IFMXLoggingService ) then
    TPlatformServices.Current.RemovePlatformService( IFMXLoggingService );
  // register my service
  TPlatformServices.Current.AddPlatformService( IFMXLoggingService, MyLoggingService );
  TCPServer.DefaultPort := 16000;
  TCPServer.Bindings.Clear;
  Binding := TCPServer.Bindings.Add;
  Binding.IP := '127.0.0.1';
  Binding.Port := 16000;
  //if Assigned(MyLoggingService) then
  MyLoggingService.Log('FormCreate!',[]);
end;

procedure TForm1.FormShow(Sender: TObject);
begin
 TCPServer.Active := True;
end;

procedure TForm1.TCPServerAfterBind(Sender: TObject);
begin
  MyLoggingService.Log('After Bind',[]);
end;

procedure TForm1.TCPServerOnConnect(AContext: TIdContext);
begin
  MyLoggingService.Log('Recieved Connection From Client ',[]);
end;

procedure TForm1.TCPServerExecute(AContext: TIdContext);
Var
C : String;
begin
 C:= AContext.Connection.Socket.ReadLn();
 //if Assigned(MyLoggingService) then
 MyLoggingService.Log('TserverExecute !',[]);

 MyLoggingService.Log('Recived Data !',[C]);
 if C = 'TESTSTRING' then
 begin
   AContext.Connection.Socket.Writeln('SENT');
 end;


end;

end.

我的问题是在我记录消息的系统日志中,这是我得到的。

Debug Output: FormCreate! Process Project1.exe (3340)
Debug Output: After Bind Process Project1.exe (3340)
Debug Output: Recieved Connection From Client  Process Project1.exe (3340)
First chance exception at 9BC42D. Exception class EIdSocketError with message
'Socket Error # 10054
Connection reset by peer.'.
Process Project1.exe (3340)

connection reset by peer。我的问题是为什么我的代码会发生这种情况?我做错了什么,我该如何解决?

在远程端,我有一个非常简单的 python 脚本,如下所示。

import socket

# Set up a TCP/IP socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# Connect as client to a selected server
# on a specified port
s.connect(('127.0.0.1',16000))

# Protocol exchange - sends and receives
data = 'TESTSTRING';
s.send(data.encode())
while True:
    resp = s.recv(1024)
    if resp == "": 
        print('NOTHING')
        break
    else:
        print(resp)
        break

# Close the connection when completed
s.close()
print("\ndone")

服务器代码没有问题。客户端在其端断开连接,服务器端的 调试器 只是检测 Indy 引发的异常以处理断开连接。 这是正常行为

但是,您的客户端代码存在问题。在服务器端,您正在使用 TIdIOHandler.ReadLn(),它期望客户端发送一行由 LF 字符(或 CRLF 字符串)分隔的文本。但是您的客户端脚本根本没有发送该分隔符,因此 ReadLn() 不会退出,因此服务器不会调用 TIdIOHandler.WriteLn() 来发送响应。在客户端,s.recv() 可能会失败(因为没有收到响应)并且脚本结束,断开套接字,导致服务器端的 ReadLn() 将异常返回到 TIdTCPServer 所以它可以停止线程关闭套接字。