登录 用户中心() [退出] 后台管理 注册
   
您的位置: 首页 >> SoftHub关联区 >> 主题: 目前 lazarus 的原始 socket 函数并没有写完整的跨平台,不推荐使用[更新,按一种方式也可以]     [回主站]     [分站链接]
目前 lazarus 的原始 socket 函数并没有写完整的跨平台,不推荐使用[更新,按一种方式也可以]
clq
浏览(470) - 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) 得了。






总数:6 页次:1/1 首页 尾页  
总数:6 页次:1/1 首页 尾页  


所在合集/目录
lazarus不同于delphi的地方 更多
lazarus开发 更多



发表评论:
文本/html模式切换 插入图片 文本/html模式切换


附件:



NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.

Copyright © 2005-2020 clq, All Rights Reserved
版权所有
桂ICP备15002303号-1