TserverSocket 分析3

本文详细介绍了基于WinSocket的非阻塞IO机制。通过分析TServerWinSocket和TServerClientWinSocket类的工作原理,阐述了如何使用WSAAsyncSelect进行事件驱动,以及客户端连接的接受过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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转换成TserverClientWinSocketTserverClientWinSocket也创建一个窗口接受asRead, asWrite, asConnect, asClose网络消息。

org.apache.thrift.transport.TTransportException: Could not create ServerSocket on address 0.0.0.0/0.0.0.0:9083. at org.apache.thrift.transport.TServerSocket.<init>(TServerSocket.java:109) at org.apache.thrift.transport.TServerSocket.<init>(TServerSocket.java:91) at org.apache.thrift.transport.TServerSocket.<init>(TServerSocket.java:87) at org.apache.hadoop.hive.metastore.utils.SecurityUtils.getServerSocket(SecurityUtils.java:253) at org.apache.hadoop.hive.metastore.HiveMetaStore.startMetaStore(HiveMetaStore.java:8979) at org.apache.hadoop.hive.metastore.HiveMetaStore.main(HiveMetaStore.java:8854) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.hadoop.util.RunJar.run(RunJar.java:323) at org.apache.hadoop.util.RunJar.main(RunJar.java:236) Caused by: java.net.BindException: Address already in use (Bind failed) at java.net.PlainSocketImpl.socketBind(Native Method) at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:513) at java.net.ServerSocket.bind(ServerSocket.java:375) at org.apache.thrift.transport.TServerSocket.<init>(TServerSocket.java:106) ... 11 more Exception in thread "main" org.apache.thrift.transport.TTransportException: Could not create ServerSocket on address 0.0.0.0/0.0.0.0:9083. at org.apache.thrift.transport.TServerSocket.<init>(TServerSocket.java:109) at org.apache.thrift.transport.TServerSocket.<init>(TServerSocket.java:91) at org.apache.thrift.transport.TServerSocket.<init>(TServerSocket.java:87) at org.apache.hadoop.hive.metastore.utils.SecurityUtils.getServerSocket(SecurityUtils.java:253) at org.apache.hadoop.hi
最新发布
04-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值