ホームページ >運用・保守 >Linuxの運用と保守 >Linuxソケットを使用してサーバーに接続する複数のクライアントを実装する方法

Linuxソケットを使用してサーバーに接続する複数のクライアントを実装する方法

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB転載
2023-05-20 23:10:102382ブラウズ

1. はじめに

実際の状況では、複数のクライアントがサーバーに接続していることがよくあります。これまでに紹介したconnect、recv、sendなどの関数はすべてブロッキング関数であるため、リソースが十分に準備されていない場合、関数を呼び出したプロセスがスリープ状態になり、I/O多重化に対応できなくなります。 . .

この記事では、 I/O 多重化の 2 つの方法、fcntl()、select() について説明します。 Linux はソケットを特殊なファイル記述子として扱うため、これがユーザーに大きな利便性をもたらしていることがわかります。

2. fcntl

fcntl() 関数には次の特徴があります:

1) ノンブロッキング I/O: cmd を設定できます。に F_SETFL、ロックを O_NONBLOCK に設定

2) シグナル駆動 I/O: cmd を F_SETFL に設定し、ロックを O_ASYNC に設定できます。

ルーチン:

#include <sys>
#include <sys>
#include <sys>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys>
#include <sys>
#include <sys>
#include <unistd.h>
#include <netinet>
#include <fcntl.h>
#include <unistd.h>

#define SERVPORT 3333
#define BACKLOG 10
#define MAX_CONNECTED_NO 10
#define MAXDATASIZE 100

int main()
{
  struct sockaddr_in server_sockaddr,client_sockaddr;
  int sin_size,recvbytes,flags;
  int sockfd,client_fd;
  char buf[MAXDATASIZE];
/*创建socket*/
  if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1){
    perror("socket");
    exit(1);
  }
  printf("socket success!,sockfd=%d\n",sockfd);

/*设置sockaddr结构*/
  server_sockaddr.sin_family=AF_INET;
  server_sockaddr.sin_port=htons(SERVPORT);
  server_sockaddr.sin_addr.s_addr=INADDR_ANY;
  bzero(&(server_sockaddr.sin_zero),8);

/*将本地ip地址绑定端口号*/
  if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr))==-1){
    perror("bind");
    exit(1);
  }
  printf("bind success!\n");

/*监听*/
  if(listen(sockfd,BACKLOG)==-1){
    perror("listen");
    exit(1);
  }
  printf("listening....\n");

/*fcntl()函数,处理多路复用I/O*/
  if((flags=fcntl( sockfd, F_SETFL, 0))<p data-id="p838747a-v4XAh0T3">Runこのプログラム: <br></p>
<pre class="brush:php;toolbar:false">[root@localhost net]# ./fcntl
socket success!,sockfd=3
bind success!
listening....
accept: Resource temporarily unavailable

accept リソースが利用できない場合、プログラムが自動的に戻ることがわかります。

赤い太字のコードを次のように置き換えると:

if((flags=fcntl( sockfd, F_SETFL, 0))<p data-id="p838747a-AEbYy731">実行結果は次のようになります: <br></p><pre class="brush:php;toolbar:false">[root@localhost net]# ./fcntl1
socket success!,sockfd = 3
bind success!
listening...

プロセスが待機していることがわかります。別の関連信号がそれを駆動するまで。

3.select

#include <sys>
#include <sys>
#include <sys>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys>
#include <sys>
#include <sys>
#include <unistd.h>
#include <netinet>
#define SERVPORT 3333
#define BACKLOG 10
#define MAX_CONNECTED_NO 10
#define MAXDATASIZE 100
int main()
{
  struct sockaddr_in server_sockaddr,client_sockaddr;
  int sin_size,recvbytes;
  fd_set readfd;
  fd_set writefd;
  int sockfd,client_fd;
  char buf[MAXDATASIZE];
/*创建socket*/
  if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1){
    perror("socket");
    exit(1);
  }
  printf("socket success!,sockfd=%d\n",sockfd);
/*设置sockaddr结构*/
  server_sockaddr.sin_family=AF_INET;
  server_sockaddr.sin_port=htons(SERVPORT);
  server_sockaddr.sin_addr.s_addr=INADDR_ANY;
  bzero(&(server_sockaddr.sin_zero),8);
/*将本地ip地址绑定端口号*/
  if(bind(sockfd,(struct sockaddr *)&server_sockaddr,sizeof(struct sockaddr))==-1){
    perror("bind");
    exit(1);
  }
  printf("bind success!\n");
/*监听*/
  if(listen(sockfd,BACKLOG)==-1){
    perror("listen");
    exit(1);
  }
  printf("listening....\n");
/*select*/
  FD_ZERO(&readfd);              // 将readfd 清空 
FD_SET(sockfd,&readfd);         //将sockfd加入到readfd集合中
  while(1){
  sin_size=sizeof(struct sockaddr_in);
  if(select(MAX_CONNECTED_NO,&readfd,NULL,NULL,(struct timeval(FD_ISSET(sockfd,&readfd)>0){         // FD_ISSET 这个宏判断 sockfd 是否属于可读的文件描述符。从 sockfd 中读入, 输出到标准输出上去.
      if((client_fd=accept(sockfd,(struct sockaddr *)&client_sockaddr,&sin_size))==-1){   //client_sockaddr:客户端地址
        perror("accept");
        exit(1);
      }
      if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))==-1){
        perror("recv");
        exit(1);
      }
      if(read(client_fd,buf,MAXDATASIZE)</netinet></unistd.h></sys></sys></sys></string.h></errno.h></stdlib.h></stdio.h></sys></sys></sys>

以上がLinuxソケットを使用してサーバーに接続する複数のクライアントを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。