1 TCP_CORKオプションとは?
ソケットの送信バッファにMSS(Maximum Segment Size)まで送信データを貯めてから、データを送信する機能です。MSSとは、MTU(Maximum Transmission Unit)からTCP/IPヘッダサイズを引いた値になります。MTUは、イーサネット環境では1500(byte)です。また、TCP/IPヘッダサイズは各々20(byte)です。さらにTCPには、TCPタイムスタンプオプション(12byte)が付くのが一般的です。したがって、イーサネット環境では一般的にMSSは1448(byte)になります。本環境でもMSSは1448(byte)です。
その他ソケットオプションについても記事を書きました。
ソケットオプションの使い方(SO_REUSEPORT) - hana_shinのLinux技術ブログ
ソケットオプションの使い方(TCP_NODELAY編) - hana_shinのLinux技術ブログ
ソケットオプションの使い方(TCP_CORK編) - hana_shinのLinux技術ブログ
ソケットオプションの使い方(SO_REUSEADDR編) - hana_shinのLinux技術ブログ
ソケットオプションの使い方(SO_SNDBUF編) - hana_shinのLinux技術ブログ
ソケットオプションの使い方(SO_SNDTIMEO編) - hana_shinのLinux技術ブログ
ソケットオプションの使い方(SO_RCVTIMEO編) - hana_shinのLinux技術ブログ
ソケットオプションの使い方(SO_KEEPALIVE編) - hana_shinのLinux技術ブログ
ソケットオプションの使い方(TCP_NODELAY編) - hana_shinのLinux技術ブログ
ソケットオプションの使い方(SO_LINGER編) - hana_shinのLinux技術ブログ
2 検証環境
2.1 ネットワーク構成
サーバとクライアントの2台構成です。図中のeth0はNICの名前です。
192.168.2.0/24 client(eth0) -------------------------------------------- (eth0) server .105 .100
2.2 版数
サーバ、クライアントともに下記版数です。
[root@server ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)
2.3 MTUの確認
ipコマンドを実行すると、eth0のMTUは1500(byte)であることがわかります。
[root@server ~]# ip l show dev eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether 52:54:00:78:10:73 brd ff:ff:ff:ff:ff:ff
3 テストプログラム(TP)作成
3.1 テストプログラム
サーバで動作するTPを作成します。なお、エラー処理は見やすくするため意図的に省略しています。また、ソケットオプションの動作確認を目的としているため、実用的なプログラムにはなっていません。
[root@server ~]# cat sv.c #include <stdio.h> #include <unistd.h> #include <string.h> #include <netinet/in.h> int main(int argc, char *argv[]) { int lfd, cfd; socklen_t len; struct sockaddr_in sv, cl; char buf[32]; ssize_t n; lfd = socket(AF_INET, SOCK_STREAM, 0); sv.sin_family = AF_INET; sv.sin_port = htons(11111); sv.sin_addr.s_addr = INADDR_ANY; bind(lfd, (struct sockaddr *)&sv, sizeof(sv)); listen(lfd, 5); memset(buf, 0, sizeof(buf)); len = sizeof(cl); cfd = accept(lfd, (struct sockaddr *)&cl, &len); while (1) { n = read(cfd, buf, sizeof(buf)); if(n > 0) fprintf(stderr,"%zd, %s\n", n, buf); else if(n == 0) { //EOF close(cfd); return 0; } else { perror("read"); return 1; } } close(lfd); return 0; }
クライアントで動作するTPを作成します。なお、エラー処理は見やすくするため意図的に省略しています。
[root@client ~]# cat cl.c #include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <arpa/inet.h> #include <netinet/tcp.h> int main(int argc, char *argv[]) { struct sockaddr_in server; int sock, i, val; ssize_t n; char buf[10]="0123456789"; sock = socket(AF_INET, SOCK_STREAM, 0); server.sin_family = AF_INET; server.sin_port = htons(11111); server.sin_addr.s_addr = inet_addr("192.168.2.100"); val = atoi(argv[1]); setsockopt(sock, IPPROTO_TCP, TCP_CORK, &val, sizeof(val)); connect(sock, (struct sockaddr *)&server, sizeof(server)); for(i=0; i<1000; i++) { n = write(sock, buf, sizeof(buf)); if(n == -1) { perror("write"); return 1; } } close(sock); return 0; }
4 事前準備
サーバでポート番号を開放します。なお、firewall-cmdコマンドの使い方は、firewall-cmdの使い方 - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# firewall-cmd --add-port=11111/tcp
開放したポート番号を確認します。11111番ポートが開放されたことがわかります。
[root@server ~]# firewall-cmd --list-ports 11111/tcp
5 動作確認
5.1 TCP_CORKオプションが有効の場合
TCP_CORKが有効だと、ソケットの送信バッファにMSSまでのデータを貯めてから送信します。tcpdumpを使って、そのことを確認してみます。
サーバでTPを実行します。
[root@server ~]# ./sv
lsofコマンドを実行します。svプロセスが11111番ポートでListenしていることがわかります。なお、lsofコマンドの使い方は、lsofコマンドの使い方 - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# lsof -c sv -a -i4 -a -P COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sv 2453 root 3u IPv4 35002 0t0 TCP *:11111 (LISTEN)
サーバでtcpdumpコマンドを実行します。なお、tcpdumpコマンドの使い方は、tcpdumpの使い方(基本編) - hana_shinのLinux技術ブログを参照してください。
[root@server ~]# tcpdump -i eth0 port 11111 -nn
クライアントでTPを実行します。TPの引数には、TCP_CORK有効(=1)を指定します。
[root@client ~]# ./cl 1
tcpdumpコマンドの実行結果を確認します。lenの部分に★が付いた6つのパケットのlenは全て1448(byte)になっています。また、●が付いた1つのパケットはlenが1312(byte)になっています。lenの合計を計算すると、1448×6 + 1312 =10000となります。TPの送信バイト数と一致していることがわかります。
[root@server ~]# tcpdump -i eth0 port 11111 -nn -snip- 10:44:09.311769 IP 192.168.2.105.53204 > 192.168.2.100.11111: Flags [S], seq 1386691091, win 29200, options [mss 1460,sackOK,TS val 1306121 ecr 0,nop,wscale 7], length 0 10:44:09.311844 IP 192.168.2.100.11111 > 192.168.2.105.53204: Flags [S.], seq 975134360, ack 1386691092, win 28960, options [mss 1460,sackOK,TS val 1146026 ecr 1306121,nop,wscale 7], length 0 10:44:09.312674 IP 192.168.2.105.53204 > 192.168.2.100.11111: Flags [.], ack 1, win 229, options [nop,nop,TS val 1306124 ecr 1146026], length 0 10:44:09.313059 IP 192.168.2.105.53204 > 192.168.2.100.11111: Flags [.], seq 1:1449, ack 1, win 229, options [nop,nop,TS val 1306124 ecr 1146026], length 1448 ★ 10:44:09.313124 IP 192.168.2.100.11111 > 192.168.2.105.53204: Flags [.], ack 1449, win 249, options [nop,nop,TS val 1146027 ecr 1306124], length 0 10:44:09.313495 IP 192.168.2.105.53204 > 192.168.2.100.11111: Flags [.], seq 1449:2897, ack 1, win 229, options [nop,nop,TS val 1306124 ecr 1146026], length 1448 ★ 10:44:09.313814 IP 192.168.2.100.11111 > 192.168.2.105.53204: Flags [.], ack 2897, win 272, options [nop,nop,TS val 1146027 ecr 1306124], length 0 10:44:09.314021 IP 192.168.2.105.53204 > 192.168.2.100.11111: Flags [.], seq 2897:4345, ack 1, win 229, options [nop,nop,TS val 1306125 ecr 1146027], length 1448 ★ 10:44:09.314046 IP 192.168.2.100.11111 > 192.168.2.105.53204: Flags [.], ack 4345, win 295, options [nop,nop,TS val 1146028 ecr 1306125], length 0 10:44:09.314240 IP 192.168.2.105.53204 > 192.168.2.100.11111: Flags [.], seq 4345:5793, ack 1, win 229, options [nop,nop,TS val 1306126 ecr 1146027], length 1448 ★ 10:44:09.314284 IP 192.168.2.100.11111 > 192.168.2.105.53204: Flags [.], ack 5793, win 317, options [nop,nop,TS val 1146028 ecr 1306126], length 0 10:44:09.314545 IP 192.168.2.105.53204 > 192.168.2.100.11111: Flags [P.], seq 5793:7241, ack 1, win 229, options [nop,nop,TS val 1306126 ecr 1146028], length 1448 ★ 10:44:09.314583 IP 192.168.2.100.11111 > 192.168.2.105.53204: Flags [.], ack 7241, win 340, options [nop,nop,TS val 1146028 ecr 1306126], length 0 10:44:09.315009 IP 192.168.2.105.53204 > 192.168.2.100.11111: Flags [.], seq 7241:8689, ack 1, win 229, options [nop,nop,TS val 1306126 ecr 1146028], length 1448 ★ 10:44:09.315195 IP 192.168.2.100.11111 > 192.168.2.105.53204: Flags [.], ack 8689, win 362, options [nop,nop,TS val 1146029 ecr 1306126], length 0 10:44:09.315569 IP 192.168.2.105.53204 > 192.168.2.100.11111: Flags [FP.], seq 8689:10001, ack 1, win 229, options [nop,nop,TS val 1306127 ecr 1146028], length 1312 ● 10:44:09.319247 IP 192.168.2.100.11111 > 192.168.2.105.53204: Flags [F.], seq 1, ack 10002, win 385, options [nop,nop,TS val 1146033 ecr 1306127], length 0 10:44:09.320480 IP 192.168.2.105.53204 > 192.168.2.100.11111: Flags [.], ack 2, win 229, options [nop,nop,TS val 1306131 ecr 1146033], length 0
5.2 TCP_CORKオプションが無効の場合
サーバでTPを実行します。
[root@server ~]# ./sv
サーバでtcpdumpコマンドを実行します。
[root@server ~]# tcpdump -i eth0 port 11111 -nn
クライアントでTPを実行します。TPの引数には、TCP_CORK無効(=0)を指定します。
[root@client ~]#./cl 0
lenの部分を確認すると、1448(byte)のものもありますが、1448以外の長さのものが大部分であることがわかります。つまり、送信バッファにMSSサイズ分のデータが貯まる前に、データを送信していることがわかります。
[root@server ~]# tcpdump -i eth0 port 11111 -nn -snip- 10:50:24.844911 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [S], seq 1982540112, win 29200, options [mss 1460,sackOK,TS val 1681655 ecr 0,nop,wscale 7], length 0 10:50:24.844959 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [S.], seq 3204141593, ack 1982540113, win 28960, options [mss 1460,sackOK,TS val 1521559 ecr 1681655,nop,wscale 7], length 0 10:50:24.845601 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [.], ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521559], length 0 10:50:24.845682 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [P.], seq 1:11, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521559], length 10 10:50:24.845694 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 11, win 227, options [nop,nop,TS val 1521560 ecr 1681657], length 0 10:50:24.846079 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [.], seq 11:1459, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521559], length 1448 10:50:24.846113 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [P.], seq 1459:1461, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521560], length 2 10:50:24.846160 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 1459, win 249, options [nop,nop,TS val 1521560 ecr 1681657], length 0 10:50:24.846240 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 1461, win 249, options [nop,nop,TS val 1521560 ecr 1681657], length 0 10:50:24.846478 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [.], seq 1461:2909, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521560], length 1448 10:50:24.846495 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 2909, win 272, options [nop,nop,TS val 1521560 ecr 1681657], length 0 10:50:24.846553 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [P.], seq 2909:2951, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521560], length 42 10:50:24.846563 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 2951, win 272, options [nop,nop,TS val 1521560 ecr 1681657], length 0 10:50:24.846944 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [P.], seq 2951:3351, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521560], length 400 10:50:24.847789 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 3351, win 295, options [nop,nop,TS val 1521562 ecr 1681657], length 0 10:50:24.847845 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [.], seq 3351:6247, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521560], length 2896 10:50:24.847858 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 6247, win 340, options [nop,nop,TS val 1521562 ecr 1681657], length 0 10:50:24.847936 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [.], seq 6247:7695, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521560], length 1448 10:50:24.847950 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 7695, win 362, options [nop,nop,TS val 1521562 ecr 1681657], length 0 10:50:24.848017 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [P.], seq 7695:7701, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521562], length 6 10:50:24.848030 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 7701, win 362, options [nop,nop,TS val 1521562 ecr 1681657], length 0 10:50:24.848382 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [P.], seq 7701:8181, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521562], length 480 10:50:24.848427 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 8181, win 385, options [nop,nop,TS val 1521562 ecr 1681657], length 0 10:50:24.848523 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [.], seq 8181:9629, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521562], length 1448 10:50:24.848537 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 9629, win 408, options [nop,nop,TS val 1521562 ecr 1681657], length 0 10:50:24.848720 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [P.], seq 9629:9631, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521562], length 2 10:50:24.848733 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [.], ack 9631, win 408, options [nop,nop,TS val 1521563 ecr 1681657], length 0 10:50:24.848804 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [FP.], seq 9631:10001, ack 1, win 229, options [nop,nop,TS val 1681657 ecr 1521562], length 370 10:50:24.850268 IP 192.168.2.100.11111 > 192.168.2.105.53206: Flags [F.], seq 1, ack 10002, win 430, options [nop,nop,TS val 1521564 ecr 1681657], length 0 10:50:24.850991 IP 192.168.2.105.53206 > 192.168.2.100.11111: Flags [.], ack 2, win 229, options [nop,nop,TS val 1681657 ecr 1521564], length 0
Z 参考情報
私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ