質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

Q&A

解決済

1回答

2675閲覧

UDPで送受信可能なUDPペイロードのサイズを求めるプログラムについて

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

UDP

UDP(User Datagram Protocol)とは、トランスポート層のプロトコルであり、コネクション型のデータサービスです。IPネットワーク上の別のホストにコンピュータのアプリケーションがメッセージを送ることができ、転送チャンネルやデータ経路を設定する必要はありません。TCPに比べて高速であるが、信頼性が薄いという特徴があります。

0グッド

0クリップ

投稿2021/12/01 07:44

編集2021/12/02 06:31

以下のサンプルプログラムを改良して各自の環境で1つのUDPデータグラムで送受信可能なUDPペイロードのサイズが何バイトであるか求める課題があるのですがどのようにすればいいでしょうか。

追記:肝心なことを書いていませんでした。
すみません。
EchoStringLenに着目していたのですが具体的にどのようなことをすればUDPペイロードのサイズを計れるかが調べはしたのですがどうしても分かりませんでした。

1人の回答者様の回答を参考に
UDPEchoClient.cを変えてみました。
ありがとうございました。

c

1//UDPEchoClientを改造 2//... 3memset(&servAddr, 0, sizeof(servAddr)); 4 servAddr.sin_family = AF_INET; 5 servAddr.sin_addr.s_addr = inet_addr(servIP); 6 servAddr.sin_port = htons(servPort); 7//ここから 8 for(echoStringLen = 1; echoStringLen < 65536; echoStringLen++){ 9 sendMsgLen = sendto(sock, echoString, echoStringLen, 0, (struct sockaddr*)&servAddr, sizeof(servAddr)); 10 if(sendMsgLen == -1){ 11 printf("%d\n",echoStringLen); 12 break; 13 } 14 } 15//ここまで 16//...

実行してみたところ4399という数字がクライアント側に表示されましたが、大きな間違いはないでしょうか。
以下サンプルプログラム

c

1//UDPEchoServer.c 2#include <stdio.h> 3#include <string.h> 4#include <arpa/inet.h> 5#include <stdlib.h> 6#include <unistd.h> 7 8#define ECHOMAX (65535) 9 10int main(int argc, char *argv[]) 11{ 12 unsigned short servPort; 13 14 int sock; 15 struct sockaddr_in servAddr; 16 17 struct sockaddr_in clntAddr; 18 unsigned int clntAddrLen; 19 char msgBuffer[ECHOMAX]; 20 int recvMsgLen; 21 int sendMsgLen; 22 23 if (argc != 2){ 24 fprintf(stderr, "Usage: %s <Echo Port>\n", argv[0]); 25 return -1; 26 } 27 servPort = atoi(argv[1]); 28 29 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 30 if (sock < 0){ 31 fprintf(stderr, "socket() failed\n"); 32 return -1; 33 } 34 35 memset(&servAddr, 0, sizeof(servAddr)); 36 servAddr.sin_family = AF_INET; 37 servAddr.sin_addr.s_addr = htonl(INADDR_ANY); 38 servAddr.sin_port = htons(servPort); 39 40 if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0){ 41 fprintf(stderr, "bind() failed\n"); 42 return -1; 43 } 44 45 for (;;){ 46 clntAddrLen = sizeof(clntAddr); 47 48 recvMsgLen = recvfrom(sock, msgBuffer, ECHOMAX, 0, (struct sockaddr*)&clntAddr, &clntAddrLen); 49 50 if(recvMsgLen < 0){ 51 fprintf(stderr, "recvfrom() failed\n"); 52 return -1; 53 } 54 55 printf("Handling client %s\n", inet_ntoa(clntAddr. sin_addr)); 56 57 sendMsgLen = sendto(sock, msgBuffer, recvMsgLen, 0, (struct sockaddr*)&clntAddr, sizeof(clntAddr)); 58 59 if (recvMsgLen != sendMsgLen){ 60 fprintf(stderr, "sendto() sent a different number of bytes than expected\n"); 61 return -1; 62 } 63 } 64} 65

c

1//UDPEchoClient.c 2#include <stdio.h> 3#include <string.h> 4#include <arpa/inet.h> 5#include <stdlib.h> 6#include <unistd.h> 7 8#define ECHOMAX (65535) 9 10int main(int argc, char *argv[]) 11{ 12 char *servIP; 13 char *echoString; 14 int echoStringLen; 15 unsigned short servPort; 16 17 int sock; 18 struct sockaddr_in servAddr; 19 20 int sendMsgLen; 21 struct sockaddr_in fromAddr; 22 unsigned int fromAddrLen; 23 char msgBuffer[ECHOMAX+1]; 24 int recvMsgLen; 25 26 if (argc != 4){ 27 fprintf(stderr, "Usage: %s <Server IP> <Echo Port> <Echo Word>\n", argv[0]); 28 return -1; 29 } 30 servIP = argv[1]; 31 servPort = atoi(argv[2]); 32 echoString = argv[3]; 33 echoStringLen = strlen(echoString); 34 35 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 36 if(sock < 0){ 37 fprintf(stderr, "socket() failed\n"); 38 return -1; 39 } 40 41 memset(&servAddr, 0, sizeof(servAddr)); 42 servAddr.sin_family = AF_INET; 43 servAddr.sin_addr.s_addr = inet_addr(servIP); 44 servAddr.sin_port = htons(servPort); 45 46 sendMsgLen = sendto(sock, echoString, echoStringLen, 0, (struct sockaddr*)&servAddr, sizeof(servAddr)); 47 48 if (echoStringLen != sendMsgLen){ 49 fprintf(stderr, "sendto() sent a different number of bytes of than expected\n"); 50 return -1; 51 } 52 53 fromAddrLen = sizeof(fromAddr); 54 55 recvMsgLen = recvfrom(sock, msgBuffer, ECHOMAX, 0, (struct sockaddr*)&fromAddr, &fromAddrLen); 56 if (recvMsgLen != echoStringLen){ 57 fprintf(stderr, "recvfrom() failed\n"); 58 return -1; 59 } 60 61 if (fromAddr.sin_addr.s_addr != servAddr.sin_addr.s_addr){ 62 fprintf(stderr, "Error: received a packet from unknown source\n"); 63 return -1; 64 } 65 66 msgBuffer[recvMsgLen] = '\0'; 67 68 printf("Received: %s\n", msgBuffer); 69 70 close(sock); 71 72 return 0; 73} 74

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2021/12/01 07:56

teratail は作業依頼の場では無いと思います。
guest

回答1

0

ベストアンサー

下記URLにペイロードについて記述されてます。
https://blog.foresta.me/posts/learn_about_udp/

それによれば65507が最大のペーロード長とのことなので、
送信データを1バイトから開始し、最大65535バイトまで、送信を繰り返すように、
クライアント側を改造すれば良いかと。
(パケット長は16ビットなので最大65535となる。)
送信エラーが発生する直前が正常に送信できた最大のサイズとなる。
for (データ長=1;データ長<65536;データ長++){
sendMsgLen = sendto(省略,データ長,省略);
if (sendMsgLen== -1){
// データ長-1 が正常に送信データサイズなのでそれを表示
break;
}
}
close(sock);

クライアント側の改造の注意点
1.送信データを起動パラメータで受け取らないこと。
もしくは、起動パラメータでしてされたデータを使用しないこと。
2.送信バッファを65535バイト以上確保すること。
3.応答メッセージを表示しないこと。(画面が見苦しくなる為)

サーバー側の改造の注意点
1.受信バッファを65535バイト以上確保すること。

投稿2021/12/01 13:02

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問