🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Q&A

解決済

2回答

7627閲覧

C言語のrecv関数に渡すバッファのサイズの決め方

kitokun

総合スコア3

C

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

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

0グッド

1クリップ

投稿2021/01/14 09:49

現在、C言語の学習のため簡易的なWebサーバを自作しています。
ブラウザからのレスポンスをrecv関数で受け取るのですが、その際のバッファサイズはどのように決めるのがよいのでしょうか。
ソケットバッファのキューから受け取るサイズを取得できれば、そのサイズに合わせてバッファを動的に生成できると思うのですが……。
決め方について何かセオリーがあれば教えていただきたいです。

今は、以下に示すコードのようにとりあえず要素数2048の配列をバッファとして指定しています。

char inbuf[2048]; recv(sock, inbuf, sizeof(inbuf), 0);

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

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

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

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

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

otn

2021/01/14 09:59

送り手側がどういう単位で送信するかに依るとしか言いようが無いです。 不明なら、適当で良いんじゃ無いでしょうか。
guest

回答2

0

ベストアンサー

セオリーとしてはバッファを何バイトにしたところで、送信側が送ったデータを一度に受け取れる保証はないし、送信側としてもできることは send のみであって TCP 的に強制的に送信させることができないわけで、recv のレイヤと、それをアプリケーションプロトコルとして解釈するレイヤは別であるべき。

例えば Web サーバであれば改行コード \n\n が終端を表すとか、あるいは POST なら Content-Length 分読まないと、というわけですから、\n\n が出てくるか、あるいはあらかじめ決めた上限サイズを超えるか、あるいはタイムアウトするまでは recv を繰り返し、それらの終端が来た段階でまとめて HTTP リクエストとして解析すべき、ということです。

なので、学習であれば本題のバッファサイズは適当なサイズでよくて、それより大事なことがある、が回答ではないかと思います。

ただ、TCP の最大パケット長 MSS は 64K が上限、一般的なイーサネットなら 1460バイトなので、1500バイト~64K が効率的な気はしますが、気にするなら ab コマンドなどで計測してみるとよいでしょう。

特定サーバ間の高速伝送のように双方の環境がかちっと決まっているのであればさらに効率的なアプローチがあるのかもしれません (が、存じ上げません)。

投稿2021/01/14 10:15

68user

総合スコア2022

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

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

kitokun

2021/01/16 16:29

回答ありがとうございます。 そうなんですね。recvの仕様というか機能をちゃんと理解していませんでした。 recvで指定するバッファは一時的なもので、そこで受け取ったものを自前で生成した配列なりのデータ構造に移していくという感じでしょうか?
68user

2021/01/17 12:52

そうですね。HTTP/1.0、HTTP/1.1 は行ベースのプロトコルなので、最低でも 1行分は recv を繰り返して読むようにするのがよいと思います。また、1回の recv で複数行を取得できることもある、というかほとんどの場合はそうなるでしょうから、それにも対応した方がよいですね。 1行の最大長を自分で決めるのは問題ありませんので、固定長でもいいし、malloc で動的に確保してもよいでしょう。例えば Apache なら 1行目は 8KB、リクエストヘッダの各行は 4KB です (LimitRequestLine や LimitRequestFieldsize で変更可能)。 https://triple-underscore.github.io/RFC7230-ja.html#p.HTTP-message の 1~4 も参考になると思います。
guest

0

TCP/IPでは、送受信の単位は1byteです。(UDPではまた話が違う)
その上位のレイヤでどのようなプロトコルを決めてどのような単位を作っていようとも、sendで何バイトかのデータをまとめて送った「つもり」でも、それらのまとまりは通信路においては何の考慮もされません。
送る側のsendで"12345" "abcde"を順次まとめて送ったとしても、受信側でデータを取得した時 "123" 45ab" "cde"とrecvで受信されるかもしれない、ということです。(ちょっと古いけど、こんなのとかありました)

もちろん、現実としては諸々の条件などもあって送り側の"12345" "abcde"が「たまたま」"12345" "abcde"と受け取れてしまうこともよくあることですから、バッファサイズとしては多分送る側が一気に送るであろうサイズにしておくのが(recvの都合ではなく、その後段での処理として)都合よく運ぶことが多いだろう、という想像は出来ます。その場合でも、sendとrecvでまとめて送る/受け取るデータの境界がずれる可能性を考慮する必要はあるでしょう。

投稿2021/01/17 02:30

thkana

総合スコア7703

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問