|
Len: Integer;
OldOpenType, NewOpenType: Integer;
begin
Len := SizeOf(OldOpenType);
//得到与指定套接口相关的属性选项。
if getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, PChar(@OldOpenType),
Len) = 0 then
try
if FServerType = stThreadBlocking then
begin
NewOpenType := SO_SYNCHRONOUS_NONALERT;
//设置与指定套接口相关的属性选项。
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, PChar(@NewOpenType), Len);
end;
Len := SizeOf(Addr);
调用SocketAPI,返回一个新的套接字与客户端进行通信
ClientWinSocket := WinSock.accept(Socket, @Addr, @Len);
if ClientWinSocket <> INVALID_SOCKET then
begin
ClientSocket := GetClientSocket(ClientWinSocket);
if Assigned(FOnSocketEvent) then
FOnSocketEvent(Self, ClientSocket, seAccept);
if FServerType = stThreadBlocking then
begin
ClientSocket.ASyncStyles := [];
GetServerThread(ClientSocket);
end;
end;
finally
Len := SizeOf(OldOpenType);
setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, PChar(@OldOpenType), Len);
end;
end;
我们只针对我们非阻塞模式来看几个重要的语句,上面已经用蓝色标识出来了。首先:
ClientWinSocket := WinSock.accept(Socket, @Addr, @Len);
调用WinSock的API,Accept得到一个与客户端进行通信的Socket,而原来的Socket则继续监听。
ClientSocket := GetClientSocket(ClientWinSocket);
ClientSocket是一个TServerClientWinSocket类的对象,这个对象就是代表与客户端通信的Socket类,那么GetClientSocket必定是以参数WinSocket创建了一个TServerClientWinSocket对象,看代码去:
(411)
function TServerWinSocket.GetClientSocket(Socket: TSocket): TServerClientWinSocket;
begin
Result := nil;
if Assigned(FOnGetSocket) then FOnGetSocket(Self, Socket, Result);
if Result = nil then
Result := TServerClientWinSocket.Create(Socket, Self);
end;
果然其中创建了这个类的对象,不但传入了上面的WinSocket,还传递了ServerWinSocket自己,继续吧,不要言累:
(4111)
constructor TServerClientWinSocket.Create(Socket: TSocket; ServerWinSocket: TServerWinSocket);
begin
FServerWinSocket := ServerWinSocket;
if Assigned(FServerWinSocket) then
begin
FServerWinSocket.AddClient(Self);
if FServerWinSocket.AsyncStyles <> [] then
begin
OnSocketEvent := FServerWinSocket.ClientEvent;
OnErrorEvent := FServerWinSocket.ClientError;
end;
end;
inherited Create(Socket);
if FServerWinSocket.ASyncStyles <> [] then DoSetAsyncStyles;
if FConnected then Event(Self, seConnect);
end;
这里两个重要的语句已经标出来了,第一句,它调用了传进来的ServerWinSocket的方法AddClient,看看这个怎么实现的:
(41111)
procedure TServerWinSocket.AddClient(AClient: TServerClientWinSocket);
begin
FListLock.Enter;
try
if FConnections.IndexOf(AClient) < 0 then
FConnections.Add(AClient);
finally
FListLock.Leave;
end;
end;
哈,这个方法的意思已经很明显了,他就是把这个与客户端的通信的Socket加入了一个列表中,这个列表已经在前面看到创建了的,便于以后维护。
上面函数接下的另一句inherited Create(Socket);则是其父类TCustomWinSocket的构造函数了,上面我们已经分析过了,就是将这个与客户端的连接的Socket赋给成员FSocket。
最后我们得回过头到Accept方法再去看最后一个重要语句:
FOnSocketEvent(Self, ClientSocket, seAccept);
OnAccept终于发生了,我们可以在这里事件中向客户端发送一些信息!
5.分析到这里,接下来就是WinSock的事了,客户端和服务端开始通信,于是它向这些类发送消息,然后传递事件处理函数,就可以进行非阻塞的数据传输,而那些数据传递函数最终也都是调用Socket的API,所以我想也不要多说了,看看源代码吧。大概的脉络其实在第2步中说得也差不多了。
执行到最后,会设Active为False,回顾上面的代码,则会调用Socket的父类:
TCustomWinSocket.Disconnect,不过ServerSokcet又覆盖了这个方法,它所完成的功能只是释放掉所有的线程,最后还是会调用父类的这个方法。
(51)
procedure TCustomWinSocket.Disconnect(Socket: TSocket);
begin
Lock;
try
if FLookupHandle <> 0 then
CheckSocketResult(WSACancelASyncRequest(FLookupHandle), ''''WSACancelASyncRequest'''');
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] 下一页 没有相关教程
|