sock


※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

ソケットメモ

クライアント・サーバ間でデータをやりとりする仕組み。
HTTPなどの高級な通信しか触ったことがないので、やってみる。

soketことのはじめ。

1、ソケットの作成をOSに頼む
int socket(int protocolFamily,int type,int protocol)
戻り値はソケットを表すディスクリプタ(=id,固有値)。

2、終了時にはソケットを閉じる、閉じるまでは同一ポートで通信。
int close(int socket)
さっきのディスクリプタを入れればOK

3、sockaddrはソケットに関連づけられたアドレス
struct sockaddr{
  unsigned short sa_family; //アドレスファミリ
  char sa_data[14];         //アドレス情報
};
メモ:書いててIPv6がちょっと気になる。

4、sockaddrをTCP/IPのソケットアドレスに特化させたものがsockaddr_in
struct sockaddr_in{
  unsigned short sin_family; //アドレスファミリ
  unsigned short sin_port;   //ポート
  struct in_addr sin_addr;   //IPアドレス
  char sin_zero[8];          //未使用
};
struct in_addr{
  unsigned long s_addr;     //in_addrの中身
};

sockaddrをカッチリ割ったのがsockaddr_inになってる。

TCPクライアント

1、サーバと一緒でTCPソケットをsocket関数で作る。
2、connect関数を使って接続を確立する
int connect(int socket,struct sockaddr *foregnAddress,unsigned int addressLength)
第一引数のハンドルのソケットを使ってsockaddrで記されたサーバと接続を確立する。
addressLengthにはsockaddr_inのサイズ、sizeof(sockaddr_in)を指定。

3、send,recv関数でデータをやりとりする
int send(int socket,const void *msg,unsigned int msgLength,int flag)
int recv(int socket,void *rcvBuffer,unsigned int bufferLength,int flag)

接続を確立したならばsend,recvで通信を行うことができるようになる。
flagによってメッセージが返ってくるのを待機したりできる。

4、closeを使って接続を閉じる

TCPサーバ

1、socket関数でソケット作成
2、bind関数でポートを割り当てる
int bind(int socket,struct sockaddr *localAddress,unsigned int addressLength)
第二引数はsockaddrのポインタを渡す。第三引数はsizeof(sockaddr_in)で渡す事をわすれずに。

3、listen()関数を利用して待機
int listen(int socket,int queueLimit)
queueLimitでは接続要求を同時にいくつまでlistenするかの引数を入れるらしい、
環境によって引数の意味が異なる。通常は5を入れておくみたい。

4、accept関数を使って接続を許可、ソケットを取得。
int accept(int socket,struct sockaddr *clientAddress,unsigned int *addressLength)
戻り値としてクライアントソケットのディスクリプタ(descriptor=記述詞…印でおk?w)を返してくれます。

TCPは今のところ使わないのでサンプルコードなし。あとで。
sockaddr_inの意味がわかった。

データのエンコードについても略。
エンディアン違いの回避とか。

ではUDP。

accept無しでデータを受理可能。

udpサーバ

1、ソケットを作る
2、ローカルアドレス、任意のポートでbindする
3、recvfrom関数を使い、クライアントからメッセージが来るまでブロック
int recvfrom(int socket,void *msg,unsigned int msgLength,struct sockaddr *srcAddr,unsigned int addrLen)
今までは戻り値にdescriptorが返ってきていたのが、srcAddrにsockaddrのポインタを指定することで、
アドレスデータが直接分かるようになっています。この得られたアドレスポート情報を元にデータを送り返してやります。

4、sendto関数を使い、送り返す
int sendto(int socket,const void *msg,unsigned int msgLength,int flag,struct sockaddr *destAddr,unsigned int addrLen)
recvの逆で、destAddrには送りつけたいIPアドレス・ポートが記されている構造体のアドレスを指定。

UDPクライアント

1、ソケットを作る
2、sendto関数を使いメッセージを送る
3、recvfrom関数を使い、メッセージを待つ
4、終わる時はclose(socket);

わかったこと

  • UDPの通信では通信路を確立する必要がないのでデータの送信にアドレス・ポートを指定する必要がある
  • sockaddr_inの意味


参考

著:Michael J.Donahoo,Kenneth L.Calvert TCP/IP ソケットプログラミング C言語編