中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

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

德兴市| 云和县| 祁阳县| 富宁县| 友谊县| 筠连县| 武冈市| 安顺市| 谷城县| 元谋县| 隆回县| 新密市| 威信县| 喀什市| 兴化市| 库尔勒市| 湖州市| 什邡市| 天峨县| 锡林郭勒盟| 大邑县| 许昌市| 疏勒县| 谢通门县| 大竹县| 大宁县| 正定县| 乌苏市| 措勤县| 名山县| 昌乐县| 饶平县| 营口市| 黎平县| 同江市| 通道| 兖州市| 额尔古纳市| 太白县| 怀远县| 宾阳县|