Unix-sockets-quick-guide

提供:Dev Guides
移動先:案内検索

ソケットとは何ですか?

ソケットは、同じマシンまたは異なるマシン上の2つの異なるプロセス間の通信を可能にします。 より正確には、標準のUnixファイル記述子を使用して他のコンピューターと通信する方法です。 Unixでは、すべてのI/Oアクションはファイル記述子の書き込みまたは読み取りによって行われます。 ファイル記述子は、開いているファイルに関連付けられた単なる整数であり、ネットワーク接続、テキストファイル、端末、またはその他のものです。

プログラマーにとって、ソケットは低レベルのファイル記述子のように見え、動作します。 これは、read()やwrite()などのコマンドが、ファイルやパイプの場合と同じようにソケットで機能するためです。

ソケットは最初に2.1BSDで導入され、その後4.2BSDで現在の形式に改良されました。 ソケット機能は、現在のほとんどのUNIXシステムリリースで使用できるようになりました。

ソケットはどこで使用されますか?

Unix-Socketは、クライアント/サーバーアプリケーションフレームワークで使用されます。 サーバーは、クライアントからの要求に応じていくつかの機能を実行するプロセスです。 FTP、SMTP、POP3などのアプリケーションレベルのプロトコルのほとんどは、ソケットを使用してクライアントとサーバー間の接続を確立し、データを交換します。

ソケットの種類

ユーザーが使用できるソケットには4つのタイプがあります。 最初の2つは最も一般的に使用され、最後の2つはほとんど使用されません。

プロセスは同じタイプのソケット間でのみ通信すると想定されていますが、異なるタイプのソケット間の通信を妨げる制限はありません。

  • ストリームソケット-ネットワーク環境での配信が保証されています。 ストリームソケットを介して3つの項目「A、B、C」を送信すると、それらは同じ順序で到着します-「A、B、C」。 これらのソケットは、データ送信にTCP(Transmission Control Protocol)を使用します。 配信が不可能な場合、送信者はエラーインジケータを受け取ります。 データレコードには境界がありません。
  • データグラムソケット-ネットワーク環境での配信は保証されていません。 Stream Socketsのように接続を開く必要がないため、コネクションレスです。宛先情報を使用してパケットを作成し、送信します。 UDP(ユーザーデータグラムプロトコル)を使用します。
  • Raw Sockets -これらは、ソケット抽象化をサポートする基礎となる通信プロトコルへのアクセスをユーザーに提供します。 これらのソケットは通常、データグラム指向ですが、その正確な特性はプロトコルによって提供されるインターフェースに依存します。 生のソケットは一般ユーザー向けではありません。それらは主に、新しい通信プロトコルの開発に関心のある人、または既存のプロトコルのより不可解な機能へのアクセスを得るために提供されています。
  • シーケンスパケットソケット-レコード境界が保持されることを除いて、ストリームソケットに似ています。 このインターフェイスは、ネットワークシステム(NS)ソケット抽象化の一部としてのみ提供されており、最も深刻なNSアプリケーションでは非常に重要です。 シーケンスパケットソケットを使用すると、ユーザーは、送信するデータとともにプロトタイプヘッダーを記述するか、またはすべての発信データで使用されるデフォルトヘッダーを指定し、ユーザーが着信パケットでヘッダーを受信できるようにします。

次は何ですか?

次のいくつかの章は、_socket_を使用してサーバーおよびクライアントプログラムを作成する前に、基本を強化し、基盤を準備することを目的としています。 直接ジャンプしてクライアントおよびサーバープログラムの作成方法を確認する場合は、作成できますが、お勧めしません。 プログラミングを行う前に、一歩一歩進んでこれらの最初のいくつかの章を完了してベースを作ることを強くお勧めします。

Unixソケット-ネットワークアドレス

実際に作業を進める前に、ネットワークアドレス(IPアドレス)について少し説明しましょう。

IPホストアドレス、またはより一般的には単にIPアドレスは、インターネットに接続されているホストを識別するために使用されます。 IPはインターネットプロトコルの略で、インターネットのネットワークアーキテクチャ全体のインターネット層を指します。

IPアドレスは、4つの8ビット数またはオクテットとして解釈される32ビットの量です。 各IPアドレスは、参加しているユーザーネットワーク、ネットワーク上のホスト、およびユーザーネットワークのクラスを一意に識別します。

IPアドレスは通常、N1.N2.N3.N4の形式のドット付き10進表記で記述されます。各Niは、0〜255の10進数(00〜FF 16進数)です。

アドレスクラス

IPアドレスは、Internet Assigned Numbers Authority(IANA)によって管理および作成されます。 5つの異なるアドレスクラスがあります。 IPアドレスの最初の4ビットを調べることにより、IPアドレスがどのクラスにあるかを判別できます。

  • クラスA *アドレスは、 *0xxx 、または 1〜126 10進数で始まります。

  • クラスB *アドレスは、 *10xx または 128〜191 10進数で始まります。

  • クラスC *アドレスは、 *110x 、または 192から223 10進数で始まります。

  • クラスD *アドレスは、 *1110 、または 224から239 10進数で始まります。

  • クラスE *アドレスは、 *1111 、または10進数の 240から254 で始まります。

    *01111111* または *127* 10進数で始まるアドレスは、ループバックおよびローカルマシンでの内部テスト用に予約されています[これをテストできます:常に *127.0.0.1* をpingできる必要があります。クラスDアドレスは、マルチキャスト用に予約されています。クラスEアドレスは、将来の使用のために予約されています。 ホストアドレスには使用しないでください。

Class Leftmost bits Start address Finish address
A 0xxx 0.0.0.0 127.255.255.255
B 10xx 128.0.0.0 191.255.255.255
C 110x 192.0.0.0 223.255.255.255
D 1110 224.0.0.0 239.255.255.255
E 1111 240.0.0.0 255.255.255.255

サブネット化

サブネット化またはサブネットワーク化は、基本的にネットワークから分岐することを意味します。 これは、組織内のネットワーク、異なる物理メディア(イーサネット、FDDI、WANなど)の使用、アドレススペースの保存、セキュリティなど、さまざまな理由で実行できます。 最も一般的な理由は、ネットワークトラフィックを制御することです。

サブネット化の基本的な考え方は、IPアドレスのホスト識別子部分を2つの部分に分割することです-

  • ネットワークアドレス自体内のサブネットアドレス。そして
  • サブネット上のホストアドレス。

たとえば、一般的なクラスBアドレス形式はN1.N2.S.Hです。N1.N2はクラスBネットワークを識別し、8ビットのSフィールドはサブネットを識別し、8ビットのHフィールドはサブネット上のホストを識別します。

Unixソケット-ネットワークホスト名

数字で表すホスト名は覚えにくいため、TakshilaやNalandaなどの一般的な名前で呼ばれます。 特定の名前に対応するドット付きIPアドレスを見つけるソフトウェアアプリケーションを作成します。

指定された英数字のホスト名に基づいてドット付きIPアドレスを見つけるプロセスは、*ホスト名解決*と呼ばれます。

ホスト名の解決は、大容量システムにある特別なソフトウェアによって行われます。 これらのシステムはドメインネームシステム(DNS)と呼ばれ、IPアドレスと対応する通常名のマッピングを保持します。

===/etc/hostsファイル

ホスト名とIPアドレスの対応は、hosts_というファイルで維持されます。 ほとんどのシステムでは、このファイルは '/etc_ ディレクトリにあります。

このファイルのエントリは次のようになります-

# This represents a comments in/etc/hosts file.
127.0.0.1       localhost
192.217.44.207  nalanda metro
153.110.31.18   netserve
153.110.31.19   mainserver centeral
153.110.31.20   samsonite
64.202.167.10   ns3.secureserver.net
64.202.167.97   ns4.secureserver.net
66.249.89.104   www.google.com
68.178.157.132  services.amrood.com

複数の名前が特定のIPアドレスに関連付けられる場合があることに注意してください。 このファイルは、IPアドレスからホスト名へ、またはその逆に変換するときに使用されます。

このファイルを編集するためのアクセス権がないため、ホスト名とIPアドレスを入力する場合は、root権限が必要です。

Unixソケット-クライアントサーバーモデル

ほとんどのネットアプリケーションはクライアントサーバーアーキテクチャを使用します。これは、相互に通信して情報を交換する2つのプロセスまたは2つのアプリケーションを指します。 2つのプロセスの1つはクライアントプロセスとして機能し、別のプロセスはサーバーとして機能します。

クライアントプロセス

これはプロセスであり、通常は情報を要求します。 応答を取得した後、このプロセスは終了するか、他の処理を行う場合があります。

、インターネットブラウザーはクライアントアプリケーションとして動作し、Webサーバーに要求を送信して1つのHTML Webページを取得します。

サーバープロセス

これは、クライアントからリクエストを受け取るプロセスです。 クライアントから要求を取得した後、このプロセスは必要な処理を実行し、要求された情報を収集して、リクエスタークライアントに送信します。 完了すると、別のクライアントにサービスを提供する準備が整います。 サーバープロセスは常に警告を発し、着信要求を処理する準備ができています。

-Webサーバーは、インターネットブラウザーからの要求を待機し続け、ブラウザーから要求を受け取るとすぐに、要求されたHTMLページを取得し、そのブラウザーに送り返します。

クライアントはサーバーのアドレスを知る必要がありますが、サーバーは接続が確立される前にアドレスやクライアントの存在を知る必要がないことに注意してください。 接続が確立されると、両側で情報を送受信できます。

2層および3層のアーキテクチャ

クライアントサーバーアーキテクチャには2種類あります-

  • * 2層アーキテクチャ*-このアーキテクチャでは、クライアントはサーバーと直接対話します。 このタイプのアーキテクチャには、いくつかのセキュリティホールとパフォーマンスの問題があります。 Internet ExplorerとWebサーバーは2層アーキテクチャで動作します。 ここで、セキュリティ問題はSecure Socket Layer(SSL)を使用して解決されます。
  • * 3層アーキテクチャ*-このアーキテクチャでは、もう1つのソフトウェアがクライアントとサーバーの間に配置されます。 このミドルソフトウェアは「ミドルウェア」と呼ばれます。 ミドルウェアは、負荷が大きい場合にすべてのセキュリティチェックと負荷分散を実行するために使用されます。 ミドルウェアはクライアントからのすべてのリクエストを受け取り、必要な認証を実行した後、そのリクエストをサーバーに渡します。 その後、サーバーは必要な処理を行い、応答をミドルウェアに送り返し、最後にミドルウェアはこの応答をクライアントに返します。 3層アーキテクチャを実装する場合、WebサーバーとWebブラウザの間にWeb LogicやWebSphereソフトウェアなどのミドルウェアを保持できます。

サーバーの種類

あなたが持つことができるサーバーの2種類があります-

  • 反復サーバー-これは、サーバープロセスが1つのクライアントにサービスを提供し、最初の要求を完了した後、別のクライアントから要求を受け取る最も単純な形式のサーバーです。 その間、別のクライアントが待機し続けます。
  • 同時サーバー-このタイプのサーバーは複数の同時プロセスを実行して、一度に多くの要求を処理します。これは、1つのプロセスに時間がかかり、別のクライアントがそれほど長く待機できないためです。 Unixで並行サーバーを記述する最も簡単な方法は、各クライアントを個別に処理する子プロセスを_fork_することです。

クライアントの作り方

接続を確立するためのシステムコールは、クライアントとサーバーで多少異なりますが、両方ともソケットの基本的な構成を伴います。 両方のプロセスが独自のソケットを確立します。

クライアント側でソケットを確立する際の手順は次のとおりです-

  • * socket()*システムコールでソケットを作成します。
  • * connect()*システムコールを使用して、ソケットをサーバーのアドレスに接続します。
  • データを送受信します。 これを行うにはいくつかの方法がありますが、最も簡単な方法は* read()および write()*システムコールを使用することです。

サーバーの作り方

サーバー側でソケットを確立する際の手順は次のとおりです-

  • * socket()*システムコールでソケットを作成します。
  • * bind()*システムコールを使用して、ソケットをアドレスにバインドします。 インターネット上のサーバーソケットの場合、アドレスはホストマシンのポート番号で構成されます。
  • * listen()*システムコールとの接続をリッスンします。
  • * accept()*システムコールで接続を受け入れます。 通常、この呼び出しは、クライアントがサーバーに接続するまで接続をブロックします。
  • * read()および write()*システムコールを使用してデータを送受信します。

クライアントとサーバーの相互作用

以下は、クライアントとサーバーの完全な相互作用を示す図です-

ソケットクライアントサーバー

Unixソケット-構造

Unixソケットプログラミングでは、アドレスとポートに関する情報、およびその他の情報を保持するためにさまざまな構造が使用されます。 ほとんどのソケット関数では、引数としてソケットアドレス構造体へのポインターが必要です。 この章で定義されている構造は、インターネットプロトコルファミリに関連しています。

sockaddr

最初の構造は、ソケット情報を保持する_sockaddr_です-

struct sockaddr {
   unsigned short   sa_family;
   char             sa_data[14];
};

これは、ほとんどのソケット関数呼び出しで渡される汎用ソケットアドレス構造です。 次の表は、メンバーフィールドの説明を提供します-

Attribute Values Description
sa_family

AF_INET

AF_UNIX

AF_NS

AF_IMPLINK

It represents an address family. In most of the Internet-based applications, we use AF_INET.
sa_data Protocol-specific Address The content of the 14 bytes of protocol specific address are interpreted according to the type of address. For the Internet family, we will use port number IP address, which is represented by sockaddr_in structure defined below.

sockaddr in

ソケットの要素を参照するのに役立つ2番目の構造は次のとおりです-

struct sockaddr_in {
   short int            sin_family;
   unsigned short int   sin_port;
   struct in_addr       sin_addr;
   unsigned char        sin_zero[8];
};

ここにメンバーフィールドの説明があります-

Attribute Values Description
sa_family

AF_INET

AF_UNIX

AF_NS

AF_IMPLINK

It represents an address family. In most of the Internet-based applications, we use AF_INET.
sin_port Service Port A 16-bit port number in Network Byte Order.
sin_addr IP Address A 32-bit IP address in Network Byte Order.
sin_zero Not Used You just set this value to NULL as this is not being used.

addrに

この構造は、構造フィールドとして上記の構造でのみ使用され、32ビットのnetid/hostidを保持します。

struct in_addr {
   unsigned long s_addr;
};

ここにメンバーフィールドの説明があります-

Attribute Values Description
s_addr service port A 32-bit IP address in Network Byte Order.

司会者

この構造は、ホストに関連する情報を保持するために使用されます。

struct hostent {
   char *h_name;
   char **h_aliases;
   int h_addrtype;
   int h_length;
   char **h_addr_list

#define h_addr  h_addr_list[0]
};

ここにメンバーフィールドの説明があります-

Attribute Values Description
h_name ti.com etc. It is the official name of the host. For example, finddevguides.com, google.com, etc.
h_aliases TI It holds a list of host name aliases.
h_addrtype AF_INET It contains the address family and in case of Internet based application, it will always be AF_INET.
h_length 4 It holds the length of the IP address, which is 4 for Internet Address.
h_addr_list in_addr For Internet addresses, the array of pointers h_addr_list[0], h_addr_list[1], and so on, are points to structure in_addr.

-h_addrは、下位互換性を保つためにh_addr_list [0]として定義されています。

奉仕者

この特定の構造は、サービスおよび関連するポートに関連する情報を保持するために使用されます。

struct servent {
   char  *s_name;
   char  **s_aliases;
   int   s_port;
   char  *s_proto;
};

ここにメンバーフィールドの説明があります-

Attribute Values Description
s_name http This is the official name of the service. For example, SMTP, FTP POP3, etc.
s_aliases ALIAS It holds the list of service aliases. Most of the time this will be set to NULL.
s_port 80 It will have associated port number. For example, for HTTP, this will be 80.
s_proto

TCP

UDP

It is set to the protocol used. Internet services are provided using either TCP or UDP.

ソケット構造に関するヒント

ソケットアドレス構造は、すべてのネットワークプログラムの不可欠な部分です。 それらを割り当て、記入し、それらへのポインターをさまざまなソケット関数に渡します。 時々、これらの構造の1つへのポインターをソケット関数に渡して、内容を埋めます。

常に参照によってこれらの構造体を渡します(つまり、構造体自体ではなく構造体へのポインターを渡します)。また、常に構造体のサイズを別の引数として渡します。

ソケット関数が構造体を埋めると、その長さも参照によって渡されるため、その値は関数によって更新できます。 これらの値と結果の引数を呼び出します。

常に、bzero()関数にmemset()を使用して、構造変数をNULL(つまり、「\ 0」)に設定します。そうしないと、構造内に予期しないジャンク値を取得する可能性があります。

Unixソケット-ポートとサービス

クライアントプロセスがサーバーに接続する場合、クライアントは接続するサーバーを識別する方法を持っている必要があります。 クライアントは、サーバーが存在するホストの32ビットインターネットアドレスを知っている場合、そのホストに接続できます。 しかし、クライアントはそのホストで実行されている特定のサーバープロセスをどのように識別しますか?

ホストで実行されている特定のサーバープロセスを識別する問題を解決するために、TCPとUDPの両方が既知のポートのグループを定義しています。

この目的のために、ポートは1024〜65535の整数として定義されます。 これは、1024より小さいすべてのポート番号が「よく知られている」と見なされるためです。たとえば、telnetはポート23を使用し、httpは80を使用し、ftpは21を使用します。

ネットワークサービスへのポートの割り当ては、/etc/servicesファイルにあります。 独自のサーバーを作成している場合は、サーバーにポートを割り当てるように注意する必要があります。 このポートを他のサーバーに割り当てないようにしてください。

通常、5000を超えるポート番号を割り当てることが慣例です。 しかし、ポート番号が5000を超えるサーバーを記述した組織は数多くあります。 たとえば、Yahoo Messengerは5050で実行され、SIP Serverは5060で実行されます。

ポートとサービスの例

以下は、サービスと関連ポートの小さなリストです。 インターネットポートと関連サービスの最新のリストは、http://www.iana.org/assignments/port-numbers [IANA-TCP/IP Port Assignments]で見つけることができます。

Service Port Number Service Description
echo 7 UDP/TCP sends back what it receives.
discard 9 UDP/TCP throws away input.
daytime 13 UDP/TCP returns ASCII time.
chargen 19 UDP/TCP returns characters.
ftp 21 TCP file transfer.
telnet 23 TCP remote login.
smtp 25 TCP email.
daytime 37 UDP/TCP returns binary time.
tftp 69 UDP trivial file transfer.
finger 79 TCP info on users.
http 80 TCP World Wide Web.
login 513 TCP remote login.
who 513 UDP different info on users.
Xserver 6000 TCP X windows (N.B. >1023).

ポートおよびサービス機能

Unixは、/etc/servicesファイルからサービス名を取得するために次の関数を提供します。

  • struct servent getservbyname(char name、char proto)*-この呼び出しはサービス名とプロトコル名を取り、そのサービスに対応するポート番号を返します。
  • struct servent getservbyport(int port、char * proto)*-この呼び出しはポート番号とプロトコル名を取り、対応するサービス名を返します。

各関数の戻り値は、次の形式の構造体へのポインタです-

struct servent {
   char  *s_name;
   char  **s_aliases;
   int   s_port;
   char  *s_proto;
};

ここにメンバーフィールドの説明があります-

Attribute Values Description
s_name http It is the official name of the service. For example, SMTP, FTP POP3, etc.
s_aliases ALIAS It holds the list of service aliases. Most of the time, it will be set to NULL.
s_port 80 It will have the associated port number. For example, for HTTP, it will be 80.
s_proto

TCP

UDP

It is set to the protocol used. Internet services are provided using either TCP or UDP.

Unixソケット-ネットワークのバイト順

残念ながら、すべてのコンピューターがマルチバイト値を構成するバイトを同じ順序で保存するわけではありません。 2バイトで構成される16ビットインターネットを考えてみましょう。 この値を保存するには2つの方法があります。

  • リトルエンディアン-このスキームでは、下位バイトは開始アドレス(A)に保存され、上位バイトは次のアドレス(A+ 1)に保存されます。
  • ビッグエンディアン-このスキームでは、上位バイトは開始アドレス(A)に保存され、下位バイトは次のアドレス(A+ 1)に保存されます。

異なるバイト順序規則を持つマシンが互いに通信できるようにするために、インターネットプロトコルは、ネットワークを介して送信されるデータの標準的なバイト順序規則を指定します。 これは、ネットワークバイトオーダーと呼ばれます。

インターネットソケット接続を確立する際、sockaddr_in構造体のsin_portおよびsin_addrメンバーのデータがネットワークバイト順で表されていることを確認する必要があります。

バイト順序付け関数

ホストの内部表現とネットワークバイトオーダーの間でデータを変換するためのルーチンは次のとおりです-

Function Description
htons() Host to Network Short
htonl() Host to Network Long
ntohl() Network to Host Long
ntohs() Network to Host Short

以下は、これらの機能に関する詳細です。

  • * unsigned short htons(unsigned short hostshort)*-この関数は、16バイト(2バイト)量をホストバイト順からネットワークバイト順に変換します。
  • * unsigned long htonl(unsigned long hostlong)*-この関数は、32ビット(4バイト)量をホストバイト順からネットワークバイト順に変換します。
  • * unsigned short ntohs(unsigned short netshort)*-この関数は、16ビット(2バイト)量をネットワークバイト順からホストバイト順に変換します。
  • * unsigned long ntohl(unsigned long netlong)*-この関数は、32ビット量をネットワークバイト順からホストバイト順に変換します。

これらの関数はマクロであり、呼び出し元プログラムに変換ソースコードを挿入します。 リトルエンディアンマシンでは、コードは値をネットワークバイト順に変更します。 ビッグエンディアンのマシンでは、コードは必要ないため挿入されません。関数はヌルとして定義されています。

ホストのバイト順序を決定するプログラム

次のコードをファイル_byteorder.c_に保持し、それをコンパイルしてマシン上で実行します。

この例では、2バイト値0x0102を短整数に格納してから、連続する2つのバイトc [0](アドレスA)とc [1](アドレスA+ 1)を調べて、バイトオーダー。

#include <stdio.h>

int main(int argc, char **argv) {

   union {
      short s;
      char c[sizeof(short)];
   }un;

   un.s = 0x0102;

   if (sizeof(short) == 2) {
      if (un.c[0] == 1 && un.c[1] == 2)
         printf("big-endian\n");

      else if (un.c[0] == 2 && un.c[1] == 1)
         printf("little-endian\n");

      else
         printf("unknown\n");
   }
   else {
      printf("sizeof(short) = %d\n", sizeof(short));
   }

   exit(0);
}

Pentiumマシン上でこのプログラムによって生成された出力は次のとおりです-

$> gcc byteorder.c
$> ./a.out
little-endian
$>

Unixソケット-IPアドレス関数

Unixには、IPアドレスの操作に役立つさまざまな関数呼び出しが用意されています。 これらの関数は、ASCII文字列(人間が使用することを好む)とネットワークバイト順のバイナリ値(ソケットアドレス構造に格納されている値)の間でインターネットアドレスを変換します。

次の3つの関数呼び出しは、IPv4アドレス指定に使用されます-

*int inet_aton(const char* strptr、struct in_addr * addrptr)
*in_addr_t inet_addr(const char* strptr)
*char* inet_ntoa(struct in_addr inaddr)

int inet_aton(const char strptr、struct in_addr addrptr)

この関数呼び出しは、インターネット標準のドット表記で指定された文字列をネットワークアドレスに変換し、指定された構造体にアドレスを格納します。 変換されたアドレスは、ネットワークバイト順(バイトは左から右へ)になります。 文字列が有効な場合は1を返し、エラーの場合は0を返します。

以下は使用例です-

#include <arpa/inet.h>

(...)

   int retval;
   struct in_addr addrptr

   memset(&addrptr, '\0', sizeof(addrptr));
   retval = inet_aton("68.178.157.132", &addrptr);

(...)

in_addr_t inet_addr(const char *strptr)

この関数呼び出しは、インターネット標準のドット表記法で指定された文字列を、インターネットアドレスとしての使用に適した整数値に変換します。 変換されたアドレスは、ネットワークバイト順(バイトは左から右へ)になります。 エラー時に32ビットのバイナリネットワークバイト順のIPv4アドレスとINADDR_NONEを返します。

以下は使用例です-

#include <arpa/inet.h>

(...)

   struct sockaddr_in dest;

   memset(&dest, '\0', sizeof(dest));
   dest.sin_addr.s_addr = inet_addr("68.178.157.132");

(...)

char* inet_ntoa(struct in_addr inaddr)

この関数呼び出しは、指定されたインターネットホストアドレスをインターネット標準のドット表記の文字列に変換します。

以下は使用例です-

#include <arpa/inet.h>

(...)

   char *ip;

   ip = inet_ntoa(dest.sin_addr);

   printf("IP Address is: %s\n",ip);

(...)

Unixソケット-コア関数

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

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

ソケットクライアントサーバー

ソケット機能

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

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

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

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

パラメーター

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

Family Description
AF_INET IPv4 protocols
AF_INET6 IPv6 protocols
AF_LOCAL Unix domain protocols
AF_ROUTE Routing Sockets
AF_KEY Ket socket

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

*type* -必要なソケットの種類を指定します。 それは次の値のいずれかを取ることができます-
Type Description
SOCK_STREAM Stream socket
SOCK_DGRAM Datagram socket
SOCK_SEQPACKET Sequenced packet socket
SOCK_RAW Raw socket
*protocol* -引数は、以下に示す特定のプロトコルタイプに設定する必要があります。0を指定すると、ファミリとタイプの特定の組み合わせに対してシステムのデフォルトが選択されます-
Protocol Description
IPPROTO_TCP TCP transport protocol
IPPROTO_UDP UDP transport protocol
IPPROTO_SCTP SCTP transport protocol

_connect_関数

_connect_関数は、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アドレスとポートを含むsockaddr構造体へのポインタです。
  • addrlen -sizeof(struct sockaddr)に設定します。

_bind_関数

_bind_関数は、ローカルプロトコルアドレスをソケットに割り当てます。 インターネットプロトコルでは、プロトコルアドレスは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アドレスとポートを含むsockaddr構造体へのポインタです。
  • addrlen -sizeof(struct sockaddr)に設定します。

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

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

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

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

_listen_関数

_listen_関数はTCPサーバーによってのみ呼び出され、2つのアクションを実行します-

  • listen関数は、接続されていないソケットを受動ソケットに変換し、カーネルがこのソケットに向けられた着信接続要求を受け入れる必要があることを示します。
  • この関数の2番目の引数は、カーネルがこのソケットのためにキューに入れる必要がある接続の最大数を指定します。
#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd,int backlog);

この呼び出しは成功時に0を返し、そうでない場合はエラー時に-1を返します。

パラメーター

  • sockfd -これは、ソケット関数によって返されるソケット記述子です。
  • backlog -許可された接続の数です。

_accept_関数

_accept_関数は、TCPサーバーによって呼び出され、完了した接続キューの先頭から次に完了した接続を返します。 呼び出しの署名は次のとおりです-

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

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

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

パラメーター

  • sockfd -これは、ソケット関数によって返されるソケット記述子です。
  • cliaddr -クライアントIPアドレスとポートを含むsockaddr構造体へのポインタです。
  • addrlen -sizeof(struct sockaddr)に設定します。

_send_関数

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

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

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

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

パラメーター

  • sockfd -これは、ソケット関数によって返されるソケット記述子です。
  • msg -送信するデータへのポインタです。
  • len -送信するデータの長さ(バイト単位)です。
  • flags -0に設定されます。

_recv_関数

_recv_関数は、ストリームソケットまたはCONNECTEDデータグラムソケットを介してデータを受信するために使用されます。 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 -データを送信する必要のあるホストのsockaddr構造体へのポインタです。
  • tolen -sizeof(struct sockaddr)に設定されます。

_recvfrom_関数

_recvfrom_関数は、UNCONNECTEDデータグラムソケットからデータを受信するために使用されます。

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

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

パラメーター

  • sockfd -これは、ソケット関数によって返されるソケット記述子です。
  • buf -情報を読み込むバッファです。
  • len -バッファの最大長です。
  • flags -0に設定されます。
  • from -データの読み取りが必要なホストのsockaddr構造体へのポインタです。
  • fromlen -sizeof(struct sockaddr)に設定されます。

_close_関数

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

int close( int sockfd );

この呼び出しは成功時に0を返し、そうでない場合はエラー時に-1を返します。

パラメーター

  • sockfd -これは、ソケット関数によって返されるソケット記述子です。

_shutdown_関数

_shutdown_関数は、クライアントとサーバー間の通信を正常に閉じるために使用されます。 この関数は、_close_関数と比較してより多くの制御を提供します。 以下に示すのは、_shutdown_の構文です-

int shutdown(int sockfd, int how);

この呼び出しは成功時に0を返し、そうでない場合はエラー時に-1を返します。

パラメーター

  • sockfd -これは、ソケット関数によって返されるソケット記述子です。
  • 方法-数字の1つを入れてください-
  • 0 -受信が許可されていないことを示します。
  • 1 -送信が許可されていないことを示し、
  • 2 -送信と受信の両方が許可されていないことを示します。 _how_が2に設定されている場合、close()と同じことです。

_select_関数

_select_関数は、指定されたファイル記述子のどれが読み取りの準備ができているか、書き込みの準備ができているか、またはエラー状態が保留になっていることを示します。

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

入力キューにデータがないソケットで_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 -selectcallが利用可能なI/O操作の記述子をポーリングする時間を指定するtimeval構造体を指します。 タイムアウト値が0の場合、selectはすぐに戻ります。 タイムアウト引数がNULLの場合、selectは、少なくとも1つのファイル/ソケットハンドルが使用可能なI/O操作の準備ができるまでブロックします。 それ以外の場合、_select_は、タイムアウトの時間が経過した後、または少なくとも1つのファイル/ソケット記述子がI/O操作の準備ができたときに戻ります。

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

  • * FD_CLR(fd、&fdset)*-ファイル記述子セット_fdset._内のファイル記述子fdのビットをクリアします
  • * FD_ISSET(fd、&fdset)*-_fdset_が指すファイル記述子セットにファイル記述子_fd_のビットが設定されている場合はゼロ以外の値を返し、そうでない場合は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*/
}

Unixソケット-ヘルパー関数

この章では、ソケットプログラミング中に使用されるすべてのヘルパー関数について説明します。 他のヘルパー機能については、章-ポートとサービス、およびネットワーク*バイト順*で説明しています。

_write_関数

_write_関数は、_buf_が指すバッファーから、開いているファイル記述子_fildes_に関連付けられたファイルにnbyteバイトを書き込もうとします。

_send()_関数を使用して、別のプロセスにデータを送信することもできます。

#include <unistd.h>

int write(int fildes, const void *buf, int nbyte);

正常に完了すると、write()は、fildesに関連付けられたファイルに実際に書き込まれたバイト数を返します。 この数がnbyteを超えることはありません。 それ以外の場合、-1が返されます。

パラメーター

  • fildes -これは、ソケット関数によって返されるソケット記述子です。
  • buf -送信するデータへのポインタです。
  • nbyte -書き込まれるバイト数です。 nbyteが0の場合、ファイルが通常のファイルである場合、write()は0を返し、他の結果はありません。それ以外の場合、結果は指定されていません。

_read_関数

_read_関数は、バッファーfildesに関連付けられているファイルからnbyteバイトをbufが指すバッファーに読み取ろうとします。

_recv()_関数を使用して、データを別のプロセスに読み込むこともできます。

#include <unistd.h>

int read(int fildes, const void *buf, int nbyte);

正常に完了すると、write()は、fildesに関連付けられたファイルに実際に書き込まれたバイト数を返します。 この数がnbyteを超えることはありません。 それ以外の場合、-1が返されます。

パラメーター

  • fildes -これは、ソケット関数によって返されるソケット記述子です。
  • buf -情報を読み込むバッファです。
  • nbyte -読み取るバイト数です。

_fork_関数

_fork_関数は、新しいプロセスを作成します。 子プロセスと呼ばれる新しいプロセスは、呼び出し元プロセス(親プロセス)の正確なコピーになります。 子プロセスは、親プロセスから多くの属性を継承します。

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

int fork(void);

正常に完了すると、fork()は0を子プロセスに返し、子プロセスのプロセスIDを親プロセスに返します。 それ以外の場合、-1が親プロセスに返され、子プロセスは作成されず、エラーを示すためにerrnoが設定されます。

パラメーター

  • void -パラメータが不要であることを意味します。

_bzero_関数

bzero_関数は、文字列_s_に_nbyte nullバイトを配置します。 この関数は、すべてのソケット構造にヌル値を設定するために使用されます。

void bzero(void *s, int nbyte);

この関数は何も返しません。

パラメーター

  • s -nullバイトで埋める必要がある文字列を指定します。 これは、ソケット構造変数へのポイントになります。
  • nbyte -null値で埋められるバイト数を指定します。 これは、ソケット構造のサイズになります。

_bcmp_関数

_bcmp_関数は、バイト文字列s1とバイト文字列s2を比較します。 両方の文字列は、nbyteバイト長であると想定されます。

int bcmp(const void *s1, const void *s2, int nbyte);

この関数は、両方の文字列が同一の場合は0を返し、そうでない場合は1を返します。 nbyteが0の場合、bcmp()関数は常に0を返します。

パラメーター

  • s1 -比較する最初の文字列を指定します。
  • s2 -比較する2番目の文字列を指定します。
  • nbyte -比較するバイト数を指定します。

_bcopy_関数

_bcopy_関数は、nbyteバイトを文字列s1から文字列s2にコピーします。 重複する文字列は正しく処理されます。

void bcopy(const void *s1, void *s2, int nbyte);

この関数は何も返しません。

パラメーター

  • s1 -ソース文字列を指定します。
  • s2v -宛先文字列を指定します。
  • nbyte -コピーするバイト数を指定します。

_memset_関数

_memset_関数は、 bzero と同じ方法で構造変数を設定するためにも使用されます。 以下に示す構文を見てください。

void *memset(void *s, int c, int nbyte);

この関数はvoidへのポインターを返します。実際、設定されたメモリへのポインタであり、それに応じてキャストする必要があります。

パラメーター

  • s -設定するソースを指定します。
  • c -nbyteの場所に設定する文字を指定します。
  • nbyte -設定するバイト数を指定します。

Unixソケット-サーバーの例

プロセスをTCPサーバーにするには、以下の手順に従う必要があります-

  • _socket()_システムコールでソケットを作成します。
  • _bind()_システムコールを使用して、ソケットをアドレスにバインドします。 インターネット上のサーバーソケットの場合、アドレスはホストマシンのポート番号で構成されます。
  • _listen()_システムコールで接続をリッスンします。
  • _accept()_システムコールで接続を受け入れます。 通常、この呼び出しは、クライアントがサーバーに接続するまでブロックします。 *_read()_および_write()_システムコールを使用してデータを送受信します。

次に、これらの手順をソースコードの形式で説明します。 このコードをファイル_server.c_に入れて、_gcc_コンパイラーでコンパイルします。

#include <stdio.h>
#include <stdlib.h>

#include <netdb.h>
#include <netinet/in.h>

#include <string.h>

int main( int argc, char* argv[] ) {
   int sockfd, newsockfd, portno, clilen;
   char buffer[256];
   struct sockaddr_in serv_addr, cli_addr;
   int  n;

  /*First call to socket() function*/
   sockfd = socket(AF_INET, SOCK_STREAM, 0);

   if (sockfd < 0) {
      perror("ERROR opening socket");
      exit(1);
   }

  /*Initialize socket structure*/
   bzero((char *) &serv_addr, sizeof(serv_addr));
   portno = 5001;

   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = INADDR_ANY;
   serv_addr.sin_port = htons(portno);

  /* Now bind the host address using bind() call.*/
   if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
      perror("ERROR on binding");
      exit(1);
   }

  /*Now start listening for the clients, here process will
     * go in sleep mode and will wait for the incoming connection
   */

   listen(sockfd,5);
   clilen = sizeof(cli_addr);

  /*Accept actual connection from the client*/
   newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);

   if (newsockfd < 0) {
      perror("ERROR on accept");
      exit(1);
   }

  /*If connection is established then start communicating*/
   bzero(buffer,256);
   n = read( newsockfd,buffer,255 );

   if (n < 0) {
      perror("ERROR reading from socket");
      exit(1);
   }

   printf("Here is the message: %s\n",buffer);

  /*Write a response to the client*/
   n = write(newsockfd,"I got your message",18);

   if (n < 0) {
      perror("ERROR writing to socket");
      exit(1);
   }

   return 0;
}

複数の接続を処理する

サーバーが複数の同時接続を処理できるように、上記のコードで次の変更を行います-

  • _accept_ステートメントと次のコードを無限ループに入れます。
  • 接続が確立されたら、_fork()_を呼び出して新しいプロセスを作成します。
  • 子プロセスは、_sockfd_を閉じ、_doprocessing_関数を呼び出して、新しいソケットファイル記述子を引数として渡します。 _doprocessing()_が返すように、2つのプロセスが会話を完了すると、このプロセスは単に終了します。 *親プロセスは_newsockfd_を閉じます。 このコードはすべて無限ループにあるため、acceptステートメントに戻り、次の接続を待機します。
#include <stdio.h>
#include <stdlib.h>

#include <netdb.h>
#include <netinet/in.h>

#include <string.h>

void doprocessing (int sock);

int main( int argc, char* argv[] ) {
   int sockfd, newsockfd, portno, clilen;
   char buffer[256];
   struct sockaddr_in serv_addr, cli_addr;
   int n, pid;

  /*First call to socket() function*/
   sockfd = socket(AF_INET, SOCK_STREAM, 0);

   if (sockfd < 0) {
      perror("ERROR opening socket");
      exit(1);
   }

  /*Initialize socket structure*/
   bzero((char *) &serv_addr, sizeof(serv_addr));
   portno = 5001;

   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = INADDR_ANY;
   serv_addr.sin_port = htons(portno);

  /* Now bind the host address using bind() call.*/
   if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
      perror("ERROR on binding");
      exit(1);
   }

  /*Now start listening for the clients, here
     * process will go in sleep mode and will wait
 *for the incoming connection
  */

   listen(sockfd,5);
   clilen = sizeof(cli_addr);

   while (1) {
      newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

      if (newsockfd < 0) {
         perror("ERROR on accept");
         exit(1);
      }

     /*Create child process*/
      pid = fork();

      if (pid < 0) {
         perror("ERROR on fork");
         exit(1);
      }

      if (pid == 0) {
        /*This is the client process*/
         close(sockfd);
         doprocessing(newsockfd);
         exit(0);
      }
      else {
         close(newsockfd);
      }

   }/*end of while*/
}

次のコードシーケンスは、_doprocessing_関数の簡単な実装を示しています。

void doprocessing (int sock) {
   int n;
   char buffer[256];
   bzero(buffer,256);
   n = read(sock,buffer,255);

   if (n < 0) {
      perror("ERROR reading from socket");
      exit(1);
   }

   printf("Here is the message: %s\n",buffer);
   n = write(sock,"I got your message",18);

   if (n < 0) {
      perror("ERROR writing to socket");
      exit(1);
   }

}

Unixソケット-クライアントの例

プロセスをTCPクライアントにするには、以下の&minusの手順に従う必要があります。

  • _socket()_システムコールでソケットを作成します。
  • _connect()_システムコールを使用して、ソケットをサーバーのアドレスに接続します。
  • データを送受信します。 これを行う方法はいくつかありますが、最も簡単な方法は_read()_および_write()_システムコールを使用することです。

次に、これらの手順をソースコードの形式で説明します。 このコードをファイル client.c に入れ、 gcc コンパイラーでコンパイルします。

このプログラムを実行し、サーバーの_hostname_と_port number_を渡して、サーバーに接続します。これは、すでに別のUnixウィンドウで実行している必要があります。

#include <stdio.h>
#include <stdlib.h>

#include <netdb.h>
#include <netinet/in.h>

#include <string.h>

int main(int argc, char *argv[]) {
   int sockfd, portno, n;
   struct sockaddr_in serv_addr;
   struct hostent *server;

   char buffer[256];

   if (argc < 3) {
      fprintf(stderr,"usage %s hostname port\n", argv[0]);
      exit(0);
   }

   portno = atoi(argv[2]);

  /*Create a socket point*/
   sockfd = socket(AF_INET, SOCK_STREAM, 0);

   if (sockfd < 0) {
      perror("ERROR opening socket");
      exit(1);
   }

   server = gethostbyname(argv[1]);

   if (server == NULL) {
      fprintf(stderr,"ERROR, no such host\n");
      exit(0);
   }

   bzero((char *) &serv_addr, sizeof(serv_addr));
   serv_addr.sin_family = AF_INET;
   bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
   serv_addr.sin_port = htons(portno);

  /*Now connect to the server*/
   if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
      perror("ERROR connecting");
      exit(1);
   }

  /*Now ask for a message from the user, this message
     * will be read by server
   */

   printf("Please enter the message: ");
   bzero(buffer,256);
   fgets(buffer,255,stdin);

  /*Send message to the server*/
   n = write(sockfd, buffer, strlen(buffer));

   if (n < 0) {
      perror("ERROR writing to socket");
      exit(1);
   }

  /*Now read server response*/
   bzero(buffer,256);
   n = read(sockfd, buffer, 255);

   if (n < 0) {
      perror("ERROR reading from socket");
      exit(1);
   }

   printf("%s\n",buffer);
   return 0;
}

Unixソケット-概要

以下は、ソケットプログラミングに関連するすべての機能のリストです。

ポートおよびサービス機能

Unixは、/etc/servicesファイルからサービス名を取得するために次の関数を提供します。

  • struct servent getservbyname(char name、char proto)*-この呼び出しはサービス名とプロトコル名を取り、そのサービスに対応するポート番号を返します。
  • struct servent getservbyport(int port、char * proto)*-この呼び出しはポート番号とプロトコル名を取り、対応するサービス名を返します。

バイト順序付け関数

  • * unsigned short htons(unsigned short hostshort)*-この関数は、16バイト(2バイト)の量をホストバイト順からネットワークバイト順に変換します。
  • * unsigned long htonl(unsigned long hostlong)*-この関数は、32ビット(4バイト)量をホストバイト順からネットワークバイト順に変換します。
  • * unsigned short ntohs(unsigned short netshort)*-この関数は、16バイト(2バイト)の量をネットワークバイト順からホストバイト順に変換します。
  • * unsigned long ntohl(unsigned long netlong)*-この関数は、32ビット量をネットワークバイト順からホストバイト順に変換します。

IPアドレス機能

  • int inet_aton(const char strptr、struct in_addr * addrptr)*-この関数呼び出しは、指定された文字列をインターネット標準ドット表記でネットワークアドレスに変換し、指定された構造にアドレスを格納します。 変換されたアドレスは、ネットワークバイト順(バイトは左から右へ)になります。 文字列が有効な場合は1を返し、エラーの場合は0を返します。
  • in_addr_t inet_addr(const char strptr)*-この関数呼び出しは、インターネット標準ドット表記の指定された文字列を、インターネットアドレスとしての使用に適した整数値に変換します。 変換されたアドレスは、ネットワークバイト順(バイトは左から右へ)になります。 エラー時に32ビットのバイナリネットワークバイト順のIPv4アドレスとINADDR_NONEを返します。
  • char inet_ntoa(struct in_addr inaddr)*-この関数呼び出しは、指定されたインターネットホストアドレスをインターネット標準ドット表記の文字列に変換します。

ソケットコア機能

  • * intソケット(intファミリ、int型、intプロトコル)*-この呼び出しは、後のシステムコールで使用できるソケット記述子を返します。エラーの場合は-1を返します。
  • int connect(int sockfd、struct sockaddr serv_addr、int addrlen)*-TCPクライアントは、connect関数を使用してTCPサーバーとの接続を確立します。 この呼び出しは、サーバーへの接続に成功した場合は0を返し、それ以外の場合は-1を返します。
  • int bind(int sockfd、struct sockaddr my_addr、int addrlen)*-bind関数は、ローカルプロトコルアドレスをソケットに割り当てます。 この呼び出しは、アドレスに正常にバインドされた場合は0を返し、そうでない場合は-1を返します。
  • * int listen(int sockfd、int backlog)*-listen関数は、クライアント要求をリッスンするためにTCPサーバーによってのみ呼び出されます。 この呼び出しは成功すると0を返し、そうでなければ-1を返します。
  • int accept(int sockfd、struct sockaddr cliaddr、socklen_t * addrlen)*-accept関数は、クライアント要求を受け入れ、実際の接続を確立するためにTCPサーバーによって呼び出されます。 この呼び出しは、成功すると負でない記述子を返します。それ以外の場合は、-1を返します。
  • int send(int sockfd、const void msg、int len、int flags)*-send関数は、ストリームソケットまたはCONNECTEDデータグラムソケットを介してデータを送信するために使用されます。 この呼び出しは、送信されたバイト数を返します。それ以外の場合、-1を返します。
  • int recv(int sockfd、void buf、int len、unsigned intフラグ)*-recv関数は、ストリームソケットまたはCONNECTEDデータグラムソケットでデータを受信するために使用されます。 この呼び出しは、バッファに読み込まれたバイト数を返します。それ以外の場合は、エラー時に-1を返します。
  • int sendto(int sockfd、const void msg、int len、unsigned int flags、const struct sockaddr * to、int tolen)*-sendto関数は、UNCONNECTEDデータグラムソケットを介してデータを送信するために使用されます。 この呼び出しは送信されたバイト数を返し、そうでない場合はエラー時に-1を返します。
  • int recvfrom(int sockfd、void buf、int len、unsigned int flags struct sockaddr from、int fromlen)*-recvfrom関数は、UNCONNECTEDデータグラムソケットからデータを受信するために使用されます。 この呼び出しは、バッファに読み込まれたバイト数を返します。それ以外の場合は、エラー時に-1を返します。
  • * int close(int sockfd)*-close関数は、クライアントとサーバー間の通信を閉じるために使用されます。 この呼び出しは成功すると0を返し、そうでなければ-1を返します。
  • * int shutdown(int sockfd、int how)*-シャットダウン機能は、クライアントとサーバー間の通信を正常に閉じるために使用されます。 この関数は、close関数と比較してより多くの制御を提供します。 成功すると0を返し、そうでなければ-1を返します。
  • int select(int nfds、fd_set readfds、fd_set writefds、fd_set errorfds、struct timeval * timeout)*-この関数は、複数のソケットの読み取りまたは書き込みに使用されます。

ソケットヘルパー関数

  • int write(int fildes、const void buf、int nbyte)*-書き込み関数は、bufが指すバッファーからnbyteバイトを、開いているファイル記述子fildesに関連付けられたファイルに書き込もうとします。 正常に完了すると、write()は、fildesに関連付けられたファイルに実際に書き込まれたバイト数を返します。 この数がnbyteを超えることはありません。 それ以外の場合、-1が返されます。
  • int read(int fildes、const void buf、int nbyte)*-読み取り関数は、オープンファイル記述子fildesに関連付けられたファイルからnufバイトをbufが指すバッファーに読み取ろうとします。 正常に完了すると、write()は、fildesに関連付けられたファイルに実際に書き込まれたバイト数を返します。 この数がnbyteを超えることはありません。 それ以外の場合、-1が返されます。
  • * int fork(void)*-fork関数は新しいプロセスを作成します。 子プロセスと呼ばれる新しいプロセスは、呼び出し元プロセス(親プロセス)の正確なコピーになります。
  • void bzero(void s、int nbyte)*-bzero関数は、文字列sにnbyte nullバイトを配置します。 この関数は、すべてのソケット構造にヌル値を設定するために使用されます。
  • int bcmp(const void s1、const void * s2、int nbyte)*-bcmp関数は、バイト文字列s1とバイト文字列s2を比較します。 両方の文字列は、nbyteバイト長であると想定されます。
  • void bcopy(const void s1、void * s2、int nbyte)*-bcopy関数は、nbyteバイトを文字列s1から文字列s2にコピーします。 重複する文字列は正しく処理されます。
  • void memset(void * s、int c、int nbyte)*-memset関数は、bzeroと同じ方法で構造変数を設定するためにも使用されます。