跳转至主要内容

大约18个月前,我写了一篇博客,谈到了OpenVOS 17.1版本中accept工作方式的变化。我忽略了一点,那就是这些变化只有在应用程序代码是基于POSIX的情况下才会生效。简而言之,在17.1之前,STCP只有在服务器应用程序代码调用了accept例程的情况下才会回复客户端连接请求。如果代码没有调用accept,客户端的连接请求将进入队列,但不会被回复。一旦应用程序调用了accept,STCP将发送一个连接回复。如果客户端还在等待,此时连接就会完成。如果客户端已经放弃了,则会对连接回复做出复位的响应,STCP会将连接丢弃,accept会挂起(假设阻塞模式),等待另一个连接。

图1显示的是这个场景,左边公正的文本行是服务器应用程序的状态信息,缩进的packet_monitor行(略作修改)是客户端活动的结果。应用程序(acceptTestnoPosix)被启动,并在12345端口上监听,一旦监听就会进入300秒的睡眠状态。然后,客户端向12345端口发送一个TCP段,并设置Syn (S)标志,从而实现对12345端口的连接。在放弃之前,它尝试了三次。300秒后,应用程序唤醒并调用accept。STCP协议栈用一个设置了Syn和Ack(SA)标志的TCP段回复客户端。由于客户端不再有连接记录,如果发送一个Reset(R),STCP此时就会阻塞。如果套接字处于非阻塞模式,accept会返回一个EAGAIN错误。

acceptTestnoPosix 12345
执行 acceptTestnoPosix 12345。
睡眠300秒

  11:04:45.923 R TCP 164.152.77.50 164.152.77.217 11071 12345 S
  11:04:48.925 R TCP 164.152.77.50 164.152.77.217 11071 12345 S
  11:04:54.937 R TCP 164.152.77.50 164.152.77.217 11071 12345 S

准备接受12345端口的连接。
  11:09:41.852 T TCP 164.152.77.217 164.152.77.50 12345 11071 SA 
  11:09:41.854 R TCP 164.152.77.50 164.152.77.217 11071 12345 R

图1----接受17.1之前或17.1之后的非POSIX。

 

如果应用程序是基于POSIX的,情况就不同了(图2)。STCP会立即回复连接请求(S)(SA)。然后在300秒后,应用程序唤醒,调用accept,STCP返回接受的socket。

acceptTestwithPosix 12345
执行 acceptTestnoPosix 12345。
睡眠300秒

  10:58:43.962 R TCP 164.152.77.50 164.152.77.217 11024 12345 S
  10:58:43.964 T TCP 164.152.77.217 164.152.77.50 12345 11024 SA 
  10:58:43.964 R TCP 164.152.77.50 164.152.77.217 11024 12345A

准备接受12345端口的连接。
连接接受

图2--接受基于POSIX的17.1职位。

 

行为上的差异可能很关键。如果客户端在建立连接后期待服务器应用程序的响应,它可能会在应用程序实际调用accept之前超时并关闭连接。

如何用POSIX构建一个应用程序?首先是行

#define _POSIX_C_SOURCE 200112L

应该是应用程序源代码的第一行。其次是库的路径

(master_disk)>system>posix_object_library。

需要在对象库路径中位于STCP库之后,C库之前。

如何判断是否已经完成?你可以使用display_program_module -object_dirs命令查看应用程序绑定的对象库。

display_program_module acceptTestwithPosix -object_dirs      
     %azvos#m17_mas>SysAdmin>Noah_Davids>temp>acceptTestwithPosix.pm。 

对象目录图。

    11个搜索目录
     0个非搜索目录
    共11个目录

   DTC目录路径

     1 %azvos#m17_mas>SysAdmin>Noah_Davids>temp。
     2 %azvos#m17_mas>system>stcp>object_library。
     3 %azvos#m17_mas>system>stcp>object_library>socket。
     4 %azvos#m17_mas>system>stcp>object_library>net。
     5 %azvos#m17_mas>system>stcp>object_library>common。
     6 %azvos#m17_mas>system>posix_object_library。
     7 %azvos#m17_mas>系统>c_object_library。
     8 %azvos#m17_mas>system>object_library
     9 %azvos#m17_mas>opt>apache>lib
    10 %azvos#m17_mas>opt>openssl>lib
    11 %azvos#m17_mas>opt>mysql>lib>mysql。

但这并不能告诉你#define是否是源代码的一部分。

如果你能运行代码,你可以看一下socket标志,一个基于POSIX的程序会设置SF_POSIX socket标志。例如,我有三个程序acceptTestnoPosix、acceptTestwithPosix和acceptTestwithPosixPathOnly。最后一个程序的库路径中有>system>posix_object_library目录,但在源代码中没有包含#define。注意,这被认为是一个无效的组合。只有与POSIX库绑定并在代码中包含POSIX_SOURCE #define语句的应用程序才创建了一个带有SF_POSIX标志的套接字。

acceptTestnoPosix.pm 12345     
执行 acceptTestnoPosix 12345。
睡眠300秒
               as: match posix; dump_stcbq -full -lport 12345。       
               作为:
acceptTestwithPosix.pm 12345
执行 acceptTestnoPosix 12345。
睡眠300秒
               as: match posix; dump_stcbq -full -lport 12345。
                                                   SF_POSIX
               作为。  
acceptTestwithPosixPathOnly.pm 12345
执行 acceptTestnoPosix 12345。
睡眠300秒
               as: match posix; dump_stcbq -full -lport 12345。
               作为:

还有第四种可能,源码中包含了#define,但没有使用posix_object_library。在这种情况下,socket例程会返回一个错误。

acceptTestwithPosixDefineOnly 12345
执行 acceptTestnoPosix 12345。
acceptTestnoPosix:无法创建监听套接字。应用程序建立  
+不正确。POSIX运行时必须在C运行时之前搜索。

所有的STCP命令和实用程序都是用POSIX构建的,我强烈建议你构建的任何应用程序也使用POSIX。

© 2020 Stratus Technologies.