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

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

詳細はこちら
C

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

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

解決済

3回答

11691閲覧

sockadrr構造体 sockadrr_in構造体について

kazuyakazuya

総合スコア193

C

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

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

2クリップ

投稿2019/09/09 10:50

編集2019/09/09 10:50

C言語のソケットプログラミングをしていて
ソケットの情報を保管している構造体について
どうしても理解できないところがあるので教えてください。

c

1 struct sockaddr_in addr; 2 addr.sin_family = AF_INET; 3 addr.sin_port = htons(port); 4 addr.sin_addr.S_un.S_addr = INADDR_ANY; 5 bind(sock0, (struct sockaddr*) & addr, sizeof(addr));

まずbind関数の第二引数で
addr(sockadrr_in構造体)をキャストしsockadrrに直している
ところですが 
ほとんど似た質問
の回答によると

string

1bindはどんな種類のソケット情報構造体のアドレスも受け入れられるよう、関数プロトタイプの第2引数は、汎用的なソケット情報であるstruct sockaddrで宣言されています。

なぜsockadrr_inからsockadrrへキャストしなければいけないのかは
上記の説明でなんとなくわかったのですが
リンク先の質問である

最初からsockdrr_inではなくsockadrrを使えばいいのではないか?
の回答が理解できないです。
イメージ説明
回答では

string

1この構造体にはインターネットドメインソケット固有の情報であるIPアドレスやポート番号のフィールドがありませんので、それらの値をセットできません。

でも構造体の中身を見ると
sa_family・・・アドレスのファミリ
sa_data・・・アドレスそのもの
確かにポートを指定できそうなものはありませんが
sa_dataにIPアドレスを指定できないのでしょうか?
(ここまで考えると汎用の意味もわからなくなってきた)

c

1sockadrr_in・・・TCP/IPの通信プログラムを作るときに必要 2 3sockadrr・・・汎用型の構造体

結構調べたのですがなかなか理解が進みません。
分からないのでお願いします。

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

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

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

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

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

guest

回答3

0

ベストアンサー

私の回答ですね。

sa_dataにIPアドレスを指定できないのでしょうか?

可能ですが、めんどくさいです。nomukenさんの回答のようポートとIPアドレスが入った変数からmemcpyするか、その値をビット演算でバイト単位に切り出してsa_data[0]sa_data[5]にそれぞれ代入するなど。

struct sockaddr_inに値をセットするほうが簡単です。
面倒で読みにくい方法をとっても良いですが、普通は簡単で読みやすい手段を取ります。

投稿2019/09/09 14:06

otn

総合スコア85882

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

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

kazuyakazuya

2019/09/09 14:18

ありがとうございます。 もしかしたら思い違いしているかもしれないので(私自身が) sockaddrとsockaddr_inで共通しているのは 「アドレス全長」「ファミリ」 だからsockaddr_inからsockaddrへキャストした場合それらの値はそのまま継承される。 で、sockaddrで残るso_dataに入るのは sockaddr_inで指定したポートとアドレスから 算出されたアドレス・・・ いっていることめちゃめちゃですか? 今回も結構な思い違いをしているような気がしたので・・・
otn

2019/09/09 14:34

各種ある sockaddr構造体群で共通しているのは、先頭2バイトのアドレスファミリーだけです。 アドレスファミリーが決まると、どの構造体か決まるので、自動的に長さも決まります。 IPv4の場合は、ファミリーの後の、sockaddr.so_data の先頭2バイトにポート番号、その次の4バイトにIPアドレスがそれぞれビッグエンディアンで入ります。 aa.so_data[0] = port >> 8; aa.so_data[1] = port; aa.so_data[2] = ipaddress >> 24; aa.so_data[3] = ipaddress >> 16; aa.so_data[4] = ipaddress >> 8; aa.so_data[5] = ipaddress; みたいな。 うーん、書いてみるとそんなにわかりにくくはないですね。
kazuyakazuya

2019/09/10 02:52 編集

ありがとうございます。なんとなく理解できました。 sockaddr_inの場合は sockaddrのsa_dataに指定したポートとIPアドレス から構成される6バイトが格納されるということですね。 これがstruct sockaddr_in6など他の sockaddr系でも同じようにしてキャストが行われる ということですか?(これだけ言われてもなんか自信ない・・・)
guest

0

sa_dataにIPアドレスを指定できないのでしょうか?

sockadrr_inの場合はデータ領域が足りるので、できなくはないですが、addr.sin_port = htons(port);のような代入は不可能です。自分でバイト数を数えて正しい位置にデータを書き込む必要が出てきます。

一方で、IPv6用のsockaddr_in6やUnixドメインソケット用のsockaddr_unは、sockaddrよりデータ量が多いので、sockaddrで宣言するとメモリが不足します参考)。ただ、これらのsockaddr_*構造体は、すべて先頭が「構造体の長さ」と「アドレスファミリ」で始まるという部分は共通していますので、sockaddrにキャストしても先頭部には共通してアクセスが可能です。

投稿2019/09/09 11:23

編集2019/09/09 11:27
maisumakun

総合スコア145963

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

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

maisumakun

2019/09/09 11:25

実際にsockadrr_in以外のsockaddr_*と見比べれば。「汎用」の意味もわかりやすいかと思います。
kazuyakazuya

2019/09/09 13:51

ありがとうございます。 sockadrr_in以外のも見ましたが 「構造体の長さ」「アドレスファミリ」があることには共通していますね。 つまり・・・、 sockaddrのsa_dataに入る情報というのは (Ipv4 sockaddr_inの場合) キャスト時、「構造体の長さ」「アドレスファミリ」以外の sim_port,sim_addrこの2つから 生成されるアドレス(?)ということですか?
guest

0

sa_dataにIPアドレスを指定できないのでしょうか?

やろうと思えばできますがそれに意味はありません。

C

1sockadrr addr; 2unsigned short port; 3struct in_addr in_addr; 4 5port = htons(80); 6in_addr.s_addr = htonl(INADDR_ANY);; 7 8addr.sa_family = AF_INET; 9memcpy(&addr.sa_data[0], &port, sizeof(unsigned short)); 10memcpy(&addr.sa_data[2], &in_addr, sizeof(struct in_addr));

とやれば、一応等価コードです。
ですが、わかりにくいだけですよね。

投稿2019/09/09 11:16

nomuken

総合スコア1627

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

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

kazuyakazuya

2019/09/09 13:51

ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問