之前使用的tcp相关库都对超时作了很完善的封装…换成posix之后突然不知道超时该如何设置了…

对于tcp/ip来讲,建立连接传输数据的大致过程如下:(以下代码没有释放socket,真正实用时一定要记的在适合的地方释放掉socket)

  1. // client
  2. 1.创建一个socket(此时仅仅指定了socket的协议类型,还没有进行进行绑定,
  3. 换言之此时socket还不知道自己要和谁进行通信)
  4. 2.指明ipport,建立连接(经过这一步,socket就知道自己需要和谁进行通信了)
  5. 3.发送数据
  6. //server
  7. 1.创建socketA(同样的,此时serversocket也不知道自己将和谁进行通信)
  8. 2.bind(这一步指明了ipport
  9. 3.listen
  10. 4.accept(和client不同,server的第一步创建出来的socketA并不是真正负责通信的那个,
  11. socketA只负责监听,对应clientconnect方法,clientconnect将会作用于server
  12. 如果accept成功的话将会创建一个socketBsocketB才是真正负责通信的)
  13. 4.recv

tcp的超时

用事实来说话….首先不设置任何超时状态,按照原始tcp调用方式,使用strace查看系统调用:(长代码警告)

  1. xxxxxxxxxxxxx:~# strace lua testTCPClient.lua
  2. execve("/usr/bin/lua", ["lua", "testTCPClient.lua"], [/* 13 vars */]) = 0
  3. set_thread_area(0x77eced48) = 0
  4. set_tid_address(0x77ec7cac) = 4392
  5. open("/etc/ld-musl-mipsel-sf.path", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
  6. open("/lib/liblua.so.5.1.5", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
  7. open("/usr/local/lib/liblua.so.5.1.5", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
  8. open("/usr/lib/liblua.so.5.1.5", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
  9. fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
  10. fstat64(3, {st_mode=S_IFREG|0644, st_size=148372, ...}) = 0
  11. read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0p8\0\0004\0\0\0"..., 936) = 936
  12. mmap2(NULL, 196608, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x77df4000
  13. mmap2(0x77e22000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x1e000) = 0x77e22000
  14. close(3) = 0
  15. open("/lib/libgcc_s.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
  16. fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
  17. fstat64(3, {st_mode=S_IFREG|0644, st_size=84152, ...}) = 0
  18. read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\0(\0\0004\0\0\0"..., 936) = 936
  19. mmap2(NULL, 143360, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x77dd0000
  20. mmap2(0x77df2000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x12000) = 0x77df2000
  21. close(3) = 0
  22. mprotect(0x77e22000, 4096, PROT_READ) = 0
  23. mprotect(0x412000, 4096, PROT_READ) = 0
  24. brk(NULL) = 0x9a2000
  25. brk(0x9a3000) = 0x9a3000
  26. brk(0x9a4000) = 0x9a4000
  27. brk(0x9a5000) = 0x9a5000
  28. open("testTCPClient.lua", O_RDONLY|O_LARGEFILE) = 3
  29. brk(0x9a6000) = 0x9a6000
  30. readv(3, [{iov_base="", iov_len=0}, {iov_base="local socket = require(\"posix.sy"..., iov_len=1024}], 2) = 272
  31. readv(3, [{iov_base="", iov_len=751}, {iov_base="", iov_len=1024}], 2) = 0
  32. close(3) = 0
  33. rt_sigprocmask(SIG_UNBLOCK, [RT_1 RT_2], NULL, 16) = 0
  34. rt_sigaction(SIGINT, {sa_handler=0x400ea1, sa_mask=[RT_68 RT_69 RT_73 RT_74 RT_75 RT_76 RT_78 RT_81 RT_82 RT_86 RT_87 RT_88 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0}, {sa_handler=SIG_DFL, sa_mask=[RT_79 RT_83 RT_84 RT_86 RT_87 RT_88 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=0}, 16) = 0
  35. open("./posix/sys/socket.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  36. open("/usr/share/lua/posix/sys/socket.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  37. open("/usr/share/lua/posix/sys/socket/init.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  38. open("/usr/lib/lua/posix/sys/socket.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  39. open("/usr/lib/lua/posix/sys/socket/init.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  40. brk(0x9a7000) = 0x9a7000
  41. open("./posix/sys/socket.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  42. open("/usr/lib/lua/posix/sys/socket.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  43. open("/usr/lib/lua/loadall.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  44. open("./posix.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  45. open("/usr/lib/lua/posix.so", O_RDONLY|O_LARGEFILE) = 3
  46. brk(0x9a8000) = 0x9a8000
  47. close(3) = 0
  48. open("/usr/lib/lua/posix.so", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
  49. fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
  50. fstat64(3, {st_mode=S_IFREG|0755, st_size=90860, ...}) = 0
  51. read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\3600\0\0004\0\0\0"..., 936) = 936
  52. mmap2(NULL, 151552, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x77daa000
  53. mmap2(0x77dcd000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x13000) = 0x77dcd000
  54. close(3) = 0
  55. mprotect(0x77dcd000, 4096, PROT_READ) = 0
  56. brk(0x9aa000) = 0x9aa000
  57. socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
  58. connect(3, {sa_family=AF_INET, sin_port=htons(8383), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
  59. sendto(3, "Testipv4", 8, 0, NULL, 0) = 8
  60. recvfrom(3, "Test", 4, 0, NULL, NULL) = 4
  61. ioctl(1, TIOCGWINSZ, 0x7f9c8078) = 0
  62. writev(1, [{iov_base="Test", iov_len=4}, {iov_base="\n", iov_len=1}], 2Test
  63. ) = 5
  64. open("./posix/unistd.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  65. open("/usr/share/lua/posix/unistd.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  66. open("/usr/share/lua/posix/unistd/init.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  67. open("/usr/lib/lua/posix/unistd.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  68. open("/usr/lib/lua/posix/unistd/init.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  69. open("./posix/unistd.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  70. open("/usr/lib/lua/posix/unistd.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  71. open("/usr/lib/lua/loadall.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  72. open("./posix.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
  73. open("/usr/lib/lua/posix.so", O_RDONLY|O_LARGEFILE) = 4
  74. close(4) = 0
  75. brk(0x9ab000) = 0x9ab000
  76. brk(0x9ad000) = 0x9ad000
  77. close(3) = 0
  78. rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[RT_68 RT_69 RT_73 RT_74 RT_75 RT_76 RT_78 RT_81 RT_82 RT_86 RT_87 RT_88 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0}, {sa_handler=0x400ea1, sa_mask=[RT_67 RT_68 RT_72 RT_73 RT_75 RT_76 RT_77 RT_78 RT_79 RT_83 RT_84 RT_86 RT_87 RT_88 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0}, 16) = 0
  79. exit_group(0) = ?

抛开加载各种库,真正用于发送的代码从57行开始,真正的发送位于59行,系统调用sendto;sendto参数如下
ssize_t sendto(int sockfd, const void buf, size_t len, int flags,const struct sockaddr dest_addr, socklen_t addrlen);
这样并看不出什么东西…所以现在让我来给client添加一个send超时(10s),再来抓一下系统调用
系统调用中多了一行

  1. setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, "\5\0\0\0\0\0\0\0", 8) = 0

int getsockopt(int sockfd, int level, int optname,void optval, socklen_t optlen);

测试

给server的recv之前添加一个大于10s的延迟,这样server不会在client发送后的5s内执行接收

  1. local socket = require("posix.sys.socket")
  2. local sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM,0)
  3. socket.connect(sock,{family=socket.AF_INET,addr="127.0.0.1",port=8383})
  4. --send out of time
  5. socket.setsockopt(sock,socket.SOL_SOCKET,socket.SO_SNDTIMEO,5,0)
  6. socket.setsockopt(sock,socket.SOL_SOCKET,socket.SO_RCVTIMEO,5,0)
  7. local ok,err = socket.send(sock, 'Testipv4')
  8. assert(ok ~= nil , err)
  9. print(socket.recv(sock,4))
  10. require'posix.unistd'.close(sock)

令我意外的是…发送超时并没有生效,反而是接收超时生效了….这个问题目前已经超出了我的知识范围,不过这篇文章的目的已经达到了,send超时为何没有生效的问题以后在探究…以下为本次执行的系统调用

execve("/usr/bin/lua", ["lua", "testTCPClient.lua"], [/* 13 vars */]) = 0
set_thread_area(0x779c8d48)             = 0
set_tid_address(0x779c1cac)             = 18836
open("/etc/ld-musl-mipsel-sf.path", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/liblua.so.5.1.5", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/local/lib/liblua.so.5.1.5", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/liblua.so.5.1.5", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
fstat64(3, {st_mode=S_IFREG|0644, st_size=148372, ...}) = 0
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0p8\0\0004\0\0\0"..., 936) = 936
mmap2(NULL, 196608, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x778ee000
mmap2(0x7791c000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x1e000) = 0x7791c000
close(3)                                = 0
open("/lib/libgcc_s.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
fstat64(3, {st_mode=S_IFREG|0644, st_size=84152, ...}) = 0
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\0(\0\0004\0\0\0"..., 936) = 936
mmap2(NULL, 143360, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x778ca000
mmap2(0x778ec000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x12000) = 0x778ec000
close(3)                                = 0
mprotect(0x7791c000, 4096, PROT_READ)   = 0
mprotect(0x412000, 4096, PROT_READ)     = 0
brk(NULL)                               = 0x675000
brk(0x676000)                           = 0x676000
brk(0x677000)                           = 0x677000
brk(0x678000)                           = 0x678000
open("testTCPClient.lua", O_RDONLY|O_LARGEFILE) = 3
brk(0x679000)                           = 0x679000
readv(3, [{iov_base="", iov_len=0}, {iov_base="local socket = require(\"posix.sy"..., iov_len=1024}], 2) = 462
readv(3, [{iov_base="", iov_len=561}, {iov_base="", iov_len=1024}], 2) = 0
close(3)                                = 0
rt_sigprocmask(SIG_UNBLOCK, [RT_1 RT_2], NULL, 16) = 0
rt_sigaction(SIGINT, {sa_handler=0x400ea1, sa_mask=[RT_68 RT_69 RT_73 RT_74 RT_75 RT_76 RT_79 RT_80 RT_82 RT_85 RT_88 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0}, {sa_handler=SIG_DFL, sa_mask=[RT_78 RT_79 RT_80 RT_81 RT_82 RT_84 RT_85 RT_88 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=0}, 16) = 0
open("./posix/sys/socket.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/share/lua/posix/sys/socket.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/share/lua/posix/sys/socket/init.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/lua/posix/sys/socket.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
brk(0x67a000)                           = 0x67a000
open("/usr/lib/lua/posix/sys/socket/init.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("./posix/sys/socket.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/lua/posix/sys/socket.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/lua/loadall.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("./posix.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/lua/posix.so", O_RDONLY|O_LARGEFILE) = 3
brk(0x67b000)                           = 0x67b000
close(3)                                = 0
open("/usr/lib/lua/posix.so", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
fstat64(3, {st_mode=S_IFREG|0755, st_size=90860, ...}) = 0
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\10\0\1\0\0\0\3600\0\0004\0\0\0"..., 936) = 936
mmap2(NULL, 151552, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x778a4000
mmap2(0x778c7000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x13000) = 0x778c7000
close(3)                                = 0
mprotect(0x778c7000, 4096, PROT_READ)   = 0
brk(0x67d000)                           = 0x67d000
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(8383), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, "\5\0\0\0\0\0\0\0", 8) = 0
setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, "\5\0\0\0\0\0\0\0", 8) = 0
sendto(3, "Testipv4", 8, 0, NULL, 0)    = 8
recvfrom(3, 0x4138b0, 4, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
ioctl(1, TIOCGWINSZ, 0x7fe14d28)        = 0
writev(1, [{iov_base="nil\tResource temporarily unavail"..., iov_len=39}, {iov_base="\n", iov_len=1}], 2nil    Resource temporarily unavailable    11
) = 40
open("./posix/unistd.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/share/lua/posix/unistd.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/share/lua/posix/unistd/init.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/lua/posix/unistd.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/lua/posix/unistd/init.lua", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("./posix/unistd.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/lua/posix/unistd.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/lua/loadall.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("./posix.so", O_RDONLY|O_LARGEFILE) = -1 ENOENT (No such file or directory)
open("/usr/lib/lua/posix.so", O_RDONLY|O_LARGEFILE) = 4
close(4)                                = 0
brk(0x67e000)                           = 0x67e000
brk(0x680000)                           = 0x680000
close(3)                                = 0
rt_sigaction(SIGINT, {sa_handler=SIG_DFL, sa_mask=[RT_68 RT_69 RT_73 RT_74 RT_75 RT_76 RT_79 RT_80 RT_82 RT_85 RT_88 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0}, {sa_handler=0x400ea1, sa_mask=[RT_67 RT_68 RT_72 RT_73 RT_75 RT_76 RT_77 RT_83 RT_84 RT_85 RT_88 RT_89 RT_90 RT_91 RT_93 RT_94 RT_95], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0}, 16) = 0
exit_group(0)                           = ?
+++ exited with 0 +++

61行的返回值是 -1 EAGAIN (Resource temporarily unavailable);这样就足够了

发送超时

发送超时没有生效的原因在于…发送并没有超时,虽然没有被接收,但是发送确实是没有超时的