Sock-99.API...使う範囲で
お題
最低限必要なデータ型とか関数など
参考サイト
Geekなページ
https://www.geekpage.jp/programming/winsock/
MicrosoftのWinSock関係のページ( 英語 )
https://docs.microsoft.com/en-us/windows/win32/api/winsock/
https://docs.microsoft.com/en-us/windows/win32/api/winsock2/
https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2
ヘッダ・ライブラリ
必要ヘッダとライブラリ
WinSock2.h
ws2tcpip.h
ws2_32.lib
注意
WinSock2.hとWindows.hを同時にインクルードすると多重定義エラーが大量に出る
解決策
code:sock.cpp
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WinSock2.h>
参考サイト https://www.chihayafuru.jp/tech/index.php/archives/2967
データ型関係
WSADATA構造体
用途
WinSockに関する情報を格納するための構造体
WinSockの初期化( WSAStartup() )時にこの構造体のアドレスを渡す
定義
code:WinSock2.h
typedef struct WSAData {
WORD wVersion; // 使用するであろうWinSockのバージョン 上位:マイナー、下位:メジャー
WORD wHighVersion; // 使用可能な最新のWinSockのバージョン 上位:マイナー、下位:メジャー
#ifdef _WIN64
unsigned short iMaxSockets; // オープン可能なソケットの最大数
unsigned short iMaxUdpDg; // 最大データグラムメッセージサイズ
char FAR * lpVendorInfo; // ベンダ固有情報へのポインタ
char szDescriptionWSADESCRIPTION_LEN+1; // Windows Sockets実装の説明
char szSystemStatusWSASYS_STATUS_LEN+1; // 関連ステータスや設定情報
#else
char szDescriptionWSADESCRIPTION_LEN+1;
char szSystemStatusWSASYS_STATUS_LEN+1;
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
#endif
} WSADATA, FAR * LPWSADATA;
BSD Socket
ない!
SOCKET型
用途
ソケットディスクリプタ用のデータ型
実際はUINT_PTR
UINT_PTRはポインタ長のunsigned int
32bit型とか64bit型とかに対応できるタイプの整数
typedef UINT_PTR SOCKET;
BSD Socket
int ※エラー時マイナス値が返ってくるのでunsignedはなしかな...
SOCKADDR構造体
用途
ソケットのアドレス情報を格納するための構造体
TCP/IP以外のプロトコルにも対応可能
定義
code:WinSock2.h
struct sockaddr{
ushort sa_family; // アドレスファミリ
char sa_data14; // アドレスデータ
};
typedef struct sockaddr SOCKADDR;
BSD Socket
メンバ変数が一つ増える ※構造体のサイズ
typedefで大文字化させたりしていない
code:BSD.h
struct sockaddr {
u_char sa_len; // 構造体のサイズ
u_char sa_family; // アドレスファミリ
char sa_data14; // アドレスデータ
};
SOCKADDR_IN構造体
用途
ソケットのアドレス情報を格納するための構造体
TCP/IP専用
INはInternetのIN
定義
code:WinSock2.h
struct sockaddr_in{
short sin_family; // アドレスファミリ
u_short sin_port; // ポート番号
struct in_addr sin_addr; // IPアドレス
char sin_zero8; // 余白 sockaddrとの互換用
};
typedef struct sockaddr_in SOCKADDR_IN;
BSD Socket
メンバ変数が一つ増える ※構造体のサイズ
typedefで大文字化させたりしていない
code:BSD.h
struct sockaddr_in{
u_char sin_len; // 構造体のサイズ
u_char sin_family; // アドレスファミリ
u_short sin_port; // ポート番号
struct in_addr sin_addr; // IPアドレス
char sin_zero8; // 余白
};
in_addr構造体
用途
IPv4アドレスを格納する
sockaddr_in構造体のメンバ変数として使用されている
定義
共用体を使って1バイト単位でのアクセスも可能にしている
code:WinSock2.h
struct in_addr {
union {
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1, s_w2; } S_un_w;
u_long S_addr;
}S_un;
#define s_addr S_un.S_addr
#define s_host S_un.S_un_b.s_b2
#define s_net S_un.S_un_b.s_b1
#define s_imp S_un.S_un_w.s_w2
#define s_impno S_un.S_un_b.s_b4
#define s_lh S_un.S_un_b.s_b3
};
BSD Socket
シンプル!
code:BSD.h
struct in_addr {
u_int32_t s_addr;
};
関数関係
WSAStartup()
用途
WinSockの初期化
定義
code:WinSock2.h
int WSAAPI WSAStartup( in WORD wVersionRequested, out LPWSADATA lpWSAData )
table:引数
wVersionRequested 使用したいWinSockのバージョン
( 上位バイト : マイナーバージョン、下位バイト : メジャーバージョン )
lpWSAData WSADATA 構造体のポインタ
初期化の結果、使用する環境上での WinSock の環境などが格納される
table:戻り値
成功 0
失敗 エラーコード
コーディング例
code:socket.cpp
WSADATA wsaData;
// WinSock2.2 初期化処理
if( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) != 0 )
{
// エラー処理
}
BSD Socket
ない!
WSACleanup()
用途
WinSockの終了処理
定義
code:WinSock2.h
int WSACleanup()
table:引数
なし
table:戻り値
成功 0
失敗 SOCKET_ERROR
#define SOCKET_ERROR (-1)
コーディング例
code:socket.cpp
// WinSock終了処理
if( WSACleanup() != 0 )
{
// エラー処理
}
BSD Socket
ない!
socket()
用途
ソケットの作成
作成された時点で、OSが空いているポート番号を自動的に割り当て
起動するたびに変わるので、サーバ側で使用するソケットは別途bind()が必要
定義
code:WinSock2.h
SOCKET WSAAPI socket( in int af, in int type, in int protocol )
table:引数
af アドレスファミリ
IPv4 : AF_INET
IPv6 : AF_INET6
type ソケットのタイプ ※現状ではTCPかUDPかでOK
TCP : SOCK_STREAM
UDP : SOCK_DGRAM
protocol トランスポート層のプロトコル
TCP : IPPROTO_TCP
UDP : IPPROTO_UDP
※0をいれるとafとtypeから自動割り当て
table:戻り値
成功 作成されたソケットのソケットディスクリプタ
失敗 INVALID_SOCKET
#define INVALID_SOCKET (SOCKET)(~0)
コーディング例
code:socket.cpp
// TCPリスンソケットの作成
SOCKET listenSock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( listenSock == INVALID_SOCKET )
{
// エラー処理
}
code:socket.cpp
// UDPソケットの作成
SOCKET sock;
if( ( sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET )
{
// エラー処理
}
BSD Socket
code:BSD.h
int socket(int address_family, int socket_type, int protocol);
table:引数
WinSockとおなじ
table:戻り値
成功 ソケットディスクリプタ ※整数値
失敗 -1
code:socket.cpp
int sock;
if( ( sock = socket( AF_INET, SOCK_DGRAM. IPPROTO_UDP ) < 0 )
{
// エラー
}
closesocket()
用途
ソケットの破棄
定義
code:WinSock2.h
int closesocket( in SOCKET s )
table:引数
s 破棄するソケットのソケットディスクリプタ
table:戻り値
成功 0
失敗 SOCKET_ERROR
コーディング例
code:Winsock.cpp
if( closesocket( sock ) == SOCKET_ERROR )
{
// エラー
}
BSD Socket
code:BSD.h
int close(int fd);
table:引数
fd 破棄するソケットのソケットディスクリプタ
table:戻り値
成功 0
失敗 -1
code:socket.cpp
if( close( sock ) < 0 )
{
// エラー
}
bind()
用途
ソケットにソケットアドレス情報を設定する
おもにサーバ側で呼ぶ関数
定義
code:WinSock2.h
int bind( in SOCKET s, const sockaddr *addr, in int namelen )
table:引数
s アドレス情報を割り当てるソケットのソケットディスクリプタ
addr アドレス情報をセットしたソケットアドレス構造体( SOCKADDR構造体 )のアドレス
namelen addrのサイズ
table:戻り値
成功 0
失敗 SOCKET_ERROR
コーディング例
code:socket.cpp
SOCKET sock;
~省略~
// ソケットアドレス構造体を用意
SOCKADDR_IN bindAddr;
memset( &bindAddr, 0, sizeof( bindAddr ) ); // 0クリアで初期化
bindAddr.sin_family = AF_INET; // IPv4アドレス使用
bindAddr.sin_port = htons( 10000 ); // ポート番号10000指定 マジックナンバーはNG
bindAddr.sin_addr.s_addr = htonl( INADDR_ANY ); // すべての自分のNICが対象
// ソケットアドレス情報割り当て
if( bind( sock, (SOCKADDR *)&bindAddr, sizeof( bindAddr ) ) == SOCKET_ERROR )
{
// エラー処理
}
1台のホストに複数のNIC――複数のIPアドレス――が存在している場合、どのIPアドレス宛でもこのアプリケーションでさばきますよ…というのがINADDR_ANY
BSD Socket
code:BSD.h
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
table:引数
sockfd アドレス情報を割り当てるソケットのソケットディスクリプタ
addr アドレス情報をセットしたソケットアドレス構造体( SOCKADDR構造体 )のアドレス
addrlen addrのサイズ
table:戻り値
成功 0
失敗 -1
code:socket.cpp
int sock;
~省略~
// ソケットアドレス構造体を用意
struct sockaddr_in bindAddr;
memset( &bindAddr, 0, sizeof( bindAddr ) ); // 0クリアで初期化
bindAddr.sin_family = AF_INET; // IPv4アドレス使用
bindAddr.sin_port = htons( 10000 ); // ポート番号10000指定 マジックナンバーはNG
bindAddr.sin_addr.s_addr = htonl( INADDR_ANY ); // すべての自分のNICが対象
// ソケットアドレス情報割り当て
if( bind( sock, (struct sockaddr*)&bindAddr, sizeof( bindAddr ) ) < 0 )
{
// エラー処理
}
listen()
用途
ソケットをリスン状態( コネクション確立のための接続要求待ち状態 )にする
おもにTCPサーバで呼ぶ関数
定義
code:WinSock2.h
int WSAAPI listen( in SOCKET s, in int backlog )
table:引数
s 割り当てるソケットのソケットディスクリプタ
backlog 接続要求用のキューのサイズ
table:戻り値
成功 0
失敗 SOCKET_ERROR
コーディング例
code:socket.cpp
SOCKET listenSock;
~省略~
// リスン状態にする
if( listen( sock, 5 ) == SOCKET_ERROR )
{
// エラー処理
}
BSD Socket
code:BSD.h
int listen(int sockfd, int backlog);
table:引数
sockfd リスン状態にするソケットのソケットディスクリプタ
backlog 接続要求用のキューのサイズ
table:戻り値
成功 0
失敗 -1
code:socket.cpp
int sock;
~省略~
// リスン状態にする
if( listen( sock, 5 ) < 0 )
{
// エラー処理
}
accpet()
用途
クライアントからの接続要求受付・コネクションの確立・通信用ソケットの作成
おもにTCPサーバで呼ぶ関数
定義
code:WinSock2.h
SOCKET WSAAPI accept( in SOCKET s, out sockaddr *addr, in, out int *addrlen )
table:引数
s 接続要求を受け付けるリスンソケットのソケットディスクリプタ
addr 接続要求を出したクライアントのソケットアドレス情報を格納する構造体の先頭アドレス
addrlen 第2引数addrのサイズを格納した領域の先頭アドレス
table:戻り値
成功 コネクションを確立した通信用ソケットのソケットディスクリプタ
失敗 INVALID_SOCKET
コーディング例
code:socket.cpp
SOCKET listenSock;
~省略~
// クライアントとのコネクション確立用のソケット
SOCKET sock;
// クライアントのアドレス情報を格納するための構造体
SOCKADDR_IN fromAddr;
int addrlen = sizeof( fromAddr );
// 接続要求受付
if( ( sock = accept( listenSock, (SOCKADDR *)&fromAddr, &addrlen ) ) == INVALID_SOCKET )
{
// エラー処理
}
複数クライアントからの接続要求を受け付けるサーバにする場合は、クライアントとのコネクション確立用のソケットに配列とかvector とか list とかを使う…vector かな
BSD Socket
code:BSD.h
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
table:引数
sockfd 接続要求を受け付けるリスンソケットのソケットディスクリプタ
addr 接続要求を出したクライアントのソケットアドレス情報を格納する構造体の先頭アドレス
addrlen 第2引数addrのサイズを格納した領域の先頭アドレス
table:戻り値
成功 コネクションを確立した通信用ソケットのソケットディスクリプタ
失敗 -1
code:socket.cpp
int listenSock;
~省略~
// クライアントとのコネクション確立用のソケット
int sock;
// クライアントのアドレス情報を格納するための構造体
SOCKADDR_IN fromAddr;
int addrlen = sizeof( fromAddr );
// 接続要求受付
if( ( sock = accept( listenSock, (struct sockaddr*)&fromAddr, &addrlen ) ) < 0 )
{
// エラー処理
}
connect()
用途
サーバへの接続要求 ※サーバ側のaccept()でサーバ側のソケットとのコネクションが確立
TCPクライアントで呼ぶ関数
定義
code:WinSock2.h
int WSAAPI connect( in SOCKET s, in const sockaddr *addr, in int addrlen )
table:引数
s 接続要求を出すソケットのソケットディスクリプタ
addr 接続先サーバのソケットアドレス情報を格納した構造体の先頭アドレス
addrlen 第2引数addrのサイズ
table:戻り値
成功 0
失敗 SOCKET_ERROR
コーディング例
code:socket.cpp
// 接続先サーバのアドレスを格納するソケットアドレス構造体
SOCKADDR_IN serverAddr;
memset( &serverAddr, 0, sizeof(serverAddr) ); // 0クリアで初期化
serverAddr.sin_family = AF_INET; // IPv4アドレス
serverAddr.sin_port = htons( 10000 ); // サーバのポート番号
inet_pton( AF_INET, "192.168.43.253", &serverAddr.sin_addr.s_addr); // サーバのIPアドレス
// 接続要求
if( connect( sock, (SOCKADDR *)&serverAddr, sizeof( serverAddr ) ) == SOCKET_ERROR )
{
// エラー処理
}
BSD Socket
code:BSD.h
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
table:引数
sockfd 接続要求をだすソケットのソケットディスクリプタ
addr 接続先サーバのソケットアドレス情報を格納した構造体の先頭アドレス
addrlen 第2引数addrのサイズを格納した領域の先頭アドレス
table:戻り値
成功 0
失敗 -1
code:socket.cpp
// 接続先サーバのアドレスを格納するソケットアドレス構造体
struct sockaddr_in serverAddr;
memset( &serverAddr, 0, sizeof(serverAddr) ); // 0クリアで初期化
serverAddr.sin_family = AF_INET; // IPv4アドレス
serverAddr.sin_port = htons( 10000 ); // サーバのポート番号
inet_pton( AF_INET, "192.168.43.253", &serverAddr.sin_addr.s_addr); // サーバのIPアドレス
// 接続要求
if( connect( sock, (SOCKADDR *)&serverAddr, sizeof( serverAddr ) ) < 0 )
{
// エラー処理
}
shutdown()
用途
コネクションの切断
送信のみ切断
受信のみ切断
送受信ともに切断
TCPで利用
定義
code:WinSock2.h
int WSAAPI shutdown( in SOCKET s, in int how )
table:引数
s 切断したいコネクションに使用しているソケットのソケットディスクリプタ
how 切断タイプ
SD_RECEIVE : 受信切断 ※0
SD_SEND : 送信切断  ※1
SD_BOTH : 送受信切断 ※2
table:戻り値
成功 0
失敗 SOCKET_ERROR
コーディング例
code:socket.cpp
// 切断
if( shutdown( sock, SD_BOTH ) == SOCKET_ERROR )
{
// エラー処理
}
BSD Socket
code:BSD.h
int shutdown(int sockfd, int how);
table:引数
sockfd 切断したいコネクションに使用しているソケットのソケットディスクリプタ
how 切断タイプ
SHUT_RD : 受信切断 ※0
SHUT_WR : 送信切断 ※1
SHUT_RDWR : 送受信切断 ※2
table:戻り値
成功 0
失敗 -1
code:socket.cpp
// 切断
if( shutdown( sock, SHUT_RDWR ) < 0 )
{
// エラー処理
}
send()
用途
コネクション確立済みの状態でのデータ送信
TCPで利用
定義
code:WinSock2.h
int WSAAPI send( in SOCKET s, in const char *buf, in int len, in int flags )
table:引数
s 送信に使用するソケットのソケットディスクリプタ
buf 送信データの先頭アドレス
len 送信データのサイズ
flags 基本的に0でOK
table:戻り値
成功 送信データのバイト数
失敗 SOCKET_ERROR
コーディング例 その1
文字列の送信
code:socket.cpp
char buff1024; // 送信文字列の格納領域
~省略~
int ret = send( sock, buff, strlen(buff), 0 ); // 終端の\0は送られないので要注意
if( ret != strlen(buff) )
{
// エラー処理
}
buffのサイズ( 1024 )ではなく文字列の長さで送信しているバージョン
終端記号の\0は送られないため、受信側で\0をつける必要がある
コーディング例 その2
文字列の送信
code:socket.cpp
char buff1024; // 送信文字列の格納領域
~省略~
int ret = send( sock, buff, strlen(buff) + 1, 0 ); // 終端の\0も送る
if( ret != strlen(buff) + 1 )
{
// エラー処理
}
文字列の長さ+1を送信 => 終端記号の\0まで送信しているバージョン
受信側は受け取った文字列をそのまま利用可能
コーディング例 その3
数値の送信 ※実は重要な処理が抜けているのでこのまま使わないこと!
code:socket.cpp
int value; // 送信データの格納領域
~省略~
int ret = send( sock, (char*)&value, sizeof(value), 0 );
if( ret != sizeof(value) )
{
// エラー処理
}
文字列( char* )以外のデータを送りたいときはキャストするだけ
整数値でも構造体でも送信可能
BSD Socket
code:BSD.h
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
table:引数
sockfd 送信に使用するソケットのソケットディスクリプタ
buf 送信データの先頭アドレス
len 送信データのサイズ
flags 基本的に0でOK
table:戻り値
成功 送信データのバイト数
失敗 -1
コーディング例は省略!
recv()
用途
コネクション確立済みの状態でのデータ受信
TCPで利用
定義
code:WinSock2.h
int WSAAPI recv( in SOCKET s, out char *buf, in int len, in int flags )
table:引数
s 受信に使用するソケットのソケットディスクリプタ
buf 受信データの格納領域の先頭アドレス
len bufのサイズ
flags 基本的に0でOK
table:戻り値
成功 受信データのバイト数
失敗 SOCKET_ERROR
コーディング例 その1
文字列の受信 ※送信時に\0を送ってないバージョン
code:socket.cpp
char buff1024; // 受信文字列の格納領域
~省略~
int ret = recv( sock, buff, sizeof(buff)-1, 0 ); // こっちはstrlen()にしないこと!
if( ret == SOCKET_ERROR )
{
// エラー処理
}
else
{
// 最後に終端記号の\0をつける
buffret = '\0';
}
送信時に\0を送っていない場合、\0をつけないとフフフフフとか出始めるので、\0を追加する
そのため、受信領域のサイズは -1 しておく
コーディング例 その2
文字列の送信 ※送信時に\0を送っていいるバージョン
code:socket.cpp
char buff1024; // 受信文字列の格納領域
~省略~
int ret = recv( sock, buff, sizeof(buff), 0 ); // こっちはstrlen()にしないこと!
if( ret == SOCKET_ERROR )
{
// エラー処理
}
\0まで送信されているので、そのまま利用可能
コーディング例 その3
数値の送信 ※実は重要な処理が抜けているのでこのまま使えない!
code:socket.cpp
int value; // 受信データの格納領域
~省略~
int ret = recv( sock, (char*)&value, sizeof(value), 0 );
if( ret == SOCKET_ERROR )
{
// エラー処理
}
文字列( char* )以外のデータを送りたいときはキャストするだけ
整数値でも構造体でも送信可能
BSD Socket
code:BSD.h
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
table:引数
sockfd 送信に使用するソケットのソケットディスクリプタ
buf 受信データの格納領域の先頭アドレス
len bufのサイズ
flags 基本的に0でOK
table:戻り値
成功 受信データのバイト数
失敗 -1
コーディング例は省略!
sendto()
用途
コネクション確立していないの状態でのデータ送信
その都度宛先を指定する必要がある
主にUDPで利用
定義
code:WinSock2.h
int WSAAPI sendto( in SOCKET s, in const char *buf, in int len,
in int flags, in const sockaddr *to, in int tolen )
table:引数
s 送信に使用するソケットのソケットディスクリプタ
buf 送信データの先頭アドレス
len 送信データのサイズ
flags 基本的に0でOK
to 宛先のソケットアドレス情報を格納した構造体の先頭アドレス
tolen toのサイズ
table:戻り値
成功 送信データのバイト数
失敗 SOCKET_ERROR
コーディング例
文字列の送信
これ以外のコーディング例は省略 send()をみよ!
code:socket.cpp
char buff1024; // 送信文字列の格納領域
~省略~
SOCKADDR_IN toAddr; // 宛先のソケットアドレス情報
memset( &toAddr, 0, sizeof(toAddr) );
toAddr.sin_family = AF_INET; // IPv4アドレス
toAddr.sin_port = htons( 10000 ); // サーバのポート番号
inet_pton( AF_INET, "192.168.43.253", &toAddr.sin_addr.s_addr); // サーバのIPアドレス
int ret = sendto( sock, buff, strlen(buff), 0, (SOCKADDR*)&toAddr, sizeof(toAddr) );
if( ret != strlen(buff) )
{
// エラー処理
}
BSD Socket
code:BSD.h
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
table:引数
sockfd 送信に使用するソケットのソケットディスクリプタ
buf 送信データの先頭アドレス
len 送信データのサイズ
flags 基本的に0でOK
dest_addr 宛先のソケットアドレス情報を格納した構造体の先頭アドレス
addrlen dest_addrのサイズ
table:戻り値
成功 送信データのバイト数
失敗 -1
コーディング例は省略!
recvfrom()
用途
コネクション確立していない状態でのデータ受信
UDPで利用
定義
code:WinSock2.h
int WSAAPI recvfrom( in SOCKET s, out char *buf, in int len,
in int flags, out sockaddr *from, in, out, optional int *fromlen )
table:引数
s 受信に使用するソケットのソケットディスクリプタ
buf 受信データの格納領域の先頭アドレス
len bufのサイズ
flags 基本的に0でOK
from 送信元のソケットアドレス情報を格納する領域の先頭アドレス
fromlen fromのサイズを格納した領域の先頭アドレス
table:戻り値
成功 受信データのバイト数
失敗 SOCKET_ERROR
コーディング例
文字列の受信
code:socket.cpp
char buff1024; // 受信文字列の格納領域
SOCKADDR_IN fromAddr; // 送信元ソケットアドレス情報を格納する領域
int fromlen = sizeof(fromAddr);
~省略~
int ret = recvfrom( sock, buff, sizeof(buff), 0, (SOCKADDR*)&fromAddr, &fromlen );
if( ret == SOCKET_ERROR )
{
// エラー処理
}
BSD Socket
code:BSD.h
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
table:引数
sockfd 送信に使用するソケットのソケットディスクリプタ
buf 受信データの格納領域の先頭アドレス
len bufのサイズ
flags 基本的に0でOK
src_addr 送信元のソケットアドレス情報を格納する構造体の先頭アドレス
addrlen src_addrのサイズを格納した領域の先頭アドレス
table:戻り値
成功 受信データのバイト数
失敗 -1
コーディング例は省略!
inet_pton()
用途
文字列形式のIPアドレスをコンピュータが使用する数値型のIPアドレスに変換
IPv4、IPv6に対応
バイトオーダーの変換も同時に行う
定義
code:WinSock2.h
INT WSAAPI inet_pton( in INT Family, in PCSTR pszAddrString, out PVOID pAddrBuf )
table:引数
Family アドレスファミリ
IPv4 : AF_INET
IPv6 : AF_INET6
pszAddrString 文字列型のIPアドレス
pAddrBuf 変換後のアドレスを格納する領域の先頭アドレス
table:戻り値
成功 1
失敗 0か-1
0 : 文字列型のIPアドレスの形式が間違っている
-1 : 上記以外のエラー
コーディング例
code:Winsock.cpp
// サーバのIPアドレス192.168.42.253、ポート番号8080の場合
SOCKADDR_IN toAddr;
memset( &toAddr, 0, sizeof( toAddr ) );
toAddr.sin_family = AF_INET;
toAddr.sin_port = htons( 8080 );
inet_pton( AF_INET, "192.168.42.253", &toAddr.sin_addr.s_addr );
BSD Socket
code:BSD.h
int inet_pton(int af, const char *src, void *dst);
table:引数
af アドレスファミリ
IPv4 : AF_INET
IPv6 : AF_INET6
src 文字列型のIPアドレス
dst 変換後のアドレスを格納する領域の先頭アドレス
table:戻り値
成功 1
失敗 0か-1
0 : 文字列型のIPアドレスの形式が間違っている
-1 : 上記以外のエラー
WSAGetLastError()
用途
WinSockの直近のエラーコードの取得
ここまで扱ってきたWinSock APIの関数がらみでエラーがでたら、この関数を呼び出してエラー原因を探る
定義
code:WinSock.h
int WSAAPI WSAGetLastError()
table:引数
なし
table:戻り値
エラーコード
エラーコード
https://docs.microsoft.com/ja-jp/windows/win32/winsock/windows-sockets-error-codes-2
BSD Socket
ない ※WSAだもの
バイトオーダー変換用関数
ホストバイトオーダー => ネットワークバイトオーダー
hton■:■の部分にはデータ型の省略形( っぽいアルファベット )が入る
htons:2バイトの整数値を変換 s:short
htonl:4バイトの整数値を変換 l:long
ネットワークバイトオーダー => ホストバイトオーダー
ntoh■:■の部分にはデータ型の省略形( っぽいアルファベット )が入る
ntohs:2バイトの整数値を変換 s:short
ntohl:4バイトの整数値を変換 l:long
n:network・h:hostの略
ノンブロッキングモード用関数
ioctlsocket()
用途
ソケットのI/Oモードを制御
ソケットをノンブロッキングモードにする際に使用
定義
code:WinSock2.h
int ioctlsocket( in SOCKET s, in long cmd, in, out u_long *argp );
table:引数
s ノンブロッキングモードにしたいソケットのソケットディスクリプタ
cmd 制御するためのコマンド
ノンブロッキングにしたい場合はFIONBIO
argp cmdのパラメータのポインタ
ノンブロッキングにしたい場合は0以外をいれた領域の先頭アドレス
table:戻り値
成功 0
失敗 SOCKET_ERROR
コーディング例
文字列の受信
code:socket.cpp
// ソケットsockをノンブロッキングソケットにする
unsigned long cmdarg = 0x01;
int ret = ioctlsocket( sock, FIONBIO, &cmdarg );
if( ret == SOCKET_ERROR )
{
// エラー処理
}
BSD Socket
code:BSD.h
int ioctl(int fd, unsigned int cmd, char *argp );
table:引数
fd ノンブロッキングモードにしたいソケットのソケットディスクリプタ
cmd 制御するためのコマンド
ノンブロッキングにしたい場合はFIONBIO
argp cmdに引数が必要な場合記述
ノンブロッキングにしたい場合は0以外をいれた領域の先頭アドレス
table:戻り値
成功 0
失敗 -1
コーディング例はWinSockのioctlsocket()とほぼ変わらないので省略
#ネットワーク関係
#ネットワークプログラミング