没有找到合适的产品?
联系客服协助选型:023-68661681
提供3000多款全球软件/控件产品
针对软件研发的各个阶段提供专业培训与技术咨询
根据客户需求提供定制化的软件开发服务
全球知名设计软件,显著提升设计质量
打造以经营为中心,实现生产过程透明化管理
帮助企业合理产能分配,提高资源利用率
快速打造数字化生产线,实现全流程追溯
生产过程精准追溯,满足企业合规要求
以六西格玛为理论基础,实现产品质量全数字化管理
通过大屏电子看板,实现车间透明化管理
对设备进行全生命周期管理,提高设备综合利用率
实现设备数据的实时采集与监控
利用数字化技术提升油气勘探的效率和成功率
钻井计划优化、实时监控和风险评估
提供业务洞察与决策支持实现数据驱动决策
翻译|其它|编辑:郝浩|2005-02-25 09:51:00.000|阅读 1781 次
概述:
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
下面开始TServerSockett和TClientSocket的原代码阅读:
不过在分析之前,先要明白,对于WinSock的封装其实是由ScktComp单元的几个类一起完成的,它们的关系是:
TServerSocket继承于TCustomServerSocket
TCustomServerSocket继承于TCustomSocket
TCustomSocket继承于TAbstractSocket而TAbstractSockeet的上级则是TComponent了
TClientSocket继承于TCustomSocket
另外还有几个类:
TServerWinSocket和TClientWinSocket以及TServerClientWinSocket继承TCustomSocket
它们才是真正封装Socket的类。作为上面提到的类的成员存在
此外还有几个用于阻塞式传输的类。这里就忽略不讲了,以后有机会再补上来吧。
以ServerSocket和ClientSocket的一次操作流程来跟踪它们的源代码,看看他们是怎么样封WinSocket的。以非阻塞方式来例子。
1. ServerSocket要创建,构造函数如下:
(11)
constructor TServerSocket.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FServerSocket := TServerWinSocket.Create(INVALID_SOCKET);
InitSocket(FServerSocket);
FServerSocket.ThreadCacheSize := 10;
end;
inherited Create(AOwner);是继承自TComponent的构造函数。
接下来创建它的一个成员,这是一个TServerWinSocket的对象,这个才是真正封装SocketApi的类,等一个讨论它。事实上这个构造函数继承自它的父类TCustomServerSocket
接下来调用InitSocket(FServerSocket);这是ServerSocket的祖先类TAbstractSocket的一个方法,传入参数是成员FserverSocket完成的功能是将ServerSocket的事件指针指向TServerWinSocket的事件,使其能处理Socket触发的事件。
最后,设置FServerSocket允许连接的线程数,这里为10。
好,现在回过头来看看FServerSocket := TServerWinSocket.Create(INVALID_SOCKET);做了什么:
(111)
constructor TServerWinSocket.Create(ASocket: TSocket);
begin
FConnections := TList.Create;
FActiveThreads := TList.Create;
FListLock := TCriticalSection.Create;
inherited Create(ASocket);
FAsyncStyles := [asAccept];
end;
首先创建两个TList对象,一个是FConnections,代表各个处理客户连接的Socket,它对应于属性:property
Connections[Index: Integer]: TCustomWinSocket,你可以通过这个属性对各个客户连接进行操作。FActiveThreads
管理由Connections 数组确定的的客户端连接线程TServerClientThread,它对应的属性是ActiveThreads,这个是只读属性,返回当前正在使用的TServerClientThread对象的个数。接下来创建互斥量对象,用于线程同步的处理。
到这里又调用其父类的构造函数,传递的参数就是ServerSocket给的值INVALID_SOCKET,(想想上面提到的这个值的意义)
好,再继续跟踪,到其父类的构造函数去看一下,我们这时应该保留一个问题,按照WinSock的编程模式,刚开始应该是初始化Winsock.DLL,并调用绑定监听函数,这些API是什么在地方被调用呢?
(1111)
constructor TCustomWinSocket.Create(ASocket: TSocket);
begin
inherited Create;
Startup;
FSocketLock := TCriticalSection.Create;
FASyncStyles := [asRead, asWrite, asConnect, asClose];
FSocket := ASocket;
FAddr.sin_family := PF_INET;
FAddr.sin_addr.s_addr := INADDR_ANY;
FAddr.sin_port := 0;
FConnected := FSocket <> INVALID_SOCKET;
end;
首先调用TObject的构造函数,
再调用Sartup;分析完这个函数再看里面的代码,这里可以猜测它里面会调用WSAStartup函数。
接下来看到从ServerSocket传过来的参数指定给了TCustomWinSocket的成员,还有下面几个成员的设置,可以肯定,这里是对Socket进行初始化,结合开头所讲的知识,再看看源代码。应该不难理解了吧。
再看看Startup的源码:
(11111)
procedure Startup;
var
ErrorCode: Integer;
begin
ErrorCode := WSAStartup($0101, WSAData);
if ErrorCode <> 0 then
raise ESocketError.CreateResFmt(@sWindowsSocketError,
[SysErrorMessage(ErrorCode), ErrorCode, 'WSAStartup']);
end;
这是一个全局函数,看到其中一行重要的代码了,
ErrorCode := WSAStartup($0101, WSAData);WinSock就是在这里被初始化的。
而在服务端没有建立监听之时,Socket就在上面被默认设置了。
好,现在ServerSocket的成员FserverSocket的创建就完成了,再回到最上面,
FServerSocket := TServerWinSocket.Create(INVALID_SOCKET);之后,便是
InitSocket(FServerSocket);了,看看它的代码:
(12)
procedure TAbstractSocket.InitSocket(Socket: TCustomWinSocket);
begin
Socket.OnSocketEvent := DoEvent;
Socket.OnErrorEvent := DoError;
end;
正好和上面所说的一样,现在可以认为当Socket发生了事件(比如连接,接收等)之后,就是调用了DoEvent了,错误发生了也一样。不妨看看DoEvent代码:
(121)
procedure TAbstractSocket.DoEvent(Sender: TObject; Socket: TCustomWinSocket;
SocketEvent: TSocketEvent);
begin
Event(Socket, SocketEvent);
end;
里面是调用Event,再看看Event的声明:
procedure Event(Socket: TCustomWinSocket; SocketEvent: TSocketEvent);virtual;
abstract;
这是一个抽象函数,由此可以知道,TAbstractSocket是一个抽象的类,它只是封装了一般的操作,具体地都留到了它的子类中去了,所以它的子类一定覆盖了这个Event方法,而DoEvent中调用的Event实际上就是调用它子类的Event方法,这个就是典型的模板模式。
好,看看它的子类有没有覆盖这个方法,果然在TCustomSocket中看到了这个方法,并实现了它,看看它的源代码:
(1211)
procedure TCustomSocket.Event(Socket: TCustomWinSocket; SocketEvent:
TSocketEvent);
begin
case SocketEvent of
seLookup: if Assigned(FOnLookup) then FOnLookup(Self, Socket);
seConnecting: if Assigned(FOnConnecting) then FOnConnecting(Self, Socket);
seConnect:
begin
FActive := True;
if Assigned(FOnConnect) then FOnConnect(Self, Socket);
end;
seListen:
begin
FActive := True;
if Assigned(FOnListen) then FOnListen(Self, Socket);
end;
seDisconnect:
begin
FActive := False;
if Assigned(FOnDisconnect) then FOnDisconnect(Self, Socket);
end;
seAccept: if Assigned(FOnAccept) then FOnAccept(Self, Socket);
seRead: if Assigned(FOnRead) then FOnRead(Self, Socket);
seWrite: if Assigned(FOnWrite) then FOnWrite(Self, Socket);
end;
end;
其中FonAccept等这些都是TCusotmSocket的成员,都是TSocketNotifyEvent类型的,TCustomSocket还通过下面这些属性,使该类拥有了这些事件处理的能力:
property OnLookup: TSocketNotifyEvent read FOnLookup write FOnLookup;
property OnConnecting: TSocketNotifyEvent read FOnConnecting write FOnConnecting;
property OnConnect: TSocketNotifyEvent read FOnConnect write FOnConnect;
property OnDisconnect: TSocketNotifyEvent read FOnDisconnect write FOnDisconnect;
property OnListen: TSocketNotifyEvent read FOnListen write FOnListen;
property OnAccept: TSocketNotifyEvent read FOnAccept write FOnAccept;
property OnRead: TSocketNotifyEvent read FOnRead write FOnRead;
property OnWrite: TSocketNotifyEvent read FOnWrite write FOnWrite;
而上面的Event实现,我们可以看到它是根据SocketEvent的类型来调用相应的事件指针的,而它的子类ServerSocket和ClientSocket也拥有了这些事件的处理能力,到这里我们终于明白了,它们的事件是怎么样出来的,但如果想得知这些事件是怎么触发的,还要看这一句:Socket.OnSocketEvent,OnSocketEvent到后面再说,这里先略。
错误处理事件原理上也是一样,到后面再说。
好了,到这里第一步解读完毕,我们所知道的ServerSocket创建之后所完成事件就是初始化Socket
DLL,并指定好事件处理的方法指针和错误处理的方法指针。我们接下来看第二步。
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
面对“数字中国”建设和中国制造2025战略实施的机遇期,中车信息公司紧跟时代的步伐,以“集约化、专业化、标准化、精益化、一体化、平台化”为工作目标,大力推进信息服务、工业软件等核心产品及业务的发展。在慧都3D解决方案的实施下,清软英泰建成了多模型来源的综合轻量化显示平台、实现文件不失真的百倍压缩比、针对模型中的大模型文件,在展示平台上进行流畅展示,提升工作效率,优化了使用体验。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
服务电话
重庆/ 023-68661681
华东/ 13452821722
华南/ 18100878085
华北/ 17347785263
客户支持
技术支持咨询服务
服务热线:400-700-1020
邮箱:sales@evget.com
关注我们
地址 : 重庆市九龙坡区火炬大道69号6幢
慧都科技 版权所有 Copyright 2003-
2025 渝ICP备12000582号-13 渝公网安备
50010702500608号