3

プログラムで recvfrom を使用して、src_addr で指定したサーバーから DGRAM データを取得しています。ただし、addrlen を初期化して渡す必要がある理由がわかりません。

マニュアルページを読みましたが、それが何を目指しているのかよくわかりませんでした。

src_addr が NULL ではなく、基になるプロトコルが送信元アドレスを提供する場合、この送信元アドレスが入力されます。src_addr が NULL の場合、何も入力されません。この場合、addrlen は使用されず、NULL にする必要があります。引数 addrlen は値と結果の引数であり、呼び出し元は呼び出し前に src_addr に関連付けられたバッファーのサイズを初期化し、戻り時にソース アドレスの実際のサイズを示すように変更する必要があります。提供されたバッファが小さすぎる場合、返されるアドレスは切り捨てられます。この場合、addrlen は、呼び出しに提供された値よりも大きな値を返します。

src_addr が ipv4 または ipv6 であることと関係があると思います。これは正しいです?

ありがとう!

4

2 に答える 2

7

多分あなたの側からの誤解があるでしょう。について話す:

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, 
                 struct sockaddr *src_addr, socklen_t *addrlen);

src_addr聞きたいアドレスを渡すために使用されるのではなく、配布された実際の送信元アドレスを取得するために提供されストレージの場所です

したがってsrc_addr、アドレスにまったく関心がないために NULL に設定しても、いずれにしても使用されないので気にする必要はありませaddrlenん。

一方、送信元アドレスについて通知を受けたい場合は、保存場所を提供するだけでなく、提供した保存場所の大きさも伝える必要があります。*addr_lenそのため、割り当てたバッファ サイズに初期化する必要があります。

呼び出し後、 が指す値はaddrlen、送信元アドレスを格納するために割り当てたスペースのうち、実際にデータで満たされた量 (ある場合) を通知します。

サイズについて

struct sockaddr とサイズの受け渡しに関する全体的な問題は、それらがネットワーク ソケットで最も頻繁に使用されているにもかかわらず、はるかに一般的な概念であることを意図していたという事実に関係しています。

ファイルシステムを介して実装される UNIX ドメイン ソケットを例として考えてみてください。IP ベースのネットワークで知られているものとはまったく異なるアドレス指定スキームが必要です。ここで使用される sockaddr のタイプは次のとおりです。

struct sockaddr_un {
  sa_family_t sun_family;               /* AF_UNIX */
  sun_path[UNIX_PATH_MAX];  /* pathname */
};

これを IP ベースのネットワーキングで使用される構造体と比較してください。

struct sockaddr_in {
  sa_family_t    sin_family; /* address family: AF_INET */
  in_port_t      sin_port;   /* port in network byte order */
  struct in_addr sin_addr;   /* internet address */
};

両方に共通点があまりないことは明らかです。

ソケットは両方のケースに適合するように設計されています。

于 2013-03-01T23:02:19.003 に答える
3
ssize_t recvfrom(int socket, void *buffer, size_t length, int flags,
         struct sockaddr *address, socklen_t *address_len);`

address_len引数は、構造体の長さ、つまり、 (メモリ位置の開始アドレス + 値を保持する開始アドレスからのバイト数) でaddress示される開始アドレスから使用するバイト数を指定します。address

構造はで定義されています/usr/include/bits/socket.h

/* Structure describing a generic socket address.  */
struct sockaddr
{
    __SOCKADDR_COMMON (sa_);    /* Common data: address family and length.      */  
    char sa_data[14];       /* Address data.  */
};

したがって、このsa_dataフィールドには、引数で指定された長さのアドレス データ (データの開始アドレス) が格納されaddress_lenます。

... 関数が struct sockaddr* を取ると言うときはいつでも、struct sockaddr_in*、struct sockaddr_in6*、または struct sockadd_storage* をその型に簡単かつ安全にキャストできます。

したがって、man ページと質問へのコメントの @WhozCraig に示されているように、このフィールドは、メソッドが返されるときに実際のサイズで更新されます。

詳しくは

于 2013-03-01T22:50:19.543 に答える