久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

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

152次閱讀
沒有評論

共計 4315 個字符,預計需要花費 11 分鐘才能閱讀完成。

這篇“linux socket 怎么實現多個客戶端連接服務器端”文章的知識點大部分人都不太理解,所以丸趣 TV 小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“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 怎么實現多個客戶端連接服務器端”這篇文章的內容,相信大家都有了一定的了解,希望丸趣 TV 小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注丸趣 TV 行業資訊頻道。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-15發表,共計4315字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 宽甸| 琼中| 内江市| 酒泉市| 稻城县| 柳江县| 新余市| 松桃| 会东县| 龙岩市| 都兰县| 昌乐县| 昆明市| 凌海市| 方城县| 宽城| 岑溪市| 西和县| 财经| 监利县| 雅江县| 和平区| 汾西县| 明水县| 南乐县| 宜春市| 上蔡县| 红安县| 临沂市| 始兴县| 汶上县| 肇东市| 宿松县| 灯塔市| 吉木乃县| 满城县| 云林县| 广元市| 舞钢市| 陵川县| 洪江市|