ネットワークプログラミング4:Linuxが提供するAPIの簡単な分析(ソケットサーバーとクライアントの開発手順)

Linuxが提供するAPIの簡単な分析(ソケットサーバーとクライアントの開発手順)

1.接続プロトコル:(TCP / UDP)

//创建套接字
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain,int type,int protocol);
返回sockfd---失败返回-1

ドメイン:
通常、使用するプロトコルファミリを指定しますAF_INET、インターネットプロトコルファミリ(TCP / IPプロトコルファミリ)を表します。

AF_INET IPV4インターネットドメイン
AF_INET6 IPV6インターネットドメイン
AF_UNIX unixドメイン
AF_ROUTEルーティングソケット
AF_KEYキーソケット
AF_UNSPECが指定されていません

typeパラメーターは、ソケットのタイプを指定します。
SOCK_STREAM
ストリーミングソケットは、信頼性の高い接続指向の通信フローを提供します。TCPプロトコルを使用して、データ伝送の正確性とシーケンスを保証ます
SOCK_DGRAM
データグラムソケットはコネクションレス型サーバーを定義します。データは独立したメッセージを介して送信されます。無秩序であり、信頼性を保証するものではなく、エラーもありません。データグラムプロトコルUDPを使用します
SOCK_RAW
プログラムが基になるプロトコルを使用できるようにします。元のソケットは、IPやICMPなどの基になるプロトコルに直接アクセスするために実行されます。強力ですが、使用するのに不便で、主一部のプロトコルの開発に使用されます


プロトコルに
は通常値「0
0タイプタイプに対応するデフォルトプロトコルを選択します
== IPPROTO_TCP TCP伝送プロトコル==
IPPROTO_UDP UDP伝送プロトコル
IPPROTO_SCTP SCTP伝送プロトコル
IPPROTO_TIPC TIPC伝送プロトコル

2. IP番号、ポート番号および対応する説明語の割り当て関数:bind()関数

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

bind()関数は、アドレスファミリの特定のアドレスをソケットに割り当てます。たとえば、AF_INETとAF_INET6に対応するのは、ipv4またはipv6アドレスとポート番号の組み合わせをソケットに割り当てることです。

機能:IPアドレスとポート番号をsocketfd
パラメーターにバインドするために使用されます。
sockfd:ソケットを説明する単語。socket()関数によって作成され、ソケットを一意に識別します。bind()関数は、この記述子に名前をバインドします。
アドレス:バインドされるsockfdを指すconst struct sockaddr *ポインタープロトコルアドレス
addrlen:住所の長さに対応します。

プロトコルアドレス構造ソケット作成時のアドレスプロトコルファミリによって異なります。たとえば、ipv4は以下に対応します。

struct sockaddr_in {
    
    
    sa_family_t    sin_family; //协议族
    in_port_t      sin_port;   //端口号
    struct in_addr sin_addr;   //IP地址结构体
};
struct in_addr {
    
    
    uint32_t       s_addr;     /* address in network byte order */
};

通常、サーバーはサーバーの起動時に既知のアドレス==(IPアドレス+ポート番号など)==をバインドします。これはサービスを提供するために使用され、クライアントはそれを介してサーバーに接続できます。クライアントを指定する必要はなく、システムは自動的にポート番号と独自のIPアドレスの組み合わせを割り当てます。このため、通常はサーバーがlistenの前にbind()を呼び出しますが、クライアントはそれを呼び出さず、代わりにシステムがconnect()のときにランダムに生成します。

3.listen()モニタリング関数、connect()接続関数

サーバーの場合、socket()とbind()を呼び出した後、listen()を呼び出してソケットを監視します。クライアントがconnect()を呼び出して接続要求を送信すると、サーバーは要求を受信します。

#include <sys/types.h> 
#include <sys/socket.h>
int listen(int sockfd, int backlog);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

リッスン機能の最初のパラメータは、監視されるものですソケット記述語、2番目のパラメーターは、対応するソケットがキューに入れることができるキューです接続の最大数socket()関数によって作成されたソケットはデフォルトでアクティブタイプであり、listen関数はソケットをパッシブタイプに変えて、クライアントの接続要求を待ちます。

接続関数の最初のパラメーターはクライアントのソケットの説明、2番目のパラメーターはサーバーのソケットアドレス、3番目のパラメータはソケットアドレスです長さクライアントは、connect関数を呼び出すことにより、TCPサーバーとの接続を確立します。
  
4.accept()受信リクエスト関数

TCPサーバーがsocket()、bind()、listen()を順に呼び出した後、指定されたソケットアドレスをリッスンします。TCPクライアントは、socket()およびconnect()を順に呼び出した後、TCPサーバーに接続要求を送信します。TCPサーバーは要求を待機した後、accept()関数を呼び出して要求を受信し、接続が確立されます。その後、ネットワークI / O操作、つまり通常のファイルと同様の読み取りおよび書き込みI / O操作を開始できます。

#include <sys/types.h> 
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //返回连接connect_fd

関数の3つのパラメーターは次のとおりです。

sockfd:は、上記で説明したリスニングソケットです。このソケットは、ポートを監視するために使用されます。クライアントがサーバーに接続するとき、このポート番号を使用します。このポート番号は現在、このソケットに接続されています関連。もちろん、クライアントはソケットの詳細を知りません。アドレスとポート番号しか知りません。
addr:これは、戻り値を受け取るために使用される結果パラメーターです。この戻り値は、クライアントのアドレスを指定します。もちろん、このアドレスは、特定のアドレス構造によって記述されます。ユーザーは、このアドレス構造の種類を知っている必要があります。顧客の住所に関心がない場合は、この値をNULLに設定できます。
len:誰もが思うように、それは結果のパラメータでもあります。これは、上記のaddr構造のサイズを受け入れるために使用されます。これは、addr構造が占めるバイト数を示します。同様に、NULLに設定することもできます。

受け入れが正常に返された場合、サーバーとクライアントは正しく接続を確立しており、サーバーは受け入れによって返されたソケットを介してクライアントとの通信を完了します。

注意
Acceptは、クライアント接続が確立されて戻るまで、デフォルトでプロセスをブロックし、新しく利用可能なソケット(接続ソケット)を返します。

この時点で、2つのタイプのソケットを区別する必要があります。

リスニングソケット:リスニングソケットは、acceptパラメータsockfdに似ています。リスニングソケットです。listen関数が呼び出されると、サーバーはsocket()関数の呼び出しを開始します。リスニングソケット記述子(モニターソケット)と呼ばれます。
ソケットを接続:ソケットはアクティブに接続されたソケットからリスニングソケットに変わり、accept関数は接続されたソケット(接続されたソケット)の説明を返します。これは、ネットワークがすでに存在するポイントを表します接続。

サーバーは通常、リスニングソケット記述子のみを作成します。これは、サーバーのライフサイクル中に常に存在します。カーネルは、サーバープロセスによって受け入れられたクライアント接続ごとに接続されたソケット記述子を作成し、サーバーが特定のクライアントのサービスを完了すると、対応する接続​​されたソケット記述子が閉じられます。

接続ソケットsocketfd_newは、クライアントと通信するための新しいポートを占有せず、リスニングソケットsocketfdと同じポート番号を使用します。
  
5.read()、write()およびその他の関数

ネットワークI / O操作には次のグループがあります。

read()/write()
recv()/send()
readv()/writev()
recvmsg()/sendmsg()
recvfrom()/sendto()

6.閉じる機能

int close(int fd);

TCPソケットを閉じるデフォルトの動作は、ソケットを閉じたものとしてマークし、すぐに呼び出しプロセスに戻ります。説明語は呼び出しプロセスで使用できなくなりました。つまり、読み取りまたは書き込みの最初のパラメーターとして使用できなくなりました。

注意:クローズ操作は、対応するソケット記述ワードの参照カウントを-1にするだけであり、参照カウントが0の場合のみ、TCPクライアントがサーバーに接続終了要求を送信するようトリガーします。

7.アドレス変換API:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
//把字符串形成的“192.168.1.123”转为网络能识别的格式
char *inet_ntoa(struct in_addr in);
//把网络格式的ip地址转化为字符串形式

8.エンディアン変換API:

#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);//返回网络字节序的值
uint16_t htons(uint16_t hostshort);//返回网络字节序的值
uint32_t ntohl(uint32_t netlong);//返回主机字节序的值uint32_t
uint16_t ntohs(uint16_t netshort);//返回主机字节序的值

hはホスト、nはネット、sは短い(2バイト)、lは長い(4バイト)を表します。ホストのバイトオーダーとネットワークのバイトオーダー間の変換は、上記の4つの関数によって実現できます。時にはそれは使用することができますINADDR_ANY、INADDR_ANYは、オペレーティングシステムが取得するアドレスを指定します。

クライアントとサーバー間のコードの記述は、上記のAPIを介して完了することができます。

コードの実装については、次のセクションを参照してくださいネットワークプログラミング5説明する

おすすめ

転載: blog.csdn.net/weixin_40734514/article/details/108555217