ソケットオプション機能 機能: ソケットファイル記述子の属性の読み取りと設定に使用されるメソッド #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 の設定
パスワード入力後にMySQLデータベースがクラッシュする問題と解決策1 ケースの説明最近、基本的な機...
背景モバイル デバイスでは、ページ ジャンプ間のキャッシュが必須要件です。例: ホームページ =&g...
Vue でフォーム フィールドを記述および検証する方法は多数あります。このブログでは、より一般的に使...
前回の「最もシンプルなスイッチを実現するCSS」のように、HTML5とCSS3でほとんどの機能をすで...
問題の説明プロジェクトのログインページでは、7日間パスワードを記憶する必要がある機能があります。この...
効果: <div class="imgs"> <!-- 背景画...
今日は、スライドを使用する原理に似た、Taobao のフロントエンドのマウス ズーム効果に慣れました...
数日前、CSS で 3 列レイアウトを書いていたときに、突然この方法を思いつきました。このアイデアは...
1. まず、2つ以上の隣接する通常フローブロック要素の垂直マージンの崩壊を引き起こす原因を知る必要が...
目次確認する:例の検証と組み合わせるselect クエリ ステートメントはロックされませんが、sel...
目次序文配列.isArrayコンストラクタインスタンスプロトタイプオブジェクト.プロトタイプ.toS...
以下のように表示されます。 LOCATE(部分文字列、文字列)文字列 str 内の部分文字列 sub...
この記事では、プログレスバーヒストグラムを実現するためのvue+echartsの具体的なコードを参考...
目次導入実装手順キャンバス環境を作成するライティングボールBallクラスを継承するMoveBallク...
1. インストールパッケージを使用してMySQLをインストールします(オンラインダウンロードは遅すぎ...