打印本文 打印本文 关闭窗口 关闭窗口
ServerSocket,ClientSocket控件源码阅读笔记
作者:武汉SEO闵涛  文章来源:敏韬网  点击数7769  更新时间:2009/4/23 18:28:00  文章录入:mintao  责任编辑:mintao
  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]  下一页

打印本文 打印本文 关闭窗口 关闭窗口