日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

套接字选项SO_LINGER

發布時間:2025/6/15 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 套接字选项SO_LINGER 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? ? ? ? ? ?在說明套接字選項SO_LINGER之前,我們來先看一個問題。如果發送緩沖區中還有數據沒有發送到對方協議棧,此時close發送端的socket會發生什么,下面代碼給出答案。

服務端:

?

#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <signal.h> #include <sys/wait.h>int main() {char recvbuf[100000]={0};int sockSrv = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in addrSrv;addrSrv.sin_family = AF_INET;addrSrv.sin_addr.s_addr =htonl(INADDR_ANY);addrSrv.sin_port = htons(8888);bind(sockSrv, (const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));listen(sockSrv, 5);sockaddr_in addrClient;socklen_t len=sizeof(addrClient);int sockConn = accept(sockSrv, (struct sockaddr *)&addrClient, &len);while(1){getchar();read(sockConn,recvbuf,sizeof(recvbuf)-1);}getchar();close(sockSrv);return 0; }

客戶端:

?

?

#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <error.h>int main() {int ret=0;int sockClient = socket(AF_INET, SOCK_STREAM, 0);char readbuf[175000]={0};struct sockaddr_in addrSrv;addrSrv.sin_addr.s_addr=inet_addr("127.0.0.1");addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(8888);ret=connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));write(sockClient,readbuf,sizeof(readbuf)+1);getchar();close(sockClient);return 0; }

?

編譯并運行,并用tcpdump進行抓包,在客戶端多按幾次回車鍵,用netstat命令查看情況。

?

[mapan@localhost ~]$ netstat -nao|grep 8888 tcp 0 0 0.0.0.0:8888 0.0.0.0:* LISTEN off (0.00/0/0) tcp 161018 0 127.0.0.1:8888 127.0.0.1:41282 ESTABLISHED off (0.00/0/0) tcp 0 124001 127.0.0.1:41282 127.0.0.1:8888 ESTABLISHED probe (0.19/0/1)

?

其中1611018為服務端接收緩沖區中的數據,124001為發送緩沖區中的數據。此時由于服務端沒有調用read函數讀取數據,服務端的接收緩沖區已滿,所以客戶端的發送緩沖區的數據不能由TCP到達服務端的接收緩沖區中。如果這時我們突然斷開客戶端,客戶端調用了close函數,close函數立即返回,發送緩沖區剩余的數據由系統接管將數據發送至對端,但是我們并不知道對方的是否已接收到數據,這時SO_LINGER選項改登場了。

?

SO_LINGER結構如下:

?

struct linger { int l_onoff //0=off, nonzero=on(開關) int l_linger //linger time(延遲時間) }

1)當l_onoff為0時,l_linger的值被忽略,這也是close的默認操作。

?

2)當l_onoff為0時,l_linger的值也為0。在這個情況下,close將會延遲l_linger秒,這里是0秒。此時當調用close的時候,TCP連接會立即斷開。發送緩沖區里面剩余的數據將被丟棄,并向對方發送一個RST,這是非正常的斷開連接。下面看代碼,服務端不變,客戶端稍微變一下。

客戶端:

?

#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <error.h>int main() {int ret=0;int sockClient = socket(AF_INET, SOCK_STREAM, 0);char readbuf[175000]={0};struct sockaddr_in addrSrv;addrSrv.sin_addr.s_addr=inet_addr("127.0.0.1");addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(8888);struct linger so_linger;so_linger.l_onoff=1;so_linger.l_linger=0;setsockopt(sockClient,SOL_SOCKET,SO_LINGER,&so_linger,sizeof(so_linger));ret=connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));write(sockClient,readbuf,sizeof(readbuf)+1);getchar();close(sockClient);return 0; }

?

編譯并運行,用netstat查看。

?

[mapan@localhost ~]$ netstat -nao|grep 8888 tcp 0 0 0.0.0.0:8888 0.0.0.0:* LISTEN off (0.00/0/0) tcp 138900 0 127.0.0.1:8888 127.0.0.1:41332 ESTABLISHED off (0.00/0/0) tcp 0 36101 127.0.0.1:41332 127.0.0.1:8888 ESTABLISHED probe (1.23/0/0)

此時在客戶端還卡在getchar()出,在客戶端按下回車鍵,查看tcpdump抓包的結果。抓包結構如下:

?

?

[root@localhost mapan]# tcpdump -iany port 8888 -nlps0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes 19:06:53.835303 IP 127.0.0.1.41336 > 127.0.0.1.ddi-tcp-1: Flags [S], seq 2551942925, win 65495, options [mss 65495,sackOK,TS val 3407479544 ecr 0,nop,wscale 7], length 0 19:06:53.835318 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41336: Flags [S.], seq 3358092135, ack 2551942926, win 65483, options [mss 65495,sackOK,TS val 3407479544 ecr 3407479544,nop,wscale 7], length 0 19:06:53.835333 IP 127.0.0.1.41336 > 127.0.0.1.ddi-tcp-1: Flags [.], ack 1, win 512, options [nop,nop,TS val 3407479544 ecr 3407479544], length 0 19:06:53.835421 IP 127.0.0.1.41336 > 127.0.0.1.ddi-tcp-1: Flags [.], seq 1:32742, ack 1, win 512, options [nop,nop,TS val 3407479544 ecr 3407479544], length 32741 19:06:53.835431 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41336: Flags [.], ack 32742, win 829, options [nop,nop,TS val 3407479544 ecr 3407479544], length 0 19:06:53.835466 IP 127.0.0.1.41336 > 127.0.0.1.ddi-tcp-1: Flags [P.], seq 32742:65483, ack 1, win 512, options [nop,nop,TS val 3407479544 ecr 3407479544], length 32741 19:06:53.835558 IP 127.0.0.1.41336 > 127.0.0.1.ddi-tcp-1: Flags [.], seq 65483:98224, ack 1, win 512, options [nop,nop,TS val 3407479544 ecr 3407479544], length 32741 19:06:53.835571 IP 127.0.0.1.41336 > 127.0.0.1.ddi-tcp-1: Flags [P.], seq 98224:130965, ack 1, win 512, options [nop,nop,TS val 3407479544 ecr 3407479544], length 32741 19:06:53.874708 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41336: Flags [.], ack 130965, win 62, options [nop,nop,TS val 3407479584 ecr 3407479544], length 0 19:06:54.079730 IP 127.0.0.1.41336 > 127.0.0.1.ddi-tcp-1: Flags [P.], seq 130965:138901, ack 1, win 512, options [nop,nop,TS val 3407479789 ecr 3407479584], length 7936 19:06:54.079741 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41336: Flags [.], ack 138901, win 0, options [nop,nop,TS val 3407479789 ecr 3407479789], length 0 19:06:54.241704 IP 127.0.0.1.41336 > 127.0.0.1.ddi-tcp-1: Flags [R.], seq 138901, ack 1, win 512, options [nop,nop,TS val 3407479951 ecr 3407479789], length 0

?

客戶端發RST了。

3)當l_onoff為非零,l_linger也為非零。此時調用close函數時,內核將會延遲l_linger秒直到所有數據都發送對端且收到應答消息或者l_linger秒被消耗完。如果l_linger被消耗完,發送緩沖區中還有數據,則剩余的數據被丟棄,并向對端發送RST。如果套接字處于非阻塞狀態,發送緩沖區的數據立即丟棄,close返回,所以要判斷一下close函數的返回值。還是服務端代碼不變,客戶端代碼稍作修改,客戶端代碼如下:

?

#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <malloc.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <stdarg.h> #include <fcntl.h> #include <error.h>int main() {int ret=0;int sockClient = socket(AF_INET, SOCK_STREAM, 0);char readbuf[175000]={0};struct sockaddr_in addrSrv;addrSrv.sin_addr.s_addr=inet_addr("127.0.0.1");addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(8888);struct linger so_linger;so_linger.l_onoff=1;so_linger.l_linger=60;setsockopt(sockClient,SOL_SOCKET,SO_LINGER,&so_linger,sizeof(so_linger));ret=connect(sockClient, ( const struct sockaddr *)&addrSrv, sizeof(struct sockaddr_in));write(sockClient,readbuf,sizeof(readbuf)+1);getchar();close(sockClient);return 0; }


編譯并運行,先運行服務端后運行客戶端。和上面一樣,此時客戶端發送緩沖區內有殘余數據。這時在客戶端按下回車鍵會發現進程并沒有結束,而是休眠了。然后在服務端連續按回車鍵,隨著客戶端進程就結束了,標明數據已全部發送到服務端且受到答復。我們看下tcpdump抓包結果:

?

?

[root@localhost mapan]# tcpdump -iany port 8888 -nlps0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes 19:27:14.937303 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [S], seq 1492693418, win 65495, options [mss 65495,sackOK,TS val 3408700646 ecr 0,nop,wscale 7], length 0 19:27:14.937319 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41348: Flags [S.], seq 1875150207, ack 1492693419, win 65483, options [mss 65495,sackOK,TS val 3408700646 ecr 3408700646,nop,wscale 7], length 0 19:27:14.937334 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [.], ack 1, win 512, options [nop,nop,TS val 3408700646 ecr 3408700646], length 0 19:27:14.937425 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [.], seq 1:32742, ack 1, win 512, options [nop,nop,TS val 3408700646 ecr 3408700646], length 32741 19:27:14.937434 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41348: Flags [.], ack 32742, win 829, options [nop,nop,TS val 3408700646 ecr 3408700646], length 0 19:27:14.937474 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [P.], seq 32742:65483, ack 1, win 512, options [nop,nop,TS val 3408700646 ecr 3408700646], length 32741 19:27:14.937573 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [.], seq 65483:98224, ack 1, win 512, options [nop,nop,TS val 3408700646 ecr 3408700646], length 32741 19:27:14.937586 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [P.], seq 98224:130965, ack 1, win 512, options [nop,nop,TS val 3408700646 ecr 3408700646], length 32741 19:27:14.976713 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41348: Flags [.], ack 130965, win 62, options [nop,nop,TS val 3408700686 ecr 3408700646], length 0 19:27:15.181743 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [P.], seq 130965:138901, ack 1, win 512, options [nop,nop,TS val 3408700891 ecr 3408700686], length 7936 19:27:15.181754 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41348: Flags [.], ack 138901, win 0, options [nop,nop,TS val 3408700891 ecr 3408700891], length 0 19:27:15.386744 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [.], ack 1, win 512, options [nop,nop,TS val 3408701096 ecr 3408700891], length 0 19:27:15.386754 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41348: Flags [.], ack 138901, win 0, options [nop,nop,TS val 3408701096 ecr 3408700891], length 0 19:27:15.796774 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [.], ack 1, win 512, options [nop,nop,TS val 3408701506 ecr 3408701096], length 0 19:27:16.616810 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [.], ack 1, win 512, options [nop,nop,TS val 3408702326 ecr 3408701096], length 0 19:27:16.616820 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41348: Flags [.], ack 138901, win 0, options [nop,nop,TS val 3408702326 ecr 3408700891], length 0 19:27:16.807990 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41348: Flags [.], ack 138901, win 780, options [nop,nop,TS val 3408702517 ecr 3408700891], length 0 19:27:16.808017 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [P.], seq 138901:163706, ack 1, win 512, options [nop,nop,TS val 3408702517 ecr 3408702517], length 24805 19:27:16.808021 IP 127.0.0.1.41348 > 127.0.0.1.ddi-tcp-1: Flags [FP.], seq 163706:175002, ack 1, win 512, options [nop,nop,TS val 3408702517 ecr 3408702517], length 11296 19:27:16.808033 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41348: Flags [.], ack 163706, win 631, options [nop,nop,TS val 3408702517 ecr 3408702517], length 0 19:27:16.847713 IP 127.0.0.1.ddi-tcp-1 > 127.0.0.1.41348: Flags [.], ack 175003, win 562, options [nop,nop,TS val 3408702557 ecr 3408702517], length 0

最后4行是客戶端發送數據到服務端,服務端給出ACK回應。

?

?

通過上面的學習,我們知道SO_LINGER能保證數據能發送到對端。

?

?

?

?

?

?

?

?


?

?

?

?


?

?

?

?

?

總結

以上是生活随笔為你收集整理的套接字选项SO_LINGER的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。