「12.网络编程」4.Linux环境下Tcp Socket 编程

(20) 2024-01-01 20:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说「12.网络编程」4.Linux环境下Tcp Socket 编程,希望能够帮助你!!!。

4.Linux环境下Tcp Socket 编程

在 Linux 环境下使用 Indy 组件进行 TCP Socket 编程也非常的简单,一般情况下,Linux 下编写 TCP Socket 应用程序是不需要有 UI 的,所以,今天我们一起来在 Linux 环境下实现一个 shell 命令行的 TCP Socket 应用程序。

在 Linux 环境下编写 Object Pascal 程序,就需要使用 Lazarus 或者 CodeTyphon 了,我们在本节使用 CodeTyphon 来编写,同时在 Linux 下编写 shell 命令行程序,日志系统是不可缺少的,所以,我先介绍 Lazarus 下的日志系统。

4.1 Lazarus Logger

在 Lazarus 中, TEventLog 是一个可用于向系统日志发送消息的组件。如果不存在系统日志(例如在 Windows 95/98 或 DOS 上),则将消息写入文件。消息可以使用一般的 Log 调用,或专门的 Warning、Error、Info或Debug调用来记录,这些调用具有预定义的事件类型。

TEventLog 的主要属性:

  • LogType - 日志类型,取值: ltSystem | ltFile | ItStdErr | ItStdOut
  • FileName - 日志文件名
  • DefaultEventType - 默认事件类型,取值:etCustom | etInfo | etWarning |etError | etDebug
  • AppendContent - 控制是否将输出附加到现有文件
  • Active - 激活日志机制,取值为布尔型
  • TimeStampFormat - 时间戳字符串的格式

TEventLog 的主要方法:

方法

说明

Log()

将消息记录到系统日志中

Warning()

记录警告消息

Error()

将错误消息记录

Debug()

记录调试消息

Info()

记录信息性消息

4.2 Tcp Socket 服务端

在 Linux shell 下开发 Tcp Socket 服务端,需要创建一个 Console Application,然后新建的应用程序类中编写代码。仍然采用上一节的示例来说明。

示例:客户端定时实时检测所在机器的屏幕分辨率上行到服务端,服务端接收到数据后,根据其屏幕分辨率随机生成一个坐标并下发给客户端,客户端将应用程序的窗体位置放置到相应的坐标上。

客户端代码仍然是上一节的代码,在此不再赘述。

首先,打开 CodeTyphon,选择 Project -> New Project,然后选择 Console Application,设置 Application class name 和 Title,单击 Ok,此时生成的代码如下:

program Project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  Classes, SysUtils, CustApp
  { you can add units after this };

type

  { TTcpApplication }

  TTcpApplication = class(TCustomApplication)
  protected
    procedure DoRun; override;
  public
    constructor Create(TheOwner: TComponent); override;
    destructor Destroy; override;
    procedure WriteHelp; virtual;
  end;

{ TTcpApplication }

procedure TTcpApplication.DoRun;
var
  ErrorMsg: String;
begin
  // quick check parameters
  ErrorMsg:=CheckOptions('h', 'help');
  if ErrorMsg<>'' then begin
    ShowException(Exception.Create(ErrorMsg));
    Terminate;
    Exit;
  end;

  // parse parameters
  if HasOption('h', 'help') then begin
    WriteHelp;
    Terminate;
    Exit;
  end;

  { add your program here }

  // stop program loop
  Terminate;
end;

constructor TTcpApplication.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  StopOnException:=True;
end;

destructor TTcpApplication.Destroy;
begin
  inherited Destroy;
end;

procedure TTcpApplication.WriteHelp;
begin
  { add your help code here }
  writeln('Usage: ', ExeName, ' -h');
end;

var
  Application: TTcpApplication;
begin
  Application:=TTcpApplication.Create(nil);
  Application.Title:='Tcp Application';
  Application.Run;
  Application.Free;
end.

生成的代码为设置的类名的类代码,其中:

  • WriteHelp - 输出帮助信息
  • DoRun - 该程序的主要执行代码

下面,我们根据需求来实现 Tcp Server 的功能,由于需要在程序执行过程中记录日志,所以先在该类的声明部分添加日志和 TIdTCPServer 变量,如下代码:

private
    TcpServer: TIdTCPServer;
    Logger: TEventLog;

接下来,声明日志输出功能和 Tcp Server 需要实现的事件处理功能,对于日志,我们需要输出消息类数据和错误类信息,代码如下:

procedure OutputInfoLog(Info: String);  // 消息日志
procedure OutputErrorLog(Error: String);  // 错误日志
procedure ServeExecute(AContext: TIdContext);  // 与客户端交互数据
procedure ServeConnecte(AContext: TIdContext);  // 客户端建立连接时触发
procedure ServeDisconnect(AContext: TIdContext);  // 客户端断开连接时触发
procedure ServeException(AContext: TIdContext; AException: Exception);  // 与客户端交互发生异常时触发

实现日志输出功能:

procedure TTcpApplication.OutputInfoLog(Info: String);
var
  LogContent: String;
begin
  LogContent:=FormatDateTime('yyyy-mm-dd hh:nn:ss:zzz', Now) + ' -info- ' + Info;
  Writeln(LogContent);
  Logger.Info(LogContent);
end;

procedure TTcpApplication.OutputErrorLog(Error: String);
var
  LogContent: String;
begin
  LogContent:=FormatDateTime('yyyy-mm-dd hh:nn:ss:zzz', Now) + ' -error- ' + Error;
  Writeln(LogContent);
  Logger.Info(LogContent);
end;           

实现客户端建立连接、断开连接、发生异常时触发的事件:

procedure TTcpApplication.ServeConnecte(AContext: TIdContext);
var
  Info: String;
begin
  // 连接
  Info := AContext.Connection.Socket.Binding.PeerIP + ':' + inttostr(AContext.Connection.Socket.Binding.PeerPort) + ' - has created connection.';
  OutputInfoLog(Info);
end;

procedure TTcpApplication.ServeDisconnect(AContext: TIdContext);
var
  Info: String;
begin
  // 断开连接
  Info := AContext.Connection.Socket.Binding.PeerIP + ':' + inttostr(AContext.Connection.Socket.Binding.PeerPort) + ' - has closed connection.';
  OutputInfoLog(Info);
end;

procedure TTcpApplication.ServeException(AContext: TIdContext; AException: Exception);
var
  Info: String;
begin
  // 异常
  Info := AContext.Connection.Socket.Binding.PeerIP + ' ' + inttostr(AContext.Connection.Socket.Binding.PeerPort) + ' - Error: ' + AException.Message;
  OutputErrorLog(Info);
end;    

定义交互数据结构:

// 通信数据结构
  TCommBlock = Record
    Part: String[1];   // 客户端上传: W-屏幕宽度, H-屏幕高度, E-结束; 服务端下发: X-水平坐标, Y-垂直坐标, E-结束
    Desc: String[16];   // 描述
    Value: Integer; // 数据值
  end; 

实现数据交互功能:

procedure TTcpApplication.ServeExecute(AContext: TIdContext);
var
  CommBlock: TCommBlock;
  bytes: TIdBytes;
  W, H, X, Y: Integer;
  Host: String;
begin
  // 执行
  if AContext.Connection.Connected then
  begin
    try
      OutputInfoLog('----- Start -----');
      Host:=AContext.Connection.Socket.Binding.PeerIP;

      AContext.Connection.IOHandler.ReadBytes(bytes, SizeOf(CommBlock), False);
      BytesToRaw(bytes, CommBlock, SizeOf(CommBlock));

      OutputInfoLog('Recv - ' + Host + ' ' + CommBlock.Desc + ': ' + inttostr(CommBlock.Value));

      if CommBlock.Part = 'W' then W:=CommBlock.Value;
      if CommBlock.Part = 'H' then H:=CommBlock.Value;

      if CommBlock.Part = 'E' then
      begin
        Randomize;
        X:=Random(W);
        Y:=Random(H);

        // 发送水平坐标
        CommBlock.Part:='X';
        CommBlock.Desc:='水平坐标';
        CommBlock.Value:=X;
        OutputInfoLog('Send - ' + Host + ' ' + CommBlock.Desc + ': ' + inttostr(CommBlock.Value));

        AContext.Connection.IOHandler.Write(RawToBytes(CommBlock, SizeOf(CommBlock)));
        // 发送垂直坐标
        CommBlock.Part:='Y';
        CommBlock.Desc:='垂直坐标';
        CommBlock.Value:=Y;
        OutputInfoLog('Send - ' + Host + ' ' + CommBlock.Desc + ': ' + inttostr(CommBlock.Value));

        AContext.Connection.IOHandler.Write(RawToBytes(CommBlock, SizeOf(CommBlock)));
        // 发送结束标志
        CommBlock.Part:='E';
        CommBlock.Desc:='结束';
        CommBlock.Value:=0;
        OutputInfoLog('Send - ' + Host + ' ' + CommBlock.Desc + ': ' + inttostr(CommBlock.Value));

        AContext.Connection.IOHandler.Write(RawToBytes(CommBlock, SizeOf(CommBlock)));
      end;
    except
      ON E: Exception do
        OutputErrorLog('ERROR: ' + Host + ' - ' + E.Message);
    end;
  end;
end;

实现主程序:

// 日志初始化
Logger:=TEventLog.Create(Self);
Logger.FileName:='tcp_serve.log';
Logger.LogType:=ltFile;
Logger.DefaultEventType:=etDebug;
Logger.AppendContent:=True;
Logger.Active:=True;

// Server 端初始化
TcpServer:=TIdTCPServer.Create(Self);
TcpServer.DefaultPort:=8081;
// 设置 Server 端事件处理
TcpServer.OnConnect:=@ServeConnecte;
TcpServer.OnDisconnect:=@ServeDisconnect;
TcpServer.OnExecute:=@ServeExecute;
TcpServer.OnException:=@ServeException;
// 启动 Server
TcpServer.StartListening;
TcpServer.Active:=True;

OutputInfoLog('Started at 8081');  

while True do readln();
// 释放资源  
Logger.Destroy;
TcpServer.StopListening;
TcpServer.Destroy;   

// stop program loop
Terminate;           

完整代码如下:

program ct1203;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  Classes, SysUtils, CustApp, IdTCPServer, IdContext, IdGlobal, EventLog
  { you can add units after this };

type

  { TTcpApplication }

  TTcpApplication = class(TCustomApplication)
  private
    TcpServer: TIdTCPServer;
    Logger: TEventLog;
  protected
    procedure DoRun; override;
    procedure OutputInfoLog(Info: String);
    procedure OutputErrorLog(Error: String);
    procedure ServeExecute(AContext: TIdContext);
    procedure ServeConnecte(AContext: TIdContext);
    procedure ServeDisconnect(AContext: TIdContext);
    procedure ServeException(AContext: TIdContext; AException: Exception);
  public
    constructor Create(TheOwner: TComponent); override;
    destructor Destroy; override;
    // procedure WriteHelp; virtual;
  end;

  // 通信数据结构
  TCommBlock = Record
    Part: String[1];   // 客户端上传: W-屏幕宽度, H-屏幕高度, E-结束; 服务端下发: X-水平坐标, Y-垂直坐标, E-结束
    Desc: String[16];   // 描述
    Value: Integer; // 数据值
  end;


{ TTcpApplication }

procedure TTcpApplication.OutputInfoLog(Info: String);
var
  LogContent: String;
begin
  LogContent:=FormatDateTime('yyyy-mm-dd hh:nn:ss:zzz', Now) + ' -info- ' + Info;
  Writeln(LogContent);
  Logger.Info(LogContent);
end;

procedure TTcpApplication.OutputErrorLog(Error: String);
var
  LogContent: String;
begin
  LogContent:=FormatDateTime('yyyy-mm-dd hh:nn:ss:zzz', Now) + ' -error- ' + Error;
  Writeln(LogContent);
  Logger.Info(LogContent);
end;

procedure TTcpApplication.ServeConnecte(AContext: TIdContext);
var
  Info: String;
begin
  // 连接
  Info := AContext.Connection.Socket.Binding.PeerIP + ':' + inttostr(AContext.Connection.Socket.Binding.PeerPort) + ' - has created connection.';
  OutputInfoLog(Info);
end;

procedure TTcpApplication.ServeDisconnect(AContext: TIdContext);
var
  Info: String;
begin
  // 断开连接
  Info := AContext.Connection.Socket.Binding.PeerIP + ':' + inttostr(AContext.Connection.Socket.Binding.PeerPort) + ' - has closed connection.';
  OutputInfoLog(Info);
end;

procedure TTcpApplication.ServeException(AContext: TIdContext; AException: Exception);
var
  Info: String;
begin
  // 异常
  Info := AContext.Connection.Socket.Binding.PeerIP + ' ' + inttostr(AContext.Connection.Socket.Binding.PeerPort) + ' - Error: ' + AException.Message;
  OutputErrorLog(Info);
end;

procedure TTcpApplication.ServeExecute(AContext: TIdContext);
var
  CommBlock: TCommBlock;
  bytes: TIdBytes;
  W, H, X, Y: Integer;
  Host: String;
begin
  // 执行
  if AContext.Connection.Connected then
  begin
    try
      OutputInfoLog('----- Start -----');
      Host:=AContext.Connection.Socket.Binding.PeerIP;

      AContext.Connection.IOHandler.ReadBytes(bytes, SizeOf(CommBlock), False);
      BytesToRaw(bytes, CommBlock, SizeOf(CommBlock));

      OutputInfoLog('Recv - ' + Host + ' ' + CommBlock.Desc + ': ' + inttostr(CommBlock.Value));

      if CommBlock.Part = 'W' then W:=CommBlock.Value;
      if CommBlock.Part = 'H' then H:=CommBlock.Value;

      if CommBlock.Part = 'E' then
      begin
        Randomize;
        X:=Random(W);
        Y:=Random(H);

        // 发送水平坐标
        CommBlock.Part:='X';
        CommBlock.Desc:='水平坐标';
        CommBlock.Value:=X;
        OutputInfoLog('Send - ' + Host + ' ' + CommBlock.Desc + ': ' + inttostr(CommBlock.Value));

        AContext.Connection.IOHandler.Write(RawToBytes(CommBlock, SizeOf(CommBlock)));
        // 发送垂直坐标
        CommBlock.Part:='Y';
        CommBlock.Desc:='垂直坐标';
        CommBlock.Value:=Y;
        OutputInfoLog('Send - ' + Host + ' ' + CommBlock.Desc + ': ' + inttostr(CommBlock.Value));

        AContext.Connection.IOHandler.Write(RawToBytes(CommBlock, SizeOf(CommBlock)));
        // 发送结束标志
        CommBlock.Part:='E';
        CommBlock.Desc:='结束';
        CommBlock.Value:=0;
        OutputInfoLog('Send - ' + Host + ' ' + CommBlock.Desc + ': ' + inttostr(CommBlock.Value));

        AContext.Connection.IOHandler.Write(RawToBytes(CommBlock, SizeOf(CommBlock)));
      end;
    except
      ON E: Exception do
        OutputErrorLog('ERROR: ' + Host + ' - ' + E.Message);
    end;
  end;
end;

procedure TTcpApplication.DoRun;
// var
  // ErrorMsg: String;
begin
  // quick check parameters
  (*ErrorMsg:=CheckOptions('h', 'help');
  if ErrorMsg<>'' then begin
    ShowException(Exception.Create(ErrorMsg));
    Terminate;
    Exit;
  end;*)

  // parse parameters
  (*if HasOption('h', 'help') then begin
    WriteHelp;
    Terminate;
    Exit;
  end;*)

  { add your program here }
  Logger:=TEventLog.Create(Self);
  Logger.FileName:='tcp_serve.log';
  Logger.LogType:=ltFile;
  Logger.DefaultEventType:=etDebug;
  Logger.AppendContent:=True;
  // Logger.TimeStampFormat:='yyyy-mm-dd hh:nn:ss:zzz';
  Logger.Active:=True;

  TcpServer:=TIdTCPServer.Create(Self);
  TcpServer.DefaultPort:=8081;

  TcpServer.OnConnect:=@ServeConnecte;
  TcpServer.OnDisconnect:=@ServeDisconnect;
  TcpServer.OnExecute:=@ServeExecute;
  TcpServer.OnException:=@ServeException;

  TcpServer.StartListening;
  TcpServer.Active:=True;

  OutputInfoLog('Started at 8081');

  while True do readln();

  Logger.Destroy;
  TcpServer.StopListening;
  TcpServer.Destroy;

  // stop program loop
  Terminate;
end;

constructor TTcpApplication.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  StopOnException:=True;
end;

destructor TTcpApplication.Destroy;
begin
  inherited Destroy;
end;

(*procedure TTcpApplication.WriteHelp;
begin
  { add your help code here }
  writeln('Usage: ', ExeName, ' -h');
end;*)

var
  Application: TTcpApplication;
begin
  Application:=TTcpApplication.Create(nil);
  Application.Title:='Tcp Application';
  Application.Run;
  Application.Free;
end.

程序运行效果:

 [2022-06-25 10:30:07.442 Info] 2022-06-25 10:30:07:442 -info- Started at 8081
 [2022-06-25 10:30:21.783 Info] 2022-06-25 10:30:21:783 -info- 127.0.0.1:52612 - has created connection.
 [2022-06-25 10:30:21.783 Info] 2022-06-25 10:30:21:783 -info- ----- Start -----
 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- Recv - 127.0.0.1 宽度: 1920
 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- ----- Start -----
 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- Recv - 127.0.0.1 高度: 1080
 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- ----- Start -----
 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- Recv - 127.0.0.1 结束: 0
 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- Send - 127.0.0.1 水平坐标: 550
 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- Send - 127.0.0.1 垂直坐标: 877
 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- Send - 127.0.0.1 结束: 0
 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- ----- Start -----
 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- Recv - 127.0.0.1 宽度: 1920
 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- ----- Start -----
 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- Recv - 127.0.0.1 高度: 1080
 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- ----- Start -----
 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- Recv - 127.0.0.1 结束: 0
 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- Send - 127.0.0.1 水平坐标: 777
 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- Send - 127.0.0.1 垂直坐标: 950
 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- Send - 127.0.0.1 结束: 0
 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- ----- Start -----
 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- Recv - 127.0.0.1 宽度: 1920
 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- ----- Start -----
 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- Recv - 127.0.0.1 高度: 1080
 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- ----- Start -----
 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- Recv - 127.0.0.1 结束: 0
 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- Send - 127.0.0.1 水平坐标: 271
 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- Send - 127.0.0.1 垂直坐标: 294
 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- Send - 127.0.0.1 结束: 0
 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- ----- Start -----
 [2022-06-25 10:30:53.792 Info] 2022-06-25 10:30:53:792 -error- ERROR: 127.0.0.1 - Connection Closed Gracefully.
 [2022-06-25 10:30:53.792 Info] 2022-06-25 10:30:53:792 -info- 127.0.0.1:52612 - has closed connection.

4.3 Tcp Socket Server 代码框架

program 程序名;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  Classes, SysUtils, CustApp, IdTCPServer, IdContext, IdGlobal, EventLog
  { you can add units after this };

type

  { TTcpApplication }

  TTcpApplication = class(TCustomApplication)
  private
    TcpServer: TIdTCPServer;
    Logger: TEventLog;
  protected
    procedure DoRun; override;
    procedure OutputInfoLog(Info: String);
    procedure OutputErrorLog(Error: String);
    procedure ServeExecute(AContext: TIdContext);
    procedure ServeConnecte(AContext: TIdContext);
    procedure ServeDisconnect(AContext: TIdContext);
    procedure ServeException(AContext: TIdContext; AException: Exception);
  public
    constructor Create(TheOwner: TComponent); override;
    destructor Destroy; override;
  end;

{ TTcpApplication }

procedure TTcpApplication.OutputInfoLog(Info: String);
var
  LogContent: String;
begin
  LogContent:=FormatDateTime('yyyy-mm-dd hh:nn:ss:zzz', Now) + ' -info- ' + Info;
  Writeln(LogContent);
  Logger.Info(LogContent);
end;

procedure TTcpApplication.OutputErrorLog(Error: String);
var
  LogContent: String;
begin
  LogContent:=FormatDateTime('yyyy-mm-dd hh:nn:ss:zzz', Now) + ' -error- ' + Error;
  Writeln(LogContent);
  Logger.Info(LogContent);
end;

procedure TTcpApplication.ServeConnecte(AContext: TIdContext);
var
  Info: String;
begin
  // 连接
  Info := AContext.Connection.Socket.Binding.PeerIP + ':' + inttostr(AContext.Connection.Socket.Binding.PeerPort) + ' - has created connection.';
  OutputInfoLog(Info);
end;

procedure TTcpApplication.ServeDisconnect(AContext: TIdContext);
var
  Info: String;
begin
  // 断开连接
  Info := AContext.Connection.Socket.Binding.PeerIP + ':' + inttostr(AContext.Connection.Socket.Binding.PeerPort) + ' - has closed connection.';
  OutputInfoLog(Info);
end;

procedure TTcpApplication.ServeException(AContext: TIdContext; AException: Exception);
var
  Info: String;
begin
  // 异常
  Info := AContext.Connection.Socket.Binding.PeerIP + ' ' + inttostr(AContext.Connection.Socket.Binding.PeerPort) + ' - Error: ' + AException.Message;
  OutputErrorLog(Info);
end;

procedure TTcpApplication.ServeExecute(AContext: TIdContext);
begin
  // 执行 - 业务逻辑
  
end;

procedure TTcpApplication.DoRun;
begin
  { add your program here }
  Logger:=TEventLog.Create(Self);
  Logger.FileName:='tcp_serve.log';
  Logger.LogType:=ltFile;
  Logger.DefaultEventType:=etDebug;
  Logger.AppendContent:=True;
  Logger.Active:=True;

  TcpServer:=TIdTCPServer.Create(Self);
  TcpServer.DefaultPort:=8081;

  TcpServer.OnConnect:=@ServeConnecte;
  TcpServer.OnDisconnect:=@ServeDisconnect;
  TcpServer.OnExecute:=@ServeExecute;
  TcpServer.OnException:=@ServeException;

  TcpServer.StartListening;
  TcpServer.Active:=True;

  Writeln('Started at 8081');
  Logger.Info('Started at 8081');

  while True do readln();

  // stop program loop
  Terminate;
end;

constructor TTcpApplication.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  StopOnException:=True;
end;

destructor TTcpApplication.Destroy;
begin
  inherited Destroy;
end;

var
  Application: TTcpApplication;
begin
  Application:=TTcpApplication.Create(nil);
  Application.Title:='Tcp Application';
  Application.Run;
  Application.Free;
end.

将上面的代码框架复制后适当修改,实现业务逻辑即可。

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复