大约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。