您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

linux socket怎么实现多个客户端连接服务器端

2024/2/24 7:33:55发布34次查看
一、引言
    在实际情况中,人们往往遇到多个客户端连接服务器端的情况。由于之前介绍的函数如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 100int 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]# ./fcntlsocket success!,sockfd=3bind 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){         // 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]# ./select1socket create success!bind success!listening...
以上就是linux socket怎么实现多个客户端连接服务器端的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product