WinSock 代入式が理解できない

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
記事: 26
登録日時: 9年前
住所: 新潟

WinSock 代入式が理解できない

#1

投稿記事 by » 8年前

sockaddr.sin_addr = *((LPIN_ADDR)*lpHost->h_addr_list);

猫でもわかるネットワークプログラミング 第230章の部分を書籍版を参照していたのですが、上記の部分をどのように理解していけばいいのかわかりません。

変数は以下のように定義されています。
LPHOSTENT lpHost;
SOCKADDR_IN sockaddr;
#include <winsock2.h>

ただ、2つの変数のどちらの型も調べてみても、どうもしっくりとくる解説のページがなくてどうにもなりませんでした。
SOCKADDR_IN構造体は接続するために必要な情報を格納するものでまた、sockaddr.sin_addr はIPアドレスを格納するものと今現在は考えているのですが、この認識でよいのでしょうか?

LPHOSTENTのほうや代入式の左辺についてはどうにも手がつけられません。

win VISTA
VC++2008

アバター
みけCAT
記事: 6243
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: WinSock 代入式が理解できない

#2

投稿記事 by みけCAT » 8年前

とりあえず、
「猫でもわかるネットワークプログラミング」は第2版を持っていますが、
第230章なんていうものはありません。
typoではありませんか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

記事: 26
登録日時: 9年前
住所: 新潟

Re: WinSock 代入式が理解できない

#3

投稿記事 by » 8年前

すみません。言葉が足りませんでした。
自分は書籍版の「猫でもわかるネットワークプログラミング」を参照しながら学んでいました。
自分が読んでいるところに対応するところがwebにおける「猫でもわかるネットワークプログラミング」のサイトの第230章です。
書籍「猫でもわかるネットワークプログラミング」を持っていない方も多数いると思ったので、対応するwebページも載せたほうがいいと思ったですが、
わかりづらくて大変申し訳ありませんでした。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: WinSock 代入式が理解できない

#4

投稿記事 by softya(ソフト屋) » 8年前

大雑把に言うとpHost->h_addr_list[0]のIPアドレスの数値4バイトをsockaddr.sin_addrにコピーしているだけです。

こちらを見ると分りやすいかもしれません、
「ホスト名とアドレス」
http://wisdom.sakura.ne.jp/system/winap ... Sock3.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

記事: 26
登録日時: 9年前
住所: 新潟

Re: WinSock 代入式が理解できない

#5

投稿記事 by » 8年前

1-lpHost構造体のメンバであるh_addr_listは目的の情報(IPアドレス)へのポインタが入っている。
つまり、*lpHost->h_addr_list はIPアドレス情報(数値)を表すもの

2-上記の値をLPIN_ADDR型にキャストする

3-LPIIN_ADDR型はポインタ型なので、キャストされた結果あらわすのは目的の情報(IPアドレス)へのポインタだから、実際の数値を左辺に代入するために*をつけることによってポインタのさす数値としている

ということでよいのでしょうか?

やはり、ポインタに対する理解が不足しているのでわからないのでしょうか?

アバター
みけCAT
記事: 6243
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: WinSock 代入式が理解できない

#6

投稿記事 by みけCAT » 8年前

サイトならURLを載せてくれたほうがありがたかったです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: WinSock 代入式が理解できない

#7

投稿記事 by softya(ソフト屋) » 8年前

VC++であれば「宣言への移動」でヘッダなどが見れますのでlpHost->h_addr_listなど全ての構造体を調べて貼りつけてもらえますか?
まず、ポインタ以前に構造を調べてみましょう。

記事: 26
登録日時: 9年前
住所: 新潟

Re: WinSock 代入式が理解できない

#8

投稿記事 by » 8年前

もうしわけありませんでした。次回からはURLを載せるようにします。

コード:

//LPHOSTENT(lphost)
typedef struct hostent FAR *LPHOSTENT;

//SOCKADDR_IN(sockaddr)
typedef struct sockaddr_in {

#if(_WIN32_WINNT < 0x0600)
    short   sin_family;    
#else //(_WIN32_WINNT < 0x0600)
    ADDRESS_FAMILY sin_family;
#endif //(_WIN32_WINNT < 0x0600)

    USHORT sin_port;
    IN_ADDR sin_addr;
    CHAR sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN;

//in_addr
typedef struct in_addr {
        union {
                struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
                struct { USHORT s_w1,s_w2; } S_un_w;
                ULONG S_addr;
        } S_un;
#define s_addr  S_un.S_addr /* can be used for most tcp & ip code */
#define s_host  S_un.S_un_b.s_b2    // host on imp
#define s_net   S_un.S_un_b.s_b1    // network
#define s_imp   S_un.S_un_w.s_w2    // imp
#define s_impno S_un.S_un_b.s_b4    // imp #
#define s_lh    S_un.S_un_b.s_b3    // logical host
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;

//hostent
struct  hostent {
        char    FAR * h_name;           /* official name of host */
        char    FAR * FAR * h_aliases;  /* alias list */
        short   h_addrtype;             /* host address type */
        short   h_length;               /* length of address */
        char    FAR * FAR * h_addr_list; /* list of addresses */
#define h_addr  h_addr_list[0]          /* address, for backward compat */
};

#define FAR                 far

#define far
これでよろしいでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 9年前
住所: 東海地方
連絡を取る:

Re: WinSock 代入式が理解できない

#9

投稿記事 by softya(ソフト屋) » 8年前

調べている過程で分かったと思うのですが、
sockaddr.sin_addr = *((LPIN_ADDR)*lpHost->h_addr_list);
の代入で
sin_addrはIN_ADDR型です。で、LPIN_ADDRはIN_ADDRのポインタ型ですね。
FARは今世代のコンパイラで気にしなくてよいでしょう。

では、 *((LPIN_ADDR)*lpHost->h_addr_list);を分解してみましょう。
(LPIN_ADDR)はIN_ADDRのポインタ型にキャストしています。
*( )でIN_ADDR型になるわけですね。

問題は、*lpHost->h_addr_listなのですが、C言語の場合は->が優先されるので
*(lpHost->h_addr_list)と考えてください。
h_addr_listはchar FAR * FAR * h_addr_list; ですがFARは無視して
char * * h_addr_list;
つまり、ダブルポインタですね。
*(lpHost->h_addr_list)でアクセスすると
lpHost->h_addr_list[0]
と同等の意味になります。

h_addr_listのポインタリストの最初が指しているアドレスリストのポインタを返してくれるわけです。
これは、IN_ADDR型と同じ構造をしてるので
sockaddr.sin_addr = *((LPIN_ADDR)*lpHost->h_addr_list);
これで構造体コピーが実行されてIPアドレスがコピーされます。

長いですが、わかって頂けたでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

記事: 26
登録日時: 9年前
住所: 新潟

Re: WinSock 代入式が理解できない

#10

投稿記事 by » 8年前

解決の連絡とお礼が遅れて申し訳ありませんでした。
みなさまのご協力のおかげで無事解決することができました。
本当にありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る