Unixソケット-コア機能

この章では、完全なTCPクライアントとサーバーを作成するために必要なコアソケット機能について説明します。

次の図は、クライアントとサーバーの完全な相互作用を示しています-

ソケット機能

ネットワークI / Oを実行するには、プロセスが最初に実行する必要があるのは、ソケット関数を呼び出し、必要な通信プロトコルのタイプやプロトコルファミリなどを指定することです。

#include <sys/types.h>
#include <sys/socket.h>

int socket (int family, int type, int protocol);

この呼び出しは、後のシステムコールで使用できるソケット記述子を返します。エラーの場合は-1を返します。

パラメーター

family −プロトコルファミリを指定し、以下に示す定数の1つです。

家族 説明
AF_INET IPv4プロトコル
AF_INET6 IPv6プロトコル
AF_LOCAL Unixドメインプロトコル
AF_ROUTE ルーティングソケット
AF_KEY ケットソケット

この章では、IPv4以外の他のプロトコルについては説明しません。

type−必要なソケットの種類を指定します。次のいずれかの値を取ることができます-

タイプ 説明
SOCK_STREAM ストリームソケット
SOCK_DGRAM データグラムソケット
SOCK_SEQPACKET シーケンスされたパケットソケット
SOCK_RAW 生のソケット

protocol −引数は、以下に示す特定のプロトコルタイプに設定するか、0を設定して、ファミリとタイプの特定の組み合わせに対するシステムのデフォルトを選択する必要があります。

プロトコル 説明
IPPROTO_TCP TCPトランスポートプロトコル
IPPROTO_UDP UDPトランスポートプロトコル
IPPROTO_SCTP SCTPトランスポートプロトコル

接続機能

接続機能は、TCPサーバとの接続を確立するためにTCPクライアントによって使用されます。

#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);

この呼び出しは、サーバーに正常に接続した場合は0を返し、それ以外の場合はエラー時に-1を返します。

パラメーター

  • sockfd −ソケット関数から返されるソケット記述子です。

  • serv_addr −宛先IPアドレスとポートを含むstructsockaddrへのポインタです。

  • addrlen − sizeof(struct sockaddr)に設定します。

バインド機能

バインド機能はソケットにローカルプロトコルアドレスを割り当てます。インターネットプロトコルの場合、プロトコルアドレスは、32ビットのIPv4アドレスまたは128ビットのIPv6アドレスと、16ビットのTCPまたはUDPポート番号の組み合わせです。この関数は、TCPサーバーによってのみ呼び出されます。

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, struct sockaddr *my_addr,int addrlen);

この呼び出しは、アドレスに正常にバインドされた場合は0を返し、それ以外の場合はエラー時に-1を返します。

パラメーター

  • sockfd −ソケット関数から返されるソケット記述子です。

  • my_addr −ローカルIPアドレスとポートを含むstructsockaddrへのポインタです。

  • addrlen − sizeof(struct sockaddr)に設定します。

IPアドレスとポートを自動的に入力できます

ポート番号の値が0の場合は、システムがランダムなポートを選択することを意味し、IPアドレスのINADDR_ANY値は、サーバーのIPアドレスが自動的に割り当てられることを意味します。

server.sin_port = 0;  		     
server.sin_addr.s_addr = INADDR_ANY;

NOTE−1024未満のすべてのポートが予約されています。他のプログラムで使用されているポートでない限り、1024より上および65535より下のポートを設定できます。

聞く機能

聞く機能だけTCPサーバによって呼び出されると、それは2つのアクションを実行-

  • リッスン機能は、接続されていないソケットをパッシブソケットに変換し、カーネルがこのソケットに向けられた着信接続要求を受け入れる必要があることを示します。

  • この関数の2番目の引数は、カーネルがこのソケットのためにキューに入れる必要がある接続の最大数を指定します。

#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd,int backlog);

この呼び出しは、成功した場合は0を返し、それ以外の場合はエラーの場合は-1を返します。

パラメーター

  • sockfd −ソケット関数から返されるソケット記述子です。

  • backlog −許可されている接続の数です。

受け入れる機能

受け入れる機能が完了し、接続キューの先頭から次の接続完了を返すために、TCPサーバによって呼び出されます。呼び出しの署名は次のとおりです-

#include <sys/types.h>
#include <sys/socket.h>

int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

この呼び出しは、成功した場合は負でない記述子を返します。それ以外の場合は、エラーの場合は-1を返します。返される記述子はクライアントソケット記述子であると見なされ、すべての読み取り/書き込み操作はこの記述子で実行されてクライアントと通信します。

パラメーター

  • sockfd −ソケット関数から返されるソケット記述子です。

  • cliaddr −クライアントのIPアドレスとポートを含むstructsockaddrへのポインタです。

  • addrlen − sizeof(struct sockaddr)に設定します。

送信機能

送信機能は、ストリームソケットまたはCONNECTEDデータグラムソケットを介してデータを送信するために使用されます。UNCONNECTEDデータグラムソケットを介してデータを送信する場合は、sendto()関数を使用する必要があります。

write()システムコールを使用してデータを送信できます。その署名は次のとおりです-

int send(int sockfd, const void *msg, int len, int flags);

この呼び出しは、送信されたバイト数を返します。それ以外の場合は、エラー時に-1を返します。

パラメーター

  • sockfd −ソケット関数から返されるソケット記述子です。

  • msg −送信したいデータへのポインタです。

  • len −送信するデータの長さ(バイト単位)です。

  • flags −0に設定されます。

recv関数

recv関数は、ストリームソケットまたは接続されたデータグラムソケットを介してデータを受信するために使用されます。UNCONNECTEDデータグラムソケットを介してデータを受信する場合は、recvfrom()を使用する必要があります。

read()システムコールを使用してデータを読み取ることができます。この呼び出しは、ヘルパー関数の章で説明されています。

int recv(int sockfd, void *buf, int len, unsigned int flags);

この呼び出しは、バッファに読み込まれたバイト数を返します。それ以外の場合は、エラー時に-1を返します。

パラメーター

  • sockfd −ソケット関数から返されるソケット記述子です。

  • buf −情報を読み込むためのバッファです。

  • len −バッファの最大長です。

  • flags −0に設定されます。

sendto関数

sendto関数はUNCONNECTEDデータグラムソケットを介してデータを送信するために使用されます。その署名は次のとおりです-

int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);

この呼び出しは、送信されたバイト数を返します。それ以外の場合は、エラー時に-1を返します。

パラメーター

  • sockfd −ソケット関数から返されるソケット記述子です。

  • msg −送信したいデータへのポインタです。

  • len −送信するデータの長さ(バイト単位)です。

  • flags −0に設定されます。

  • to −データを送信する必要のあるホストのstructsockaddrへのポインタです。

  • tolen − sizeof(struct sockaddr)に設定されます。

recvfromの機能

recvfromの機能は未接続データグラムソケットからデータを受信するために使用されます。

int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);

この呼び出しは、バッファに読み込まれたバイト数を返します。それ以外の場合は、エラー時に-1を返します。

パラメーター

  • sockfd −ソケット関数から返されるソケット記述子です。

  • buf −情報を読み込むためのバッファです。

  • len −バッファの最大長です。

  • flags −0に設定されます。

  • from −データを読み取る必要のあるホストのstructsockaddrへのポインタです。

  • fromlen − sizeof(struct sockaddr)に設定されます。

クローズ機能

クローズ機能は、クライアントとサーバ間の通信を閉じるために使用されます。その構文は次のとおりです-

int close( int sockfd );

この呼び出しは、成功した場合は0を返し、それ以外の場合はエラーの場合は-1を返します。

パラメーター

  • sockfd −ソケット関数から返されるソケット記述子です。

シャットダウン機能

シャットダウン機能は、優雅に、クライアントとサーバ間の通信を閉じるために使用されます。この関数は、閉じる関数と比較してより詳細な制御を提供します。以下にシャットダウンの構文を示します-

int shutdown(int sockfd, int how);

この呼び出しは、成功した場合は0を返し、それ以外の場合はエラーの場合は-1を返します。

パラメーター

  • sockfd −ソケット関数から返されるソケット記述子です。

  • how −数字の1つを入れてください−

    • 0 −受信が許可されていないことを示します。

    • 1 −送信が許可されていないことを示し、

    • 2−送信と受信の両方が許可されていないことを示します。howが2に設定されている場合、close()と同じです。

選択機能

選択機能は、書き込み用、読み取りのための準備ができて準備ができている、または保留中のエラー状態を持つ、指定されたファイルディスクリプタのかを示します。

アプリケーションがrecvまたはrecvfromを呼び出すと、そのソケットにデータが到着するまでブロックされます。着信データストリームが空のときに、アプリケーションが他の有用な処理を実行している可能性があります。もう1つの状況は、アプリケーションが複数のソケットからデータを受信する場合です。

入力キューにデータがないソケットでrecvまたはrecvfromを呼び出すと、他のソケットからのデータの即時受信が妨げられます。select関数呼び出しは、プログラムがすべてのソケットハンドルをポーリングして、それらが非ブロッキングの読み取りおよび書き込み操作に使用できるかどうかを確認できるようにすることで、この問題を解決します。

以下に、select −の構文を示します。

int select(int  nfds, fd_set  *readfds, fd_set  *writefds, fd_set *errorfds, struct timeval *timeout);

この呼び出しは、成功した場合は0を返し、それ以外の場合はエラーの場合は-1を返します。

パラメーター

  • nfds−テストするファイル記述子の範囲を指定します。select()関数は、0からnfds-1の範囲のファイル記述子をテストします

  • readfds−入力時に読み取り準備ができているかどうかをチェックするファイル記述子を指定し、出力時にどのファイル記述子を読み取る準備ができているかを示すタイプfd_setのオブジェクトを指します。空のセットを示す場合はNULLにすることができます。

  • writefds−入力時に書き込み準備ができているかどうかをチェックするファイル記述子を指定し、出力時に書き込み準備ができているファイル記述子を示すタイプfd_setのオブジェクトを指します。空のセットを示す場合はNULLにすることができます。

  • exceptfds−入力時に、保留中のエラー条件をチェックするファイル記述子を指定し、出力時に、保留中のエラー条件を持つファイル記述子を示すタイプfd_setのオブジェクトを指します。空のセットを示す場合はNULLにすることができます。

  • timeout−使用可能なI / O操作についてselect呼び出しが記述子をポーリングする時間を指定するtimeval構造体を指します。タイムアウト値が0の場合、selectはすぐに戻ります。タイムアウト引数がNULLの場合、selectは、少なくとも1つのファイル/ソケットハンドルが使用可能なI / O操作の準備ができるまでブロックします。それ以外の場合、selectは、タイムアウトの時間が経過した後、または少なくとも1つのファイル/ソケット記述子がI / O操作の準備ができたときに戻ります。

selectからの戻り値は、I / Oの準備ができているファイル記述子セットで指定されたハンドルの数です。タイムアウトフィールドで指定された制限時間に達した場合は、return 0を選択します。ファイル記述子セットを操作するために、次のマクロが存在します。

  • FD_CLR(fd, &fdset)−ファイル記述子セットfdset内のファイル記述子fdのビットをクリアします

  • FD_ISSET(fd, &fdset)−ファイル記述子fdのビットがfdsetが指すファイル記述子セットに設定されている場合はゼロ以外の値を返し、それ以外の場合は0を返します。

  • FD_SET(fd, &fdset) −ファイル記述子セットfdsetのファイル記述子fdのビットを設定します。

  • FD_ZERO(&fdset) −ファイル記述子セットfdsetを初期化して、すべてのファイル記述子に対してゼロビットを使用します。

fd引数が0未満、またはFD_SETSIZE以上の場合、これらのマクロの動作は定義されていません。

fd_set fds;

struct timeval tv;

/* do socket initialization etc.
tv.tv_sec = 1;
tv.tv_usec = 500000;

/* tv now represents 1.5 seconds */
FD_ZERO(&fds);

/* adds sock to the file descriptor set */
FD_SET(sock, &fds); 

/* wait 1.5 seconds for any data to be read from any single socket */
select(sock+1, &fds, NULL, NULL, &tv);

if (FD_ISSET(sock, &fds)) {
   recvfrom(s, buffer, buffer_len, 0, &sa, &sa_len);
   /* do something */
}
else {
   /* do something else */
}