首页 > 其他分享 >Lazarus 将LNET封装到DLL中

Lazarus 将LNET封装到DLL中

时间:2024-07-16 09:53:26浏览次数:13  
标签:LNET begin end TLink aLink DLL aSocket Lazarus procedure

最近工作中有个要求SOCKET的功能,想将一个通信功能做得简单一点。发现LNET非常方便,所以对它研究了一下。
LNET有两种类型,可视化和非可视化。做WINDOWS下一般都是用可视化的。
用于LINUX和WINCE,必须用非可视化的。
我要将它封装成DLL的话,必须用非可视化的。
DLL代码如下:
library project1;

{$mode objfpc}{$H+}

uses
Classes, Interfaces,Forms,unit1, indylaz, lnetvisual
{ you can add units after this };
procedure StartThread; stdcall;
var
DemoThread : TDemoThread;
begin
DemoThread := TDemoThread.Create(false);
DemoThread.FreeOnTerminate := true;
end;

exports
synapp,
StartThread,
showform;

begin
RequireDerivedFormResource:=True;
Application.Initialize;
end.
//////////////////
开窗口界面
Procedure synapp(App:THandle);stdcall;
Begin
Application.Handle:=app;
End;

Procedure showform;stdcall;
Begin
Form1:=Tform1.create(application);
Form1.ShowModal;
Form1.Free;
End;
//////////创建NET
LTCP:= TLTcp.Create(self);
最重要的是事件回滚,
LTCP.OnAccept:=@LTCPComponent1Connect;
LTCP.OnConnect:=@LTCPComponent1Connect;
LTCP.OnError:=@LTCPComponent1Error;
LTCP.OnDisconnect:=@LTCPComponent1Disconnect;
LTCP.OnReceive:=@LTCPComponent1Receive;
// LTCP.Eventer.AddHandle(application);
LTCP.Host:='192.168.0.164';
LTCP.Port:=9898;
//////////////////////////////
unit uLinkTCP;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, Crt,
lNet, lEvents;

type

{ TLink }

TLink = class
public
ServerSocket: TLSocket;
ServerBuffer: string;
ClientTCP: TLTcp;
ClientBuffer: string;
Number: Integer;

constructor Create(aCount: Integer);

end;

{ TLinkServer }

TLinkServer = class(TComponent)
private
FHost: string;
FPort: Word;
FServer: TLTcp;
FCount: Integer;
FEventer: TLEventer;
FQuit: Boolean;
// server callbacks
procedure OnEr(const aMsg: string; aSocket: TLSocket);
procedure OnAc(aSocket: TLSocket);
procedure OnCs(aSocket: TLSocket);
procedure OnRe(aSocket: TLSocket);
procedure OnDs(aSocket: TLSocket);
// client callbacks
procedure OnCliEr(const aMsg: string; aSocket: TLSocket);
procedure OnCliCo(aSocket: TLSocket);
procedure OnCliCs(aSocket: TLSocket);
procedure OnCliRe(aSocket: TLSocket);
procedure OnCliDs(aSocket: TLSocket);
// helpers
procedure ConnectToTarget(aLink: TLink);
procedure SendToTarget(aLink: TLink);
procedure SendToClient(aLink: TLink);
public
constructor Create(const aHost: string; const aServPort, aCliPort: Word);
destructor Destroy; override;
procedure Run;
end;

implementation

constructor TLink.Create(aCount: Integer);
begin
Number := aCount;
end;

{ TLinkServer }

procedure TLinkServer.OnEr(const aMsg: string; aSocket: TLSocket);
var
l: TLink;
c: Integer = -1;
begin
l := TLink(aSocket.UserData);
if Assigned(l) then begin
c := l.Number;
Writeln('Listener error: ', aMsg, ' on connection: ', c);
l.ClientTCP.Free;
l.Free;
aSocket.UserData := nil;
Exit;
end;
Writeln('Listener error: ', aMsg);
FQuit := True;
end;

procedure TLinkServer.OnAc(aSocket: TLSocket);
var
l: TLink;
begin
Inc(FCount);
l := TLink.Create(FCount);
l.ServerSocket := aSocket;
aSocket.UserData := l;

ConnectToTarget(l);
Writeln('Listener accepted connection: ', l.Number, ' from: ', aSocket.PeerAddress);
end;

procedure TLinkServer.OnCs(aSocket: TLSocket);
var
l: TLink;
begin
l := TLink(aSocket.UserData);
SendToTarget(l);
end;

procedure TLinkServer.OnRe(aSocket: TLSocket);
var
l: TLink;
s: string;
begin
l := TLink(aSocket.UserData);
if FServer.GetMessage(s) > 0 then begin
l.ServerBuffer := l.ServerBuffer + s;
SendToTarget(l);
end;
end;

procedure TLinkServer.OnDs(aSocket: TLSocket);
var
l: TLink;
begin
l := TLink(aSocket.UserData);
Writeln('Listener disconnect on connection: ', l.Number);
l.ClientTCP.Free; // TODO: this causes a hard discon, handle softly later
l.Free;
aSocket.UserData := nil;
end;

procedure TLinkServer.OnCliEr(const aMsg: string; aSocket: TLSocket);
var
l: TLink;
c: Integer = -1;
begin
l := TLink(aSocket.UserData);
if Assigned(l) then begin
c := l.Number;
Writeln('Target error: ', aMsg, ' on connection: ', c);
l.ServerSocket.Disconnect;
Exit;
end;
Writeln('Target error: ', aMsg);
end;

procedure TLinkServer.OnCliCo(aSocket: TLSocket);
var
l: TLink;
begin
l := TLink(aSocket.UserData);
Writeln('Target connect on connection: ', l.Number);
SendToTarget(l); // just in case they sent something before we connected to target
end;

procedure TLinkServer.OnCliCs(aSocket: TLSocket);
var
l: TLink;
begin
l := TLink(aSocket.UserData);
SendToClient(l);
end;

procedure TLinkServer.OnCliRe(aSocket: TLSocket);
var
l: TLink;
s: string;
begin
l := TLink(aSocket.UserData);
if l.ClientTCP.GetMessage(s, aSocket) > 0 then begin
l.ClientBuffer := l.ClientBuffer + s;
SendToClient(l);
end;
end;

procedure TLinkServer.OnCliDs(aSocket: TLSocket);
var
l: TLink;
begin
l := TLink(aSocket.UserData);
Writeln('Target disconnect on connection: ', l.Number);
l.ServerSocket.Disconnect; // will trigget OnDs eventually
end;

procedure TLinkServer.ConnectToTarget(aLink: TLink);
begin
aLink.ClientTCP := TLTcp.Create(nil);
aLink.ClientTCP.Eventer := FEventer;
aLink.ClientTCP.OnError := @OnCliEr;
aLink.ClientTCP.OnConnect := @OnCliCo;
aLink.ClientTCP.OnCanSend := @OnCliCs;
aLink.ClientTCP.OnReceive := @OnCliRe;
aLink.ClientTCP.OnDisconnect := @OnCliDs;

if aLink.ClientTCP.Connect(FHost, FPort) then
aLink.ClientTCP.Iterator.UserData := aLink;
end;

procedure TLinkServer.SendToTarget(aLink: TLink);
var
n: Integer;
begin
if (Length(aLink.ServerBuffer) > 0) and (aLink.ClientTCP.Connected) then begin
n := aLink.ClientTCP.SendMessage(aLink.ServerBuffer);
if n > 0 then
Delete(aLink.ServerBuffer, 1, n); // not efficient, rework later
end;
end;

procedure TLinkServer.SendToClient(aLink: TLink);
var
n: Integer;
begin
if Length(aLink.ClientBuffer) > 0 then begin
n := FServer.SendMessage(aLink.ClientBuffer, aLink.ServerSocket);
Delete(aLink.ClientBuffer, 1, n); // not efficient, rework later
end;
end;

constructor TLinkServer.Create(const aHost: string; const aServPort, aCliPort: Word);
begin
inherited Create(nil);

FHost := aHost; // main server host
FPort := aCliPort; // main server port
FEventer := BestEventerClass.Create; // common eventer

FServer := TLTcp.Create(Self); // free server on self.free
FServer.Eventer := FEventer;
FServer.Timeout := 100;
FServer.OnError := @OnEr;
FServer.OnAccept := @OnAc;
FServer.OnCanSend := @OnCs;
FServer.OnReceive := @OnRe;
FServer.OnDisconnect := @OnDs;

FServer.Listen(aServPort);
end;

destructor TLinkServer.Destroy;
begin
inherited Destroy;

// AFTER inherited (which destroys the TCPs)
FEventer.Free;
end;

procedure TLinkServer.Run;
begin
Writeln('Linkserver running... press escape to stop');
while not FQuit do begin
FEventer.CallAction;
if KeyPressed
and (ReadKey = #27) then
FQuit := True;
end;
end;

end.

标签:LNET,begin,end,TLink,aLink,DLL,aSocket,Lazarus,procedure
From: https://www.cnblogs.com/dylxpecho/p/18304557

相关文章

  • 修复《NBA 2K23》“vcruntime140.dll“ 缺失:全面恢复指南
    在尝试运行备受期待的篮球模拟游戏《NBA2K23》时,不少玩家遇到了一个令人沮丧的问题:“vcruntime140.dll”文件丢失。这个动态链接库(DLL)文件是VisualC++Redistributable的一部分,对于许多基于Windows的应用程序来说至关重要。本文将指导你如何快速、有效地解决这个问题,让你能够......
  • Win11系统提示找不到LcRes.dll文件的解决办法
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个LcRes.dll文件(挑选合适的版本文件)把它放入......
  • Win11系统提示找不到libGLESv2.dll文件的解决办法
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个libGLESv2.dll文件(挑选合适的版本文件)把它......
  • Win11系统提示找不到learning_tools.dll文件的解决办法
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个learning_tools.dll文件(挑选合适的版本文件......
  • Win11系统提示找不到LockSearchAPI.dll文件的解决办法
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个LockSearchAPI.dll文件(挑选合适的版本文件)......
  • 封装C++项目为dll
    这是头文件,定义了一个接口类IMyInterface。#pragmaonce#ifndefMY_INTERFACE_H#defineMY_INTERFACE_H#define_CRT_SECURE_NO_WARNINGS#defineMY_DLL_API__declspec(dllexport)//定义导出到DLL中的宏//接口类,用于导出到DLLclassMY_DLL_APIIMyInterface{pub......
  • lib与dll(静态库与动态库)
    在计算机软件开发中,lib和dll是两种不同的库文件类型,用于代码共享和模块化。以下是它们的详细解释:静态库(StaticLibrary-.lib)特点文件扩展名:通常为.lib(在Windows上)或.a(在Unix/Linux系统上)。编译时间链接:静态库在编译时被直接链接到目标应用程序中。这意味着在......
  • Windows11系统System.Runtime.Serialization.dll文件丢失问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个System.Runtime.Serialization.dll文件(挑选......
  • Windows11系统System.Resources.Writer.dll文件丢失问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个System.Resources.Writer.dll文件(挑选合适......
  • 反射DLL注入原理解析
    反射DLL注入又称RDI,与常规DLL注入不同的是,它不需要LoadLibrary这个函数来加载dll,而是通过DLL内部的一个函数来自己把自己加载起来,这么说可能会有一点抽象,总之这个函数会负责解析DLL文件的头信息、导入函数的地址、处理重定位等初始化操作,先不用理解这个函数是怎么实现的......