記事ディレクトリ
ソケットプロトコルとそのデータ転送特性
協定について
遠くにいる二人が電話する場合、まず通話方法を決定する必要があり、一方が電話を選択した場合、もう一方も電話を選択しないと、メッセージは受信されません。
つまり、プロトコルはデータ交換を完了するために作成される合意です。
ソケットを作成する
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
- 成功返回文件描述符,失败返回-1
domain 套接字中使用的协议族信息
type 套接字数据传输类型信息
protocol 计算机间通信中使用的协议信息
プロトコルファミリー
ソケット関数の第一引数にはソケットで使用するプロトコル分類情報が渡され、このプロトコル分類情報がプロトコルファミリーとなります。
名前 | プロトコルファミリー |
---|---|
PF_INET | IPv4 インターネット プロトコル スイート |
PF_INET6 | IPv6 インターネット プロトコル スイート |
PF_LOCAL | ローカル通信用の UNIX プロトコル スイート |
PF_パケット | 基礎となるソケットプロトコルファミリー |
PF_IPX | IPX Novell プロトコル スイート |
ソケット タイプ 1: 接続指向ソケット (SOCK_STREAM)
伝送方式の特徴は以下の通りです。
- 転送中にデータが消えることはありません
- データを順次転送する
- 転送されるデータにデータ境界はありません
ソケット内にはデータを送受信するバッファーがあり、これはバイト配列です。ソケット経由で送信されたデータはこの配列に保存されるため、データを受信してもすぐにread関数が呼び出されるわけではなく、配列の容量を超えない限り、一度のread関数呼び出しで全て読み込むことが可能ですデータがバッファにいっぱいになった後、複数の読み取り関数呼び出しに分割して読み取ることもできます。コネクション指向ソケットでは、読み取り関数と書き込み関数の呼び出し数はあまり意味がないため、コネクション指向ソケットにはデータ境界がありません。
コネクション型ソケットの概要は次のとおりです。信頼性が高く、順序どおりに配信され、バイトベースのコネクション型データ送信ソケットです。
ソケットタイプ 2: メッセージ指向ソケット (SOCK_DGRAM)
伝送方式の特徴は以下の通りです。
- 送信順序よりも高速送信を重視
- 送信されたデータが消失または破損する可能性があります。
- 送信されるデータにはデータ境界がある
- 転送ごとのデータ サイズを制限する
メッセージ指向ソケットの概要は次のとおりです。信頼性が低く、順序どおりに配信されず、高速データ送信用に設計されたソケットです。
プロトコルの最終選択
プロトコル ファミリ情報とソケット データ送信方法は、ソケット関数の強力な 2 つのパラメーターを通じて渡されていますが、この情報だけでは使用するプロトコルを決定するのに十分ではないため、3 番目のパラメーターを渡す必要があります。
最初の 2 つのパラメータを渡すと必要なソケットが作成されるため、次のような状況が発生しない限り、ほとんどの場合 3 番目のパラメータに 0 を渡すことができます。
「同じプロトコル ファミリ内に同じデータ伝送方式を持つ複数のプロトコルが存在します。」
-
IPv4 プロトコル ファミリの接続指向ソケットの場合、3 番目のパラメータは IPPROTO_TCP を使用します。
-
IPv4 プロトコル ファミリのメッセージ指向ソケットの場合は、IPPROTO_UDP を 3 番目のパラメータとして使用します。
コネクション型ソケット: TCP ソケットの例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
void error_handling(char *message);
int main(int argc, char* argv[])
{
int sock;
struct sockaddr_in serv_addr;
char message[30];
int str_len=0;
int idx=0, read_len=0;
if(argc!=3){
printf("Usage : %s <IP> <port>\n", argv[0]);
exit(1);
}
sock=socket(PF_INET, SOCK_STREAM, 0);
if(sock == -1)
error_handling("socket() error");
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
serv_addr.sin_port=htons(atoi(argv[2]));
if(connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
error_handling("connect() error!");
while(read_len=read(sock, &message[idx++], 1))
{
if(read_len==-1)
error_handling("read() error!");
str_len+=read_len;
}
printf("Message from server: %s \n", message);
printf("Function read call count: %d \n", str_len);
close(sock);
return 0;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
要約する
「TCP/IP ネットワーク プログラミング」コラムの 2 回目の記事です。読者の皆様もぜひご購読ください。
詳細については、「 GitHub 」をクリックしてください。
⭐学術交流グループQ 754410389更新中~~~