GNU/Linux >> Linux の 問題 >  >> Linux

C raw ソケットの sendto アドレスの目的は?

<ブロック引用>

send でソケットに書き込む

send() であるため、失敗します。 関数は 接続 でのみ使用できます ソケット(ここで述べたように)。通常は send() を使用します TCP 通信 (接続指向) および sendto() 用 UDP データグラム (コネクションレス) の送信に使用できます。

「ping」パケット、またはより正確には ICMP データグラムを送信したいので、明らかにコネクションレスであるため、sendto() を使用する必要があります。 関数。

<ブロック引用>

sendto の余分なフィールドはないようです 実際にかなり使用されています。 sendto を使用しなければならない技術的な理由はありますか? send の代わりに それとも API の単なる見落としですか?

短い答え:

send() を使用できない場合 の場合、sendto() というオプションが 1 つだけ残っています。 .

長い答え:

これは、API の単なる見落としではありません。通常のソケットを使用して UDP データグラムを送信する場合 (例:SOCK_DGRAM )、sendto() struct sockaddr_in で指定した宛先アドレスとポートに関する情報が必要です。 、 右?構造体 sockaddr_in唯一です 受信者が誰になるかを指定した場所。言い換えれば、この場合、追加の IP ヘッダーを提供しないため、カーネルは構造体から宛先情報を取得する必要があります。

sendto()だから UDPだけでなく生のソケットにも使用されるため、ポート番号などの一部のパラメーターが関連しない/最終的に使用されない場合でも、さまざまなユースケースをすべてカバーできる多かれ少なかれ「汎用」関数でなければなりません。 /P>

たとえば、 IPPROTO_RAW を使用して (これは自動的に IP_HDRINCL を意味します )、IP ヘッダーを独自に作成する意図を示します。したがって、sendto() の最後の 2 つの引数は sendto() に渡すデータ バッファーに既に含まれているため、実際には冗長な情報です。 2 番目の引数として。 IP_HDRINCL を使用する場合でも、注意してください。 raw ソケットを使用して、対応するフィールドを 0 に設定すると、カーネルはソース アドレスと IP データグラムのチェックサムを入力します。 .

独自の ping プログラムを作成する場合は、 socket() の最後の引数を変更することもできます IPPROTO_RAW の関数 IPPROTO_ICMP へ カーネルに IP ヘッダーを作成させるので、心配することが 1 つ少なくなります。これで、2 つの sendto() がどのように機能するかを簡単に確認できます。 -パラメータ *dest_addraddrlen 宛先アドレスを提供する唯一の場所であるため、再び重要になります。

言語と API は非常に古く、時間の経過とともに成長してきました。一部の API は、今日の観点からは奇妙に見える場合がありますが、大量の既存のコードを壊さずに古いインターフェイスを変更することはできません。何年も何十年も前に定義/設計されたものに慣れる必要がある場合もあります。

それがあなたの質問に答えてくれることを願っています.


send() 呼び出しは、ソケットが TCP SOCK_STREAM にある場合に使用されます 接続状態。

マニュアルページから:

<ブロック引用>

send() 呼び出しは、ソケットが接続状態にある場合にのみ使用できます (そのため、意図した受信者が認識されます)。

あなたのアプリケーションは明らかに他のソケットに接続していないので、send() は期待できません。


Linux
  1. Whoisクエリのソースアドレスを制御しますか?

  2. MAC アドレスの取得

  3. raw ソケットを特定のインターフェイスにバインドする方法

  1. Bash For Loopsの「do」キーワードの目的は?

  2. Python raw ソケット:プロトコルがサポートされていません

  3. root 権限なしで Python で raw ソケットを作成する

  1. パブリックIPを決定するためのコマンド?

  2. 汎用またはI/Oクラウドサーバーへの移行に関する考慮事項

  3. C++ メソッドの perf プローブを追加できない