2/ stNonBlocking
介绍stNonBlocking之前,要先介绍TserverClientWinSocket
TServerClientWinSocket.Create 中
inherited Create(Socket);
if FServerWinSocket.ASyncStyles <> [] then DoSetAsyncStyles;
TserverClientWinSocket 是从TcustomWinSocket继承下来的
FASyncStyles := [asRead, asWrite, asConnect, asClose];
接下来看TCustomWinSocket.DoSetAsyncStyles
if FAsyncStyles <> [] then
begin
Msg := CM_SOCKETMESSAGE;
Wnd := Handle;
end;
WSAAsyncSelect(FSocket, Wnd, Msg, Longint(Byte(FAsyncStyles)));
使用了WSAAsyncSelect 用一个窗口来接受CM_SOCKETMESSAGE 消息来标示网络消息,消息类型 在TCustomWinSocket.Create中设置为 FASyncStyles := [asRead, asWrite, asConnect, asClose];asRead, asWrite, asConnect, asClose就是接受的网络消息类型。
TCustomWinSocket.CMSocketMessage函数来出来消息CM_SOCKETMESSAGE
with Message do
if CheckError then
case SelectEvent of
FD_CONNECT: Connect(Socket);
FD_CLOSE: Disconnect(Socket);
FD_READ: Read(Socket);
FD_WRITE: Write(Socket);
FD_ACCEPT: Accept(Socket);
end;
根据网络类型调用不同的函数
现在开始stNonBlocking类型的研究
TServerWinSocket.Listen 中
inherited Listen(Name, Address, Service, Port, QueueSize, ServerType = stThreadBlocking);
调用的父类的Listen
TCustomWinSocket.Listen中
FSocket := socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
if FSocket = INVALID_SOCKET then raise ESocketError.CreateRes(@sCannotCreateSocket);
try
Event(Self, seLookUp);
if Block then
begin
FAddr := InitSocket(Name, Address, Service, Port, False);
DoListen(QueueSize);
end else
AsyncInitSocket(Name, Address, Service, Port, QueueSize, False);
初始化socket ,然后调用了AsyncInitSocket
AsyncInitSocket就是用递归的来实现了端口,地址的解析,最后调用DoListen
TCustomWinSocket.DoListen 中
CheckSocketResult(bind(FSocket, FAddr, SizeOf(FAddr)), 'bind');
DoSetASyncStyles;
if QueueSize > SOMAXCONN then QueueSize := SOMAXCONN;
Event(Self, seListen);
CheckSocketResult(Winsock.listen(FSocket, QueueSize), 'listen');
FLookupState := lsIdle;
FConnected := True;
绑定端口,监听,
在DoSetASyncStyles中用WSAAsyncSelect实现用窗口接受网络事件消息,不过事件类型在
TServerWinSocket.Create中初始化为asAccept , FAsyncStyles := [asAccept];
TserverWinSocket重载了Accept函数TServerWinSocket.Accept中
ClientWinSocket := WinSock.accept(Socket, @Addr, @Len);
if ClientWinSocket <> INVALID_SOCKET then
begin
ClientSocket := GetClientSocket(ClientWinSocket);
if Assigned(FOnSocketEvent) then
FOnSocketEvent(Self, ClientSocket, seAccept);
接受socket,把socket转换为TserverClientWinSocket
TServerWinSocket.GetClientSocket中
Result := TServerClientWinSocket.Create(Socket, Self);
产生了一个TserverClientWinSocket对象,按照我们开始研究的时候,TserverClientWinSocket生成一个窗口自动接受socket消息。
总结:
TserverWinSocket创建一个窗口只接受accept网络消息,当消息来了后accept客户端的socket,把客户端的socket转换成TserverClientWinSocket,TserverClientWinSocket也创建一个窗口接受asRead, asWrite, asConnect, asClose网络消息。