4.Linux環(huán)境下Tcp Socket 編程
在 Linux 環(huán)境下使用 Indy 組件進(jìn)行 TCP Socket 編程也非常的簡單,一般情況下,Linux 下編寫 TCP Socket 應(yīng)用程序是不需要有 UI 的,所以,今天我們一起來在 Linux 環(huán)境下實(shí)現(xiàn)一個(gè) shell 命令行的 TCP Socket 應(yīng)用程序。
在 Linux 環(huán)境下編寫 Object Pascal 程序,就需要使用 Lazarus 或者 CodeTyphon 了,我們在本節(jié)使用 CodeTyphon 來編寫,同時(shí)在 Linux 下編寫 shell 命令行程序,日志系統(tǒng)是不可缺少的,所以,我先介紹 Lazarus 下的日志系統(tǒng)。
4.1 Lazarus Logger
在 Lazarus 中, TEventLog 是一個(gè)可用于向系統(tǒng)日志發(fā)送消息的組件。如果不存在系統(tǒng)日志(例如在 Windows 95/98 或 DOS 上),則將消息寫入文件。消息可以使用一般的 Log 調(diào)用,或?qū)iT的 Warning、Error、Info或Debug調(diào)用來記錄,這些調(diào)用具有預(yù)定義的事件類型。
TEventLog 的主要屬性:
- LogType – 日志類型,取值: ltSystem | ltFile | ItStdErr | ItStdOut
- FileName – 日志文件名
- DefaultEventType – 默認(rèn)事件類型,取值:etCustom | etInfo | etWarning |etError | etDebug
- AppendContent – 控制是否將輸出附加到現(xiàn)有文件
- Active – 激活日志機(jī)制,取值為布爾型
- TimeStampFormat – 時(shí)間戳字符串的格式
TEventLog 的主要方法:
方法 | 說明 |
Log() | 將消息記錄到系統(tǒng)日志中 |
Warning() | 記錄警告消息 |
Error() | 將錯(cuò)誤消息記錄 |
Debug() | 記錄調(diào)試消息 |
Info() | 記錄信息性消息 |
4.2 Tcp Socket 服務(wù)端
在 Linux shell 下開發(fā) Tcp Socket 服務(wù)端,需要創(chuàng)建一個(gè) Console Application,然后新建的應(yīng)用程序類中編寫代碼。仍然采用上一節(jié)的示例來說明。
示例:客戶端定時(shí)實(shí)時(shí)檢測所在機(jī)器的屏幕分辨率上行到服務(wù)端,服務(wù)端接收到數(shù)據(jù)后,根據(jù)其屏幕分辨率隨機(jī)生成一個(gè)坐標(biāo)并下發(fā)給客戶端,客戶端將應(yīng)用程序的窗體位置放置到相應(yīng)的坐標(biāo)上。
客戶端代碼仍然是上一節(jié)的代碼,在此不再贅述。
首先,打開 CodeTyphon,選擇 Project -> New Project,然后選擇 Console Application,設(shè)置 Application class name 和 Title,單擊 Ok,此時(shí)生成的代碼如下:
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.
生成的代碼為設(shè)置的類名的類代碼,其中:
- WriteHelp – 輸出幫助信息
- DoRun – 該程序的主要執(zhí)行代碼
下面,我們根據(jù)需求來實(shí)現(xiàn) Tcp Server 的功能,由于需要在程序執(zhí)行過程中記錄日志,所以先在該類的聲明部分添加日志和 TIdTCPServer 變量,如下代碼:
private TcpServer: TIdTCPServer; Logger: TEventLog;
接下來,聲明日志輸出功能和 Tcp Server 需要實(shí)現(xiàn)的事件處理功能,對于日志,我們需要輸出消息類數(shù)據(jù)和錯(cuò)誤類信息,代碼如下:
procedure OutputInfoLog(Info: String); // 消息日志procedure OutputErrorLog(Error: String); // 錯(cuò)誤日志procedure ServeExecute(AContext: TIdContext); // 與客戶端交互數(shù)據(jù)procedure ServeConnecte(AContext: TIdContext); // 客戶端建立連接時(shí)觸發(fā)procedure ServeDisconnect(AContext: TIdContext); // 客戶端斷開連接時(shí)觸發(fā)procedure ServeException(AContext: TIdContext; AException: Exception); // 與客戶端交互發(fā)生異常時(shí)觸發(fā)
實(shí)現(xiàn)日志輸出功能:
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;
實(shí)現(xiàn)客戶端建立連接、斷開連接、發(fā)生異常時(shí)觸發(fā)的事件:
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;
定義交互數(shù)據(jù)結(jié)構(gòu):
// 通信數(shù)據(jù)結(jié)構(gòu) TCommBlock = Record Part: String[1]; // 客戶端上傳: W-屏幕寬度, H-屏幕高度, E-結(jié)束; 服務(wù)端下發(fā): X-水平坐標(biāo), Y-垂直坐標(biāo), E-結(jié)束 Desc: String[16]; // 描述 Value: Integer; // 數(shù)據(jù)值 end;
實(shí)現(xiàn)數(shù)據(jù)交互功能:
procedure TTcpApplication.ServeExecute(AContext: TIdContext);var CommBlock: TCommBlock; bytes: TIdBytes; W, H, X, Y: Integer; Host: String;begin // 執(zhí)行 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); // 發(fā)送水平坐標(biāo) CommBlock.Part:=’X’; CommBlock.Desc:=’水平坐標(biāo)’; CommBlock.Value:=X; OutputInfoLog(‘Send – ‘ + Host + ‘ ‘ + CommBlock.Desc + ‘: ‘ + inttostr(CommBlock.Value)); AContext.Connection.IOHandler.Write(RawToBytes(CommBlock, SizeOf(CommBlock))); // 發(fā)送垂直坐標(biāo) CommBlock.Part:=’Y’; CommBlock.Desc:=’垂直坐標(biāo)’; CommBlock.Value:=Y; OutputInfoLog(‘Send – ‘ + Host + ‘ ‘ + CommBlock.Desc + ‘: ‘ + inttostr(CommBlock.Value)); AContext.Connection.IOHandler.Write(RawToBytes(CommBlock, SizeOf(CommBlock))); // 發(fā)送結(jié)束標(biāo)志 CommBlock.Part:=’E’; CommBlock.Desc:=’結(jié)束’; 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;
實(shí)現(xiàn)主程序:
// 日志初始化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;// 設(shè)置 Server 端事件處理TcpServer.OnConnect:=@ServeConnecte;TcpServer.OnDisconnect:=@ServeDisconnect;TcpServer.OnExecute:=@ServeExecute;TcpServer.OnException:=@ServeException;// 啟動 ServerTcpServer.StartListening;TcpServer.Active:=True;OutputInfoLog(‘Started at 8081’); while True do readln();// 釋放資源 Logger.Destroy;TcpServer.StopListening;TcpServer.Destroy; // stop program loopTerminate;
完整代碼如下:
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; // 通信數(shù)據(jù)結(jié)構(gòu) TCommBlock = Record Part: String[1]; // 客戶端上傳: W-屏幕寬度, H-屏幕高度, E-結(jié)束; 服務(wù)端下發(fā): X-水平坐標(biāo), Y-垂直坐標(biāo), E-結(jié)束 Desc: String[16]; // 描述 Value: Integer; // 數(shù)據(jù)值 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 // 執(zhí)行 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); // 發(fā)送水平坐標(biāo) CommBlock.Part:=’X’; CommBlock.Desc:=’水平坐標(biāo)’; CommBlock.Value:=X; OutputInfoLog(‘Send – ‘ + Host + ‘ ‘ + CommBlock.Desc + ‘: ‘ + inttostr(CommBlock.Value)); AContext.Connection.IOHandler.Write(RawToBytes(CommBlock, SizeOf(CommBlock))); // 發(fā)送垂直坐標(biāo) CommBlock.Part:=’Y’; CommBlock.Desc:=’垂直坐標(biāo)’; CommBlock.Value:=Y; OutputInfoLog(‘Send – ‘ + Host + ‘ ‘ + CommBlock.Desc + ‘: ‘ + inttostr(CommBlock.Value)); AContext.Connection.IOHandler.Write(RawToBytes(CommBlock, SizeOf(CommBlock))); // 發(fā)送結(jié)束標(biāo)志 CommBlock.Part:=’E’; CommBlock.Desc:=’結(jié)束’; 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.
程序運(yùn)行效果:
[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 結(jié)束: 0 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- Send – 127.0.0.1 水平坐標(biāo): 550 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- Send – 127.0.0.1 垂直坐標(biāo): 877 [2022-06-25 10:30:31.797 Info] 2022-06-25 10:30:31:797 -info- Send – 127.0.0.1 結(jié)束: 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 結(jié)束: 0 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- Send – 127.0.0.1 水平坐標(biāo): 777 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- Send – 127.0.0.1 垂直坐標(biāo): 950 [2022-06-25 10:30:41.794 Info] 2022-06-25 10:30:41:794 -info- Send – 127.0.0.1 結(jié)束: 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 結(jié)束: 0 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- Send – 127.0.0.1 水平坐標(biāo): 271 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- Send – 127.0.0.1 垂直坐標(biāo): 294 [2022-06-25 10:30:51.792 Info] 2022-06-25 10:30:51:792 -info- Send – 127.0.0.1 結(jié)束: 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 // 執(zhí)行 – 業(yè)務(wù)邏輯 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.
將上面的代碼框架復(fù)制后適當(dāng)修改,實(shí)現(xiàn)業(yè)務(wù)邏輯即可。