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_addr
と addrlen
宛先アドレスを提供する唯一の場所であるため、再び重要になります。
言語と API は非常に古く、時間の経過とともに成長してきました。一部の API は、今日の観点からは奇妙に見える場合がありますが、大量の既存のコードを壊さずに古いインターフェイスを変更することはできません。何年も何十年も前に定義/設計されたものに慣れる必要がある場合もあります。
それがあなたの質問に答えてくれることを願っています.
send()
呼び出しは、ソケットが TCP SOCK_STREAM
にある場合に使用されます 接続状態。
マニュアルページから:
<ブロック引用>send() 呼び出しは、ソケットが接続状態にある場合にのみ使用できます (そのため、意図した受信者が認識されます)。
あなたのアプリケーションは明らかに他のソケットに接続していないので、send()
は期待できません。