ソケットオプション機能 機能: ソケットファイル記述子の属性の読み取りと設定に使用されるメソッド #include <sys/scoket.h> int getsockopt ( int sockfd、 int level、 int option_name、 void* option_value、 socklen_t* restrict option_len ); int setsockopt ( int sockfd、 int レベル、 int option_name、 const void* option_value、 socklen_t option_len); ソケットオプションテーブルは次のとおりです。 getsockopt および setsockopt 関数は、成功した場合は 0 を返し、失敗した場合は -1 を返して errno を設定します。 サーバーの場合、一部のソケット オプションは、listen システム コールを呼び出す前にリスニング ソケットに設定されている場合にのみ有効です。これは、接続ソケットは accept 呼び出しによってのみ返され、listen キューから accept によって受け入れられた接続は、少なくとも TCP 3 ウェイ ハンドシェイクの最初の 2 つの手順を完了しているためです (listen キュー内の接続は少なくとも SYN_RCVD 状態になっているため)。つまり、サーバーは受信した接続に TCP 同期セグメントを送信したことになります。ただし、TCP 最大セグメント オプションなど、一部のソケット オプションは TCP 同期セグメントで設定する必要があります。このような状況に対して、Linux が開発者に提供する解決策は、リスニング ソケットにこれらのソケット オプションを設定することです。そうすると、accept によって返される接続ソケットはこれらのオプションを自動的に継承します。これらのオプションは、SO_DEBUG、SO_DONTROUTE、SO_KEEPALIVE、SO_LINGER、SO_OOBINLINE、SO_RCVBUF、SO_RCVLOWAT、SO_SNDBUF、SO_SNDLOWAT、TCP_MAXSEG、および TCP_NODELAY です。 クライアントの場合、接続呼び出しが正常に返された後に TCP 3 ウェイ ハンドシェイクが完了するため、接続関数を呼び出す前にこれらのソケット オプションを設定する必要があります。 SO_REUSEADDR オプション 以前、TCP 接続の TIME_WAIT 状態について説明し、サーバー プログラムはソケット オプション SO_REUSEADDR を設定することで、TIME_WAIT 状態の接続で占有されているソケット アドレスの使用を強制できることを説明しました。 #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <文字列.h> int main( int argc, char* argv[] ) { if(argc <= 2) { printf( "使用法: %s ip_address port_number\n", basename( argv[0] ) ); 1 を返します。 } 定数 char* ip = argv[1]; int ポート = atoi( argv[2] ); int sock = socket( PF_INET, SOCK_STREAM, 0 ); アサート( sock >= 0 ); 再利用 = 1; setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( 再利用 ) ); 構造体 sockaddr_in アドレス; bzero( &address, sizeof( address ) ); アドレス.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); アドレス.sin_port = htons( ポート ); int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); アサート( ret != -1 ); ret = listen( ソック、 5 ); アサート( ret != -1 ); 構造体 sockaddr_in クライアント; socklen_t client_addrlength = sizeof( クライアント ); int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); (接続数 < 0 ) の場合 { printf( "errnoは: %d\n", errno ); } それ以外 { char リモート[INET_ADDRSTRLEN]; printf( "IP: %s、ポート: %d で接続しました\n", inet_ntop( AF_INET, &client.sin_addr, リモート, INET_ADDRSTRLEN ), ntohs( client.sin_port ) ); 閉じる( connfd ); } close( 靴下 ); 0を返します。 } setsocketopt が設定されると、たとえ sock が TIME_WAIT 状態であっても、それにバインドされたソケット アドレスはすぐに再利用できるようになります。さらに、カーネル パラメータ /proc/sys/net/ipv4/tcp_tw_recycle を変更して TCP 接続が TIME_WAIT 状態にまったく入らず、アプリケーションがローカル ソケット アドレスをすぐに再利用できるようにすることで、閉じたソケットをすばやくリサイクルすることもできます。 SO_RCVBUF および SO_SNDBUF オプション SO_RCVBUF および SO_SNDBUF オプションは、それぞれ TCP 受信バッファと送信バッファのサイズを表します。ただし、setsockopt を使用して TCP の受信バッファと送信バッファのサイズを設定すると、システムはその値を 2 倍にし、最小値よりも小さくすることはできません。 TCP 受信バッファの最小値は 256 バイト、送信バッファの最小値は 2048 バイトです (ただし、システムによってデフォルトの最小値が異なる場合があります)。さらに、カーネル パラメータ /proc/sys/net/ipv4/tcp_rmem と /proc/sys/net/ipv4/tcp_wmem を直接変更して、TCP 受信バッファと送信バッファに最小サイズ制限がないように強制することもできます。 TCP 送信バッファのクライアント プログラムを変更します。 #include <sys/socket.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <文字列.h> #include <stdlib.h> #BUFFER_SIZE 512 を定義します int main( int argc, char* argv[] ) { if(argc <= 3) { printf( "使用法: %s ip_address port_number send_bufer_size\n", basename( argv[0] ) ); 1 を返します。 } 定数 char* ip = argv[1]; int ポート = atoi( argv[2] ); 構造体 sockaddr_in サーバーアドレス; bzero( &server_address, sizeof( server_address ) ); server_address.sin_family = AF_INET; inet_pton( AF_INET, ip, &server_address.sin_addr ); server_address.sin_port = htons( ポート ); int sock = socket( PF_INET, SOCK_STREAM, 0 ); アサート( sock >= 0 ); int sendbuf = atoi( argv[3] ); int len = sizeof( sendbuf ); setsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf ) ); getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len ); printf( "設定後の TCP 送信バッファ サイズは %d\n です", sendbuf ); if ( connect( sock, ( struct sockaddr* )&server_address, sizeof( server_address ) ) != -1 ) { char バッファ[ BUFFER_SIZE ]; memset(バッファ, 'a', BUFFER_SIZE); 送信( ソック, バッファ, BUFFER_SIZE, 0 ); } close( 靴下 ); 0を返します。 } TCP 受信バッファのサーバー プログラムを変更します。 #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <文字列.h> #BUFFER_SIZE 1024 を定義します int main( int argc, char* argv[] ) { if(argc <= 3) { printf( "使用法: %s ip_address port_number receive_buffer_size\n", basename( argv[0] ) ); 1 を返します。 } 定数 char* ip = argv[1]; int ポート = atoi( argv[2] ); 構造体 sockaddr_in アドレス; bzero( &address, sizeof( address ) ); アドレス.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); アドレス.sin_port = htons( ポート ); int sock = socket( PF_INET, SOCK_STREAM, 0 ); アサート( sock >= 0 ); int recvbuf = atoi( argv[3] ); int len = sizeof( recvbuf ); setsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf ) ); getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len ); printf( "設定後の受信バッファサイズは%d\n", recvbuf ); int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) ); アサート( ret != -1 ); ret = listen( ソック、 5 ); アサート( ret != -1 ); 構造体 sockaddr_in クライアント; socklen_t client_addrlength = sizeof( クライアント ); int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); (接続数 < 0 ) の場合 { printf( "errnoは: %d\n", errno ); } それ以外 { char バッファ[ BUFFER_SIZE ]; memset(バッファ, '\0', BUFFER_SIZE); while( recv( connfd, バッファ, BUFFER_SIZE-1, 0 ) > 0 ){} 閉じる( connfd ); } close( 靴下 ); 0を返します。 } 実行結果:
上記で説明したように、setsockopt を使用して TCP の受信バッファと送信バッファのサイズを設定すると、システムはその値を 2 倍にし、その値は最小値よりも小さくなってはなりません。 SO_RCVLOWAT および SO_SNDLOWAT オプション
SO_LINGER オプション SO_LINGER オプションは、TCP 接続を閉じるときに close システム コールの動作を制御するために使用されます。デフォルトでは、close システム コールを使用してソケットを閉じると、close はすぐに戻り、TCP モジュールはソケットに対応する TCP 送信バッファ内の残りのデータを相手に送信する役割を担います。 SO_LINGER オプションの値を設定するときは、次のように定義される linger 型構造体を setsockopt (getsockopt) システム コールに渡す必要があります。 #include <sys/socket.h> 構造体リンガー { int l_onoff; //このオプションをオン(0以外)またはオフ(0)にします int l_linger; //リンガー時間};
以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
<<: Vueは動的コンポーネントを使用してTAB切り替え効果を実現します
>>: Centos7 のインストールと Mysql5.7 の設定
Windows 10 で MySql データベースの解凍バージョンをインストールするステップ 1: ...
Linux でダイナミック ライブラリをロードできません次のような異常事態が発生した場合./test...
最近、JS の正規表現マッチングの落とし穴を発見したのですが、その時はあまりにも奇妙だったので、何か...
目次1. マップされた型2. マッピング修飾子3. キーの再マッピング4. さらなる探究序文: Ty...
目次1. CentOS7.0へのJDK1.8のインストール2. Dockerのインストール3.Doc...
MySQL ドキュメントでは、MySQL 変数はシステム変数とユーザー変数の 2 つのカテゴリに分類...
最近、React Hooks を zarm コンポーネント ライブラリと組み合わせて使用し、js...
この記事では、WeChatアプレットの9マスグリッド効果を実現するための具体的なコードを参考までに紹...
1. ul タグには、Mozilla ではデフォルトでパディング値がありますが、IE ではマージン値...
Linux インストール JDK1.8 手順1. CentOS に独自の openJDK があるかど...
1 選択タグは閉じられている必要があります <select></select>...
背景グラデーションと自動フルスクリーンに関する CSS の問題編集長は CSS の開発中に致命的な問...
CentOS7 のデフォルトのデータベースは mariadb ですが、mysql を使っている人も多...
背景MySQL のデッドロックについて言えば、私は以前 MySQL のロックに関する基本的な紹介記事...
<br />原文: http://andymao.com/andy/post/104.h...