亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

linux socket怎么實現多個客戶端連接服務器端

發布時間:2022-10-19 14:55:00 來源:億速云 閱讀:205 作者:iii 欄目:建站服務器

這篇“linux socket怎么實現多個客戶端連接服務器端”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“linux socket怎么實現多個客戶端連接服務器端”文章吧。

一、引言

    在實際情況中,人們往往遇到多個客戶端連接服務器端的情況。由于之前介紹的函數如connect,recv,send等都是阻塞性函數,若資源沒有充分準備好,則調用該函數的進程將進入睡眠狀態,這樣就無法處理I/O多路復用的情況了。

    本文給出兩種I/O多路復用的方法:fcntl(),select()。可以看到,由于Linux中把socket當作一種特殊的文件描述符,這給用戶的處理帶來很大方便。

二、fcntl

fcntl()函數有如下特性:

1)非阻塞I/O: 可將cmd 設為F_SETFL,將lock設為O_NONBLOCK

2)信號驅動I/O:可將cmd設為F_SETFL,將lock設為O_ASYNC.

例程:

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
#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))<0)
      perror("fcntl F_SETFL");
    flags |= O_NONBLOCK;
    if(fcntl( sockfd, F_SETFL,flags)<0)
      perror("fcntl");
  while(1){
    sin_size=sizeof(struct sockaddr_in);
    if((client_fd=accept(sockfd,(struct sockaddr*)&client_sockaddr,&sin_size))==-1){  //服務器接受客戶端的請求,返回一個新的文件描述符
      perror("accept");
      exit(1);
    }
    if((recvbytes=recv(client_fd,buf,MAXDATASIZE,0))==-1){
      perror("recv");
      exit(1);
    }
    if(read(client_fd,buf,MAXDATASIZE)<0){
      perror("read");
      exit(1);
    }
    printf("received a connection :%s",buf);

/*關閉連接*/
  close(client_fd);
  exit(1);
  }/*while*/
}

運行該程序:

[root@localhost net]# ./fcntl
socket success!,sockfd=3
bind success!
listening....
accept: Resource temporarily unavailable

可以看到,當accept的資源不可用時,程序會自動返回。

若將紅色加粗代碼替換為:

if((flags=fcntl( sockfd, F_SETFL, 0))<0)
      perror("fcntl F_SETFL");
    flags |= O_ASYNC;
    if(fcntl( sockfd, F_SETFL,flags)<0)
      perror("fcntl");

運行結果如下:

[root@localhost net]# ./fcntl1
socket success!,sockfd = 3
bind success!
listening...

可以看到,進程一直處于等待中,直到另一相關信號驅動它為止。

三、select

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.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;
  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)<0){
        perror("read");
        exit(1);
      }
      printf("received a connection :%s",buf);
    }/*if*/
    close(client_fd);
    }/*select*/
  }/*while*/
}
運行結果如下:
[root@localhost net]#  gcc select1.c -o select1
[root@localhost net]# ./select1
socket create success!
bind success!
listening...

以上就是關于“linux socket怎么實現多個客戶端連接服務器端”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

东台市| 慈利县| 元氏县| 淄博市| 鹤峰县| 友谊县| 长武县| 克东县| 石棉县| 鄂托克前旗| 临海市| 自治县| 黄冈市| 成都市| 黄大仙区| 洪湖市| 特克斯县| 松桃| 隆化县| 固安县| 礼泉县| 弥渡县| 富源县| 宜君县| 辉县市| 肥东县| 柏乡县| 镇原县| 玉山县| 通州区| 青川县| 双鸭山市| 比如县| 郯城县| 五寨县| 大荔县| 荆州市| 体育| 黄石市| 筠连县| 万全县|