UDPデータグラムの最大長
理論的には、IPデータグラムの最大長は65535バイトです。これは、IPヘッダーの16ビットの全長フィールドによって制限されます(図IPプロトコル形式)。20バイトのIPヘッダー(図IPプロトコル形式)と8バイトのUDP(図UDPプロトコル形式)ヘッダーを削除します。UDPデータグラムでのユーザーの最大長は65507です。ただし、ほとんどの実装ではこれより長い長さが提供されています最大値が小さいです。
2つの制限要因が発生します。
まず、アプリケーションはそのプログラムインターフェイスによって制限される可能性があります。ソケットAPIは、アプリケーションが呼び出して受信および送信バッファーの長さを設定できる関数を提供します。UDPソケットの場合、この長さは、アプリケーションが読み書きできる最大のUDPデータグラムの長さに直接関連しています。現在、ほとんどのシステムは、デフォルトで8192を超える読み取りと書き込みが可能な独自のUDPデータグラムを提供しています。
2番目の制限は、TCP / IPのカーネル実装によるものです。IPデータグラムの長さが65535バイト未満になるいくつかの実装特性(またはエラー)がある場合があります。
UDPの最大データグラム長コードをテストする
server.c
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys / socket.h >
#include <netinet / in.h>
#include <sys / types.h>
#include <arpa / inet.h>#define SERVER_PORT 8888
#define MAX_MSG_SIZE 1024void udps_respon(int sockfd)
{
struct sockaddr_in addr;
int addrlen、n;
char msg [MAX_MSG_SIZE];
while(1){
/ *ネットワークから読み取り、ネットワークに書き込む* /
bzero(msg、sizeof(msg)) ; //初期化、設定0
addrlen = sizeof(struct sockaddr);
n = recvfrom(sockfd、msg、MAX_MSG_SIZE、0、(struct sockaddr *)&addr、&addrlen); //クライアントからデータを受信
msg [n] = ' \ 0 ';
/ *サーバーがメッセージを受信したことを表示* /
fprintf(stdout、 "Server have received%s"、msg); //メッセージを表示
}
}int main(int argc、char * argv [])
{
int sockfd;
struct sockaddr_in addr;
/ *建立sockfd描述符* /
sockfd = socket(AF_INET、SOCK_DGRAM、0);
if(sockfd <0){
fprintf(stderr、 "ソケットエラー:%s \ n"、strerror(errno));
exit(1);
}/ *サーバー側でsockaddr構造を入力します* /
bzero(&addr、sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SERVER_PORT);
/ *バンドルsockfd記述子* /
if(bind(sockfd、(struct sockaddr *)&addr、sizeof(struct sockaddr_in))<0){
fprintf(stderr、 "Bind Error:%s \ n"、strerror(errno));
exit(1 );
}
printf( "udp server start ...... \ n");
udps_respon(sockfd); //読み取りおよび書き込み操作を
閉じる(sockfd);
}
client.c
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys / socket.h >
#include <netinet / in.h>
#include <sys / types.h>
#include <arpa / inet.h>#define SERVER_PORT 8888
#define MAX_BUF_SIZE 65508void udpc_requ(int sockfd、const struct sockaddr_in * addr、int len)
{
char buffer [MAX_BUF_SIZE + 1];
int n;
int i = 0;
// while(1){
/ * From键盘读
入力、写到服务器* / printf( "文字を入力してください:\ n");
memset(バッファ、0、sizeof(バッファ));
// fgets(buffer、MAX_BUF_SIZE、stdin);
for(i = 0; i <MAX_BUF_SIZE; i ++)
{
buffer [i] = 'a';
}
n = sendto(sockfd、buffer、strlen(buffer)、0、(struct sockaddr *)addr、len);
// bzero(buffer、MAX_BUF_SIZE);
printf( "バイトを送信:%d \ n"、n);
//}
}int main(int argc、char * argv [])
{
int sockfd;
struct sockaddr_in addr;
if(argc!= 2){
fprintf(stderr、 "用途:%s server_ip \ n"、argv [0]);
exit(1);
}
/ *建立sockfd描述符* /
sockfd = socket(AF_INET、SOCK_DGRAM、0);
if(sockfd <0){
fprintf(stderr、 "ソケットエラー:%s \ n"、strerror(errno));
exit(1);
}/ *サーバーデータを入力します* /
bzero(&addr、sizeof(struct sockaddr_in)); //初期化、0を
追加addr.sin_family = AF_INET;
addr.sin_port = htons(SERVER_PORT);
if(inet_aton(argv [1]、&addr .sin_addr)<0){/ * inet_aton関数は、文字列型IPアドレスをネットワーク型IPアドレスに変換するために使用されます* /
fprintf(stderr、 "Ip Error:%s \ n"、strerror(errno));
exit( 1);
}
udpc_requ(sockfd、&addr、sizeof(struct sockaddr_in)); //読み取りおよび書き込み操作を
閉じる(sockfd);
}
人間值
ボリュームI、グローバルインターネット実験の詳細な説明については、TCP / IPを参照してください。
実験として、変更したtracerouteプログラムを何度も実行します。宛先は、複数の大西洋および太平洋横断リンクを使用して、15か国(南極を含む)に到達できる世界中のホストです。ただし、その前に、作成者のサブネットとルーターnetbの間のダイヤルアップSLIPリンクMTUは、イーサネットと同じ1500に増加しました。
18回の実行のうち、パスMTUが1500未満であるのは2回だけでした。大西洋横断リンクの1つに572のMTU値があり、ルーターが新しい形式のICMPエラーメッセージを返します。日本の2つのルーター間のもう1つのリンクは1500バイトのデータフレームを処理できず、ルーターは新しい形式のICMPエラーメッセージを返しません。MTU値を1006に設定すると、正常に動作します。
この実験から、すべてではないが多くのWANが512を超えるパケットを処理できるようになったという結論を読み取ることができます。パスMTU検出メカニズムを使用すると、アプリケーションはより大きなMTUを最大限に活用してパケットを送信できます。
MTU値の場合、ホストは少なくとも576バイトのIPデータグラムを受信できる必要があります。多くのUDPアプリケーション設計では、アプリケーションデータは512バイト以下に制限されているため、この制限値よりも小さくなります。もちろん、多くのルーティングプロトコル(DNS TFTP BOOTP SNMP)を分析することで、常に512バイト未満のデータを送信できます。