select-IO多重化
15628 ワード
1、基本概念IO多重化とは、カーネルがプロセスによって指定された1つまたは複数のIO条件が読み取りの準備をしていることを発見すると、そのプロセスに通知することである.IO多重化は以下の場合に適用される.お客様が複数の記述語を処理する場合(一般的にはインタラクティブ入力およびネットワークソケットインタフェース)、I/O多重化を使用する必要があります. は、1つのクライアントが複数のインタフェースを同時に処理する場合、このような状況は可能であるが、めったに発生しない. TCPサーバがリスニング・スイート・インタフェースと接続されたスイート・インタフェースの両方を処理する場合、I/O多重化も一般的に使用されます. サーバがTCPを処理し、UDPも処理する場合、I/O多重化が一般的に使用されます. サーバが複数のサービスまたは複数のプロトコルを処理する場合、I/O多重化 が一般的に使用されます.
マルチプロセスとマルチスレッド技術と比較して、I/O多重技術の最大の利点はシステムオーバーヘッドが小さく、システムがプロセス/スレッドを作成する必要がなく、これらのプロセス/スレッドを維持する必要がなく、システムのオーバーヘッドを大幅に削減することである.2、select関数プロセスは、カーネルが複数のイベントのいずれかの送信を待機し、1つ以上のイベントが発生したか、または指定された時間が経過した後にのみ起動することを示す.関数のプロトタイプは次のとおりです.
int select(int maxfdp 1,fd_set*readset,fd_set*writeset,fd_set*exceptset,const struct timeval*timeout)戻り値:準備記述子の数、タイムアウト戻り0、エラー戻り-1
関数パラメータの説明は次のとおりです.最初のパラメータmaxfdp 1は、テスト対象の記述ワード数を指定し、その値はテスト対象の最大記述ワードプラス1(したがって、このパラメータをmaxfdp 1と命名する)、記述ワード0、1、2...maxfdp 1-1がテストされる.ファイル記述子は0から始まるからです. の3つのパラメータreadset、writeset、exceptsetは、カーネルに読み取り、書き込み、および異常条件をテストさせる記述語を指定します.ある条件に興味がなければ、空のポインタに設定できます.struct fd_setは、ファイル記述子が格納された集合として理解することができ、 は、以下の4つのマクロによって設定することができる. timeoutは、指定された記述ワードのいずれかの準備がどれだけ時間がかかるかをカーネルに通知する.そのtimeval構造は、この時間の秒数とマイクロ秒数を指定するために使用されます.struct timeval{ long tv_sec;//seconds long tv_usec;//microseconds };
このパラメータには,(1)I/Oの準備ができている記述語が1つある場合にのみ戻る,(3)常に待つ可能性がある.このため、このパラメータを空ポインタNULLに設定します.(2)一定時間待機:記述語がI/Oの準備ができているときに戻るが、このパラメータによって指定されたtimeval構造で指定された秒数とマイクロ秒数を超えない.(3)まったく待たない:記述語をチェックしてすぐに戻ることをポーリングと呼ぶ.このため、パラメータはtimeval構造を指し、タイマ値は0でなければなりません.
次は私が書いたselectのdemoで、後で使うか、みんなが必要とするようにします.
マルチプロセスとマルチスレッド技術と比較して、I/O多重技術の最大の利点はシステムオーバーヘッドが小さく、システムがプロセス/スレッドを作成する必要がなく、これらのプロセス/スレッドを維持する必要がなく、システムのオーバーヘッドを大幅に削減することである.2、select関数プロセスは、カーネルが複数のイベントのいずれかの送信を待機し、1つ以上のイベントが発生したか、または指定された時間が経過した後にのみ起動することを示す.関数のプロトタイプは次のとおりです.
#include
#include
int select(int maxfdp 1,fd_set*readset,fd_set*writeset,fd_set*exceptset,const struct timeval*timeout)戻り値:準備記述子の数、タイムアウト戻り0、エラー戻り-1
関数パラメータの説明は次のとおりです.
void FD_ZERO(fd_set *fdset); //
void FD_SET(int fd, fd_set *fdset); //
void FD_CLR(int fd, fd_set *fdset); //
int FD_ISSET(int fd, fd_set *fdset); //
このパラメータには,(1)I/Oの準備ができている記述語が1つある場合にのみ戻る,(3)常に待つ可能性がある.このため、このパラメータを空ポインタNULLに設定します.(2)一定時間待機:記述語がI/Oの準備ができているときに戻るが、このパラメータによって指定されたtimeval構造で指定された秒数とマイクロ秒数を超えない.(3)まったく待たない:記述語をチェックしてすぐに戻ることをポーリングと呼ぶ.このため、パラメータはtimeval構造を指し、タイマ値は0でなければなりません.
次は私が書いたselectのdemoで、後で使うか、みんなが必要とするようにします.
/*********************************************************
- Copyright (C): 2016
- File name : server.c
- Author : - Zhaoxinan -
- Date : 2016 09 29 15 09 06
- Description : selcetIO
* *******************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// 8000
#define PORT 8000
// 80
#define MAX_LINE 80
int main()
{
int i;
int ret;
int sockfd;
int new_fd;
int work_fd;
int sin_size;
int opt = 1;
int maxi;
int maxfd;
fd_set readset;
fd_set allset;
int client[FD_SETSIZE]; //
char buffer[MAX_LINE];
socklen_t addr_len; //
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
// TCP
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "Socket error!
", strerror(errno));
exit(1);
}
//
bzero(&server_addr, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
// 30s
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
// IP
if (bind(sockfd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr)) == -1)
{
fprintf(stderr, "Bind error:%s
\a", strerror(errno));
exit(1);
}
printf("bind
");
//
if (listen(sockfd, 30) == -1)
{
fprintf(stderr, "Listen error:%s
\a", strerror(errno));
exit(1);
}
printf("listening!
");
//
maxfd = sockfd;
maxi = -1;
for (i = 0; i < FD_SETSIZE; i++)
{
client[i] = -1;
}
//
FD_ZERO(&allset);
// sockfd
FD_SET(sockfd, &allset);
while (1)
{
readset = allset;
//
ret = select(maxfd + 1, &readset, NULL, NULL, NULL);
if (ret == -1)
{
printf("select error!
");
exit(1);
}
// sockfd
if (FD_ISSET(sockfd, &readset))
{
// if client_fd
addr_len = sizeof(server_addr);
if ((new_fd = accept(sockfd, (struct sockaddr*)(&client_addr), &addr_len)) == -1)
{
fprintf(stderr, "Accept error:%s
\a", strerror(errno));
exit(1);
}
printf("accept
");
printf(" fd = %d
", new_fd);
// newfd
//
for (i = 0; i < FD_SETSIZE; i++)
{
if (client[i] <= 0)
{
client[i] = new_fd;
break;
}
}
// ,
if (i == FD_SETSIZE)
{
printf("too many clients
");
exit(1);
}
//
FD_SET(new_fd, &allset);
if (new_fd > maxfd)
{
maxfd = new_fd;
}
if (i > maxi)
{
maxi = i;
}
}
//
for (i = 0; i < FD_SETSIZE; i++)
{
if ((work_fd = client[i]) < 0)
{
continue;
}
// fd , if
if (FD_ISSET(work_fd, &readset))
{
printf("reading
");
ret = read(work_fd, buffer, MAX_LINE);
if (ret == 0)
{
//
printf("the other side has been close
");
fflush(stdout);
close(work_fd);
//
FD_CLR(work_fd, &allset);
client[i] = -1;
}
else
{
printf(" fd = %d
", work_fd);
printf("%s
", buffer);
printf("__________________
");
printf("readok!
");
}
}
}
}
close(sockfd);
return 0;
}
/*********************************************************
- Copyright (C): 2016
- File name : client.c
- Author : - Zhaoxinan -
- Date : 2016 10 07 22 03 58
- Description : IO
* *******************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 8000
int main(int argc, char **argv)
{
int ret;
int sockfd;
int n_write;
char buffer[80];
struct sockaddr_in server_addr;
if (argc != 2)
{
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
exit(1);
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
if (connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1)
{
exit(1);
}
while (1)
{
memset(buffer, 0, sizeof(buffer));
scanf("%s", buffer);
n_write = write(sockfd, buffer, sizeof(buffer));
if (n_write == -1)
{
printf("write error!
");
}
printf("_________________
");
}
return 0;
}