ページ 11

WinSock 代入式が理解できない

Posted: 2011年8月23日(火) 22:41
by
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

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

Posted: 2011年8月24日(水) 21:36
by みけCAT
とりあえず、
「猫でもわかるネットワークプログラミング」は第2版を持っていますが、
第230章なんていうものはありません。
typoではありませんか?

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

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

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

Posted: 2011年8月24日(水) 22:19
by softya(ソフト屋)
大雑把に言うとpHost->h_addr_list[0]のIPアドレスの数値4バイトをsockaddr.sin_addrにコピーしているだけです。

こちらを見ると分りやすいかもしれません、
「ホスト名とアドレス」
http://wisdom.sakura.ne.jp/system/winap ... Sock3.html

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

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

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

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

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

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

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

Posted: 2011年8月25日(木) 22:17
by みけCAT
サイトならURLを載せてくれたほうがありがたかったです。

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

Posted: 2011年8月26日(金) 01:00
by softya(ソフト屋)
VC++であれば「宣言への移動」でヘッダなどが見れますのでlpHost->h_addr_listなど全ての構造体を調べて貼りつけてもらえますか?
まず、ポインタ以前に構造を調べてみましょう。

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

Posted: 2011年9月03日(土) 12:07
by
もうしわけありませんでした。次回からは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
これでよろしいでしょうか?

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

Posted: 2011年9月03日(土) 12:24
by softya(ソフト屋)
調べている過程で分かったと思うのですが、
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アドレスがコピーされます。

長いですが、わかって頂けたでしょうか?

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

Posted: 2011年9月14日(水) 22:26
by
解決の連絡とお礼が遅れて申し訳ありませんでした。
みなさまのご協力のおかげで無事解決することができました。
本当にありがとうございました。