トップページ
ひらく | たたむ | ページトップ
↓マウスで反転選択した文字を検索
Winsock
   
ページ内検索 ページ外検索
検索したい文字を入力して
ENTERを押すと移動します。
\n
[ トップページ ]
[ ____CommandPrompt ] [ ____JScript ] [ ____MySQL ] [ ____Cygwin ] [ ____Java ] [ ____Emacs ] [ ____Make ] [ ____Perl ] [ ____Python ] [ ____OpenGL ] [ ____C# ] [ ____StyleSheet ] [ ____C++ ] [ ____Winsock ] [ ____Thread ] [ ____VisualStudio ] [ ____C ] [ ____Win32API ] [ ____Lua ] [ ____PhotoShop ]
ヘッダ検索
___

■ リファレンス(Reference)






___

■ 共通

___

■ socket

SYNTAX SOCKET socket ( int af, // ソケットタイプ( アドレスの種類を表すアドレスファミリ ) int type , // ソケットの種類( SOCK_STREAM ) int protocol // (TCP | UDP) ); RET 0: OK SOCKET_ERROR: FAIL DESC 指定したタイプの Socket を作成して SOCKET HANDLE( 整数値 ) を返す。

    // TCP ソケットを作成
    SOCKET sock = socket( AF_INET, SOCK_STREAM, 0 );

    // UDP ソケットを作成
    SOCKET sock = socket( AF_INET, SOCK_DGRAM, 0 );
___

■ bind

SYNTAX int bind ( SOCKET s , const struct sockaddr FAR* name , int namelen ); RET 0: 成功 SOCKET_ERROR: 失敗 DESC ソケットにローカルIPアドレスとローカルポートを設定する。 Server 側は指定した port で listen するため bind して明示する Client 側は自動設定にまかせる。 ERROR EADDRINUSE : ポートが他のソケットで利用されている。
    {
      SOCKADDR_IN adr = { AF_INET };
      adr.sin_port = htons(80);
      adr.sin_addr = INADDR_ANY;       // ローカルアドレスにワイルドカードを指定
                                       // サーバー側のすべてのIPアドレスでデータを受け取ることができる
      
      SOCKET sock = socket(AF_INET , SOCK_STREAM , 0);
      bind( sock , (SOCKADDR *)&adr , sizeof(SOCKADDR) );
    }
WARNING
    // 同じローカルポートに他のソケットがバインドしている場合はエラーになる

    SOCKET sock1 = socket(AF_INET , SOCK_STREAM , 0);
    bind( sock1 , (SOCKADDR *)&adr , sizeof(SOCKADDR) );

    SOCKET sock2 = socket(AF_INET , SOCK_STREAM , 0);
    bind( sock2 , (SOCKADDR *)&adr , sizeof(SOCKADDR) );
___

■ SOCKADDR_IN

インターネットアドレス形式を表す構造体 union で定義されているが, ほとんどは S_addr に IP Address を表す 32bit の値をいれる
    typedef struct sockaddr_in {

      short            sin_family;
      u_short          sin_port;        // ポート
      struct in_addr   sin_addr;        // 
      char             sin_zero[8];     // 

    } SOCKADDR_IN;
POINT sin_port にはサーバがサービスを提供するポート番号を指定する sin_addr には INADDR_ANY を指定することで固定アドレスでない場合に自動で割り振られる
___

■ send

SYNTAX int send( SOCKET sock, char *msg, // メッセージのポインタ int length, // メッセージの長さ ( byte 数 ) int flags // 通常 0 ( | MSG_DONTROUTE,MSG_OOB ) ); RET N : 実際に送信されたバイト数 SOCKET_ERROR : エラー DESC 指定したソケット経由でデータを送信する(主に TCP で使用) flags で 0 を指定するとデフォルトの振る舞いをする。 正確にはソケットの送信バッファへデータがコピーされてすぐに制御を返す。 STATE ソケットは接続状態( ESTABLISHED )である必要がある。 // HTTP Client が HTTP Server に HTTP Message ( GET / )
    {
      SOCKADDR_IN adr = { AF_INET };
      name.sin_port = htons(80);
      
      SOCKET sock = socket(AF_INET , SOCK_STREAM , 0);
      bind( sock , (SOCKADDR *)&adr , sizeof(SOCKADDR) );

      const char *msg = "test";

      // WARNING
      //  メッセージは長さを送り, 末尾の '\0' は不要
      send( sock, msg, strlen(msg), 0 ) ;
    }
___

■ recv

SYNTAX int recv( SOCKET sock, char* buf, int length, int flags // 通常 0 ( MSG_PEEK MSG_OOB ) ); RET N : 読み込まれたバイト数 SOCKET_ERROR : 失敗 0 : 通信相手がコネクションを閉じた DESC 指定したソケットで相手からデータを受信をする。( 主にTCPで使用 ) 正確にはソケットの受信バッファにあるデータを buf で指定した領域へコピーする。 受信バッファにデータがなければブロックされるため メインスレッドから実行する場合は何らかの対策が必要。 STATE ESTABLISHED 接続状態でない時に利用すると SOCKET_ERROR が返る。 WARNING HTTP Server が相手だとリクエストを投げない( send() をしない )と何もかえってこない このとき recv() で Block される。 ブロックを回避するには, recv() 用のスレッドを作成したり、非同期ソケットを利用する。

    // シンプルに受信する
    char buf[1024];
    int len = recv(sock, buf, sizeof(buf), 0);
    buf[len] = '\0';

    printf( "recv size %d\n%s", len, buf );

    if ( len == SOCKET_ERROR ) return 1;


WARNING 十分なバッファを WinSock に渡しても ソケット上のキューにあるデータを全て返してくれない 全てとるには呼出しを繰り返す
    char buf[1024 * 4];
    memset(buf, 0, sizeof(buf));

    int sum = 0;
    while ( 1 ) {

      int len = recv(sock, buf + sum, sizeof(buf) - sum, 0);
      sum += len;

      // 0 がきたら相手が CLOSE したことを意味する。
      if ( len == 0 ) {
        printf( "server closed\n" );
        break;
      }

      // 相手が close した状態で recv() をしたり, サーバが落ちていると -1 が返る。
      if ( len == SOCKET_ERROR ) {
        break;
      }

    }
FD_CLOSE がうけれるなら, len == 0 の処理は不要 逆に FD_CLOSE Event がくるときに , recv をすると, len = 0 がかえってくる 0 == recv() は FD_CLOSE をチェックしているに等しい

    // Thread にわたす 受信処理
    void* waitReceiveThread(void* pParam)
    {
        char buf[1024];
        int len;

        while(1)
        {
           // データ受信待ち
           len = recv(sock,buf,1024,0);

          printf("Received %d bytes\n",len);

          // 相手が閉じたら 
          if(len == 0)
          {
              printf("check\n");

              // こっちも切る
              close(sock);
              break;
          }
        }

        return NULL;
    }
connect が失敗した状態のソケットで recv( 受信 ) をすると WSAENOTCONN (10057) が返る。 接続されていないソケットを使用したということ。 同じく send() でも発生する。
    // no check
    connect( sock, (struct sockaddr *)&adr, sizeof(adr) );

    int n = recv(m_sock, buf, sz, 0);
    if (n <  0) {
      printf("ERR: recv : %d\n", WSAGetLastError() );
    }  
___

■ closesocket

SYNTAX int closesocket ( SOCKET sock ); RET OK : 0 FAIL: SOCKET_ERROR DESC コネクションを切る。 ソケットは通信できない状態へ移行する 使うと Client 側には HOST との接続が切られました という message が届く
___

■ server.固有

___

■ listen

SYNTAX int listen ( SOCKET s , // 受信に使う Socket int queue // 接続に使うキューの数 ( 最大接続数 ) ); RET 0: 成功 SOCKET_ERROR: 失敗 DESC サーバのソケットが接続待ち状態( LISTENING )に移行して、 クライアントからの接続要求がキューへ格納できる状態へする。 queue で指定した数だけ最大でリクエストを保存できて、 アクセプト( accept )をするとキューから取り出す。 queue 以上のクライアントからの接続要求は失敗する。 POINT サーバが listen() しないとクライアント側のコネクト要求( connect() )は失敗する。
    {
      SOCKADDR_IN adr = { AF_INET };
      adr.sin_port = htons(2048);
      adr.sin_addr = INADDR_ANY;
      
      SOCKET sock = socket(AF_INET , SOCK_STREAM , 0);
      bind( sock , (SOCKADDR *)&adr , sizeof(SOCKADDR) );

      // キューの数を5にしてリスン状態にする。
      listen( sock, 5 );
    }
___

■ accept

SYNTAX SOCKET accept ( SOCKET s, struct sockaddr FAR* addr, // クライアント側のアドレス情報 int FAR* addrlen ); RET ClientSocket : 成功 INVALID_SOCKET : 失敗 DESC クライアントからの接続を受け付ける。 正確には リスン中のソケットの接続すみリストからひとつを取り出してディスクリプタを割り当てて返す。 リストが空ならばブロックされため、 GUI の MainThread では利用しないこと。
    {

      SOCKET sockCli = accept( sock,   );


      // お客さんへメッセージをなげる。
      const char buf[] = "いらっしゃい";
      send( sockCli, buf, length(buf), 0 );

    }
___

■ client.固有

___

■ connect

SYNTAX int connect( SOCKET, struct sockaddr *adr, int size ); RET SOCKET_ERROR : 接続に失敗 0 : 成功 DESC 指定したサーバに接続する。 不正なアドレスを指定すると失敗する。 ERROR ETIMEOUT : 指定した時間にハンドシェイクが完了しなかった。 WARNING Server でリスン( listen() )してない場合はすべての接続要求は失敗する。 逆に listen() していれば accept() をしなくても接続要求は成功する。 ただしリストが埋まっていれば失敗する。
    struct sockaddr_in adr = { AF_INET };
    adr.sin_port = htons( 80 );
    adr.sin_addr.S_un.S_addr = inet_addr( "127.0.0.1" );  

    int ret = connect( sock, (struct sockaddr *)&adr, sizeof(adr) );

    if ( ret == SOCKET_ERROR ) {
      printf( "fail connect\n" );
    }
host が存在して ping などで接続できるが, 一定時間がたっても応答がない場合は 20秒ほど経過してから 10060 ( WSAETIMEDOUT ) が返る。 ケースとしてクライアントが指定したポートでリスンしてないなどがある
    adr.sin_port = htons( 8888 );
    int ret = connect( sock, (struct sockaddr *)&adr, sizeof(adr) );

    if ( ret != 0 ) {
      printf("FAIL connect : WSAGetLastError  %d\n", WSAGetLastError());       
    }
___

■ 変換

___

■ htons

SYNTAX u_short htons( u_short ); DESC short int をネットワークバイトオーダーに変換 SYNTAX u_short htons ( u_short hostshort // 変換する 16 ビットホストバイトオーダ ); ); RET 指定した値のネットワークバイトオーダー DESC 16 ビットホストバイトオーダーをネットワークバイトオーダーに変換する
    {  
       struct sockaddr_in srcAddr;
              
       // short 型の Data のときに使う
       srcAddr.sin_port = htons( port );
    }
___

■ htonl

SYNTAX u_short htonl ( u_long hostshort // 変換する 32 bit HostByteOrder ); RET 指定した値の NetworkByteOrder DESC htons の long (32bit) Version
    {  
       struct sockaddr_in srcAddr;
       srcAddr.sin_addr.s_addr  = htonl( INADDR_ANY );
    }
___

■ ntohs

SYNTAX u_short ntohs( u_short netshort ); DESC short の整数を ホストバイトオーダー に変換する Client の port 情報を変換する際に便利
___

■ getHostByName

SYNTAX struct hostent * getHostByName( char *name ); DESC ホスト名( 又は dot表記のIPアドレス )から 32bit IPAddress をえる 逆に IP からホスト名とりたい場合は getHostByAddr() を使う DNS にサーバー名とアドレスを登録しておく必要がある。 RET !NULL : 変換されたホスト情報へのポインタ NULL : 不正なホスト名( dot表記IPアドレス )を指定した。 POINT IPアドレスでもあて先を指定できるが、ISPの変更があった場合に影響を受けないように ホスト名を指定しておくと良い。
     LPHOSTENT host = getHostByName( "google.co.jp" );

  POINT
    // ホスト情報を格納した構造体 hostent を返す。

    typedef struct hostent {
       char *h_name;              // ホスト名
       char **h_aliases;          // ホストの別名


       char **h_addr_list;        // 32bit IPアドレスのポインタ。プログラムはこの値を指定すること。
    };
    

___

■ getHostByAddr

SYNTAX struct hostent * getHostByAddr( char *addr, int len, int type ); DESC IP Address から Host情報をえる
___

■ inet_addr

SYNTAX int inet_addr( const char FAR * // 文字列表現アドレスへのポインタ ( "xxx.xxx.x.x" ) ); RET アドレスの数値表現: 成功 INADDR_NONE : 失敗 DESC ドット表記のIPv4アドレス文字列を 4byte の整数(ネットワークバイトオーダー)へ変換
    BAD
      // ドメイン名はダメ
      inet_addr( "library.city.chuo.tokyo.jp" )
    OK
      // dot 表記を渡すこと
      inet_addr( "210.233.111.187" );
___

■ inet_ntoa

SYNTAX char * inet_ntoa ( struct in_addr in // アドレスが格納されている in_addr 構造体 ); RET 文字列へのポインタ : 成功 NULL : 失敗 DESC バイナリ表現の IPアドレスを 10進数のドット表記文字列( "127.0.0.1" など )に変換。
___

■ WinSock.固有

___

■ WSAStartup

SYNTAX int WSAStartup ( WORD wVersionRequested, // 使用したい version LPWSADATA lpWSAData); // WinSock の実装情報を取得する. RET 0: OK !0: FAIL DESC DLL を初期化する
___

■ WSACleanup

SYNTAX int WSACleanup (); RET 0: OK !0: FAIL DESC WinSock の Resource を解放する
___

■ WSAGetLastError

SYNTAX int WSAGetLastError() DESC 最後( 直近 )に発生したエラーコードを返す。
___

■ 非同期.API

___

■ WSAWaitForMultipleEvents

SYNTAX DWORD WSAWaitForMultipleEvents( 1, // Event数 &hEvent, // EventObject FALSE, 5*1000, // 待ち時間 msec FALSE ); DESC Socket に関連つけられたネットワークイベントを指定時間まつ (connect | recv | cloes )をまつ

    // Accept を指定する

    // 
    WSAWaitForMultipleEvents()

    // Client が接続してきた !
    if ( FD_ACCEPT ) {

    } 


___

■ WSAEnumNetworkEvents

SYNTAX nRet = WSAEnumNetworkEvents( Socket, hEvent, &events ); DESC 発生したNetworkイベントの種類を調べる
___

■ WSAEventSelect

SYNTAX nRet = WSAEventSelect( Socket, // 関連づける Socket hEvent, // Event FD_READ|FD_CONNECT|FD_CLOSE // 通知をうける Event の種類を設定 ); RET 0 : 成功 !0 : ERRORCODE DESC ソケットを[ 非ブロッキング ]にし[ ネットワークイベント ]を関連付ける イベントがおきると イベントオブジェクトが Signal 状態になる yfWaitAll [in] A value that specifies the wait type wait の type を指定する If TRUE the function returns when the state of all objects in the lphEvents array is signaled If FALSE the function returns when any of the event objects is signaled ( すべての Event に対してかえす ) In the latter case the return value minus WSA_WAIT_EVENT_0 indicates the index of the event object whose state caused the function to return If more than one event object became signaled during the call this is the array index to the signaled event object with the smallest index value of all the signaled event objects なんか false でよさげ fAlertable [in] 〈物・事が〉変えられる, 改められる. A value that specifies whether the thread is placed in an alertable wait state so the system can execute I/O completion routines If TRUE the thread is placed in an altertable wait state and WSAWaitForMultipleEvents can return when the system executes an I/O completion routine In this case WSA_WAIT_IO_COMPLETION is returned and the event that was being waited on is not signaled yet The application must call the WSAWaitForMultipleEvents function again If FALSE the thread is not placed in an altertable wait state and I/O completion routines are not executed
___

■ データ型

___

■ sockaddr

DESC 汎用のアドレス構造体 特定のアドレスファミリ固有ではない。
    struct sockaddr {
      unsigned short sa_family;
      char sa_data[14]
    };
___

■ sockaddr_in

DESC インターネットアドレスファミリの構造体 POINT sockaddr 構造体をインターネットファミリ向けに定義しなおしただけのため、 sockaddr を受け取る関数にキャストして渡すことができる。 設定する値はすべてネットワークバイトオーダーであること。
    struct sockaddr {
      unsigned short sin_family;
      unsigned short sin_port;      // ポート 
      struct in_addr sin_addr;      // ip

      char sin_zero[8];             // 未使用領域
    };







金利比較.COM
NINJAIDX 13