目前 lazarus 的原始 socket 函数并没有写完整的跨平台,不推荐使用[更新,按一种方式也可以]
clq
浏览(665) -
2020-10-15 18:53:50 发表
编辑
关键字:
[2022-11-10 16:56:03 最后更新]
目前 lazarus 的原始 socket 函数并没有写完整的跨平台,不推荐使用[更新,按一种方式也可以] 基础函数是有的,但象 select , gethostbyname 这样的函数并没有给出接口。也不知 lazarus 的开发们是怎么想的,这么基础的函数都没给全。 也许是要考虑到手机平台吧。从它的文档中可以看到,它原来是有的,后来取消了,还有一些要使用 fp 的前缀才行。 //lazarus 不知为什么,没有完全实现 socket 接口 //一部分函数需要在前面加 fp 前缀 //参考 https://wiki.lazarus.freepascal.org/User_Changes_2.4.0 //关于 "Almost all old 1.0.x socket unit functions have been removed" 的部分 //也许是为了支持手机? 从源码看它的 socket 相关操作分散在以下单元: fphttpclient, //lazarus 下的 socket 操作可参考这个单元的实现 ssockets, //这个似乎是 fphttpclient 的基础 resolve, //这个的作用是什么 ctypes, //XMLRPC, //cnetdb, //windows 下据说不支持,另外什么是 netdb 和cnetdb //centos7 下是可以的 Sockets, WinSock; //lazarus 下用 Sockets 就可以了 //还是不行 lazarus 的跨平台 socket 库不完整,例如没有 gethostbyname , select 这些函数 有些函数还直接用的 WinSock 而在 unix 下则是 unit cNetDB; 这就比较尴尬,不想在几个平台下调试纠错的话,我个人认为有以下几个解决方案: 1.它的 fphttpclient 跨平台的,可以用它里面的那个 socket 实现来做。 2.用 C 语言写一个动态库。不过 socket 本身是不能完整解决通信问题的,我非常不推荐。 3.用 golang 写一个动态库。我们用的这种方法,因为本身就是拿 lazarus 来写 ui 的,业务代码我们本来就用的 golang 所以正好解决了。 4.执着的人就自己试试 cNetDB 单元吧,也许它可以跨 unix/linux 吧。不过这也只能解决 socket 函数部分,即使成功了也还是有同方法 2 的缺陷。只能说适合以 linux 平台为主的同学。
clq
2022-11-10 09:55:06 发表
编辑
TFPHTTPClient 中实际上是使用了 ssockets 中的 TInetSocket 参考 fphttpclient.pp 源码 procedure TFPCustomHTTPClient.ConnectToServer(const AHost: String; APort: Integer; UseSSL : Boolean = False); Var G : TSocketHandler; begin If IsConnected Then DisconnectFromServer; // avoid memory leaks if (Aport=0) then if UseSSL then Aport:=443 else Aport:=80; G:=GetSocketHandler(UseSSL); FSocket:=TInetSocket.Create(AHost,APort,G);
clq
2022-11-10 10:42:54 发表
编辑
目前 GetHostByName 函数在 netdb 单元中 (netdb.pp ) 已经实测可跨平台,不过最好是用 fpc/lazarus 封装后的 socket 算了。参考以下代码 unit mainform; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Sockets, fphttpclient, sslsockets, ssockets; type { TForm1 } TForm1 = class(TForm) ToggleBox1: TToggleBox; procedure ToggleBox1Change(Sender: TObject); private public end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } //from function TFPCustomHTTPClient.GetSocketHandler(const UseSSL: Boolean): TSocketHandler; function GetSocketHandler(const UseSSL: Boolean): TSocketHandler; begin Result:=Nil; if (Result=Nil) then If UseSSL then Result:=TSSLSocketHandler.GetDefaultHandler else Result:=TSocketHandler.Create; end; //from procedure TFPCustomHTTPClient.ConnectToServer //procedure ConnectToServer(const AHost: String; // APort: Integer; UseSSL : Boolean = False); //THostResolver THostResolver.NameLookup for gethostbyname //GetHostByName in netdb.pp function ConnectToServer(const AHost: String; APort: Integer; UseSSL : Boolean = False):TSocketHandler;//TInetSocket; Var G : TSocketHandler; FSocket:TInetSocket; begin if (Aport=0) then if UseSSL then Aport:=443 else Aport:=80; G:=GetSocketHandler(UseSSL); FSocket:=TInetSocket.Create(AHost,APort,G); try //if FIOTimeout<>0 then // FSocket.IOTimeout:=FIOTimeout; // //if FConnectTimeout<>0 then // FSocket.ConnectTimeout:=FConnectTimeout; FSocket.Connect; except FreeAndNil(FSocket); Raise; end; result := G;//FSocket; end; procedure TForm1.ToggleBox1Change(Sender: TObject); var so:longint; http:TFPHTTPClient; socketclient:TSocketHandler;//TInetSocket; scmd:string; buf:array[0..1024] of ansichar; begin // so := fpsocket(IPPROTO_TCP, SOCK_STREAM, 0); http := TFPHTTPClient.Create(self); ////http.Get('http://127.0.0.1'); //fpgethostbyname(); socketclient := ConnectToServer('163.com', 80, false); scmd := 'GET / http 1.0'#13#10#13#10#13#10; socketclient.Send(scmd[1], length(scmd)); //scmd[1] to "Const Buffer;" is ok FillChar(buf, sizeof(buf), #0); socketclient.Recv(buf, 100); end; end.
clq
2022-11-10 10:54:38 发表
编辑
//linux 下要安装两个包 //su apt search lazarus //sudo apt-get install lazarus //sudo apt-get install fpc //sudo apt-get install build-essential //sudo apt-get install gdb
clq
2022-11-10 11:20:20 发表
编辑
lazarus 在 linux 下输入中文有时会有问题,不过其实安装一个插件后可以用 vscode !!! OmniPascal - Open Preview Manage your Delphi and Free Pascal code with Visual Studio Code. For Windows, Mac and Linux! 配置好路径后很强。
clq
2022-11-10 11:22:52 发表
编辑
例如项目目录下可以加一个 .vscode/settings.json { "omnipascal.defaultDevelopmentEnvironment": "FreePascal", "omnipascal.delphiInstallationPath": "/usr/lib/lazarus/2.0.10", "omnipascal.freePascalSourcePath": "/usr/share/fpcsrc/3.2.0", "omnipascal.searchPath": "/usr/lib/lazarus/2.0.10/lcl" }
clq
2022-11-10 16:56:03 发表
编辑
从源码上看,在 linux 函数 gethostbyname 在 netdb 中,而在 windows 及其他操作系统中则比较啰嗦,建议按 x:\new\lazarus64\fpc\3.0.4\source\packages\fcl-net\src\resolve.pp 中的写法,用 THostResolver.NameLookup(FHost) 代替。 实在要用的话,可以参考这句话 {$ifdef usenetdb} uses netdb; {$else} {$i resolve.inc} {$endif} ------- {$ifndef win32} // Here till BSD supports the netbsd unit. // MvdV: NetBSD unit? Where? {$ifdef Unix} // Undefine this to use the C library resolve routines. // Don't use under win32, netdb does not work on Win32 (yet) !! {$define usenetdb} {$endif Unix} {$endif} ----- 即它是用 resolve.inc 代替的,而 resolve.inc 有很多个,在 fcl-net\src 之下,例如 fcl-net\src\win\resolve.inc 它直接用了 uses winsock; 所以是要自己写条件编译的,所以还不如直接用 THostResolver.NameLookup(FHost) 得了。
本帖子属于以下条目()
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.