select函数用法
- long val = fcntl(sockfd,F_GETFL); //把sockfd套接字的属性拿出来给val
- val|=O_NONBLOCK; //把非阻塞的属性O_NONBLOCK加进去,用或运算
- fcntl(sockfd,F_SETFL,val); //再把做好的属性val,再加到sockfd中去
struct timeval *timeout; //控制select()如何返回,是非阻塞,还是阻塞一定时间返回,还是直接有文件描述符有响应才返回。
- //TCP服务端
- #include"myhead.h"
- struct client_list
- {
- int sock;
- struct client_list *next;
- };
- struct client_list *head = NULL;
- struct client_list *init_list(struct client_list*head)
- {
- head = malloc(sizeof(struct client_list));
- head->sock = -1;
- head->next = NULL;
- return head;
- }
- //新的客户端加到客户端队列中
- int add_sock(struct client_list*head,int new_sock)
- {
- struct client_list *p = head;
- struct client_list *new_node = malloc(sizeof(struct client_list));
- new_node->sock = new_sock;
- new_node->next = NULL;
- while(p->next!=NULL)
- {
- p = p->next;
- }
- p->next = new_node;
- return 0;
- }
- //找出最大的文件描述符
- int find_max(struct client_list*head)
- {
- struct client_list *p = head->next;
- if(p==NULL)
- return 0;
- int max_sd = p->sock;
- for(p;p!=NULL;p=p->next)
- {
- if(max_sd < p->sock)
- max_sd = p->sock;
- }
- return max_sd;
- }
- //信息转发给其他客户端
- int write_to_client(struct client_list*head,char *wbuf,int size)
- {
- struct client_list *p=head;
- for(p=head->next;p!=NULL;p=p->next)
- {
- write(p->sock,wbuf,size);
- }
- return 0;
- }
- //当有新的客户端作为新的文件描述符加进来时,显示客户端列表中的所有客户端文件描述符
- void show_client_list(struct client_list*head)
- {
- struct client_list *p = head;
- if(p->next == NULL)
- {
- printf("IS A EMPTY LIST!\n");
- return ;
- }
- else
- {
- puts("client_list is :");
- for(p =head->next; p!=NULL;p = p->next)
- {
- printf("%d ",p->sock);
- }
- printf("\n");
- }
- }
- <pre class="cpp" name="code">//取消退出客户端的结点。
- int del_node(struct client_list*head,int sock)
- {
- struct client_list *p = head->next;
- struct client_list *q = head;
- while(p!=NULL)
- {
- if(p->sock == sock)
- {
- q->next = p->next;
- free(p);
- p = NULL;
- }
- else
- {
- p = p->next;
- q = q->next;
- }
- }
- return 0;
- }
- int main(int argc, char const *argv[])
- {
- char rbuf[50]={0};
- char wbuf[50]={0};
- int sockfd,size,on=1;
- int new_sock;
- int max_sd;
- struct client_list *pos;
- struct timeval timeout = {0,0}; //设置select为非阻塞返回
- fd_set fdset;
- long val;
- head = init_list(head); //初始化客户端链表。
- pos = head;
- struct sockaddr_in saddr;
- struct sockaddr_in caddr;
- size = sizeof(struct sockaddr_in);
- bzero(&saddr,size);
- saddr.sin_family = AF_INET;
- saddr.sin_port = htons(8888);
- saddr.sin_addr.s_addr = htonl(INADDR_ANY);
- sockfd = socket(AF_INET,SOCK_STREAM,0);
- setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));//设置socket套接字为复用,不设也可以
- //把sockfd设置为非阻塞
- val = fcntl(sockfd,F_GETFL);
- val|=O_NONBLOCK;
- fcntl(sockfd,F_SETFL,val);
- bind(sockfd,(struct sockaddr*)&saddr,size);
- listen(sockfd,10);
- while(1)
- {
- new_sock = accept(sockfd,(struct sockaddr*)&caddr,&size);//循环接受新连接的客户端
- if (new_sock!= -1)
- {
- puts("new node come!\n");
- printf("new_sock = %d\n",new_sock);
- add_sock(head,new_sock);
- show_client_list(head);
- }
- max_sd = find_max(head); //从客户端队列中,找出最大的文件描述符
- FD_ZERO(&fdset); //清空文件描述符集
- pos = head;
- //把每个套接字加入到集合中
- if(pos->next != NULL) //若套接字列表不是空
- {
- for(pos=head->next;pos!=NULL;pos=pos->next)
- {
- FD_SET(pos->sock,&fdset);
- }
- }
- select(max_sd+1,&fdset,NULL,NULL,&timeout); //等待描述符
- for(pos=head->next;pos!=NULL;pos = pos->next) //检查哪个套接字有响应
- {
- if(FD_ISSET(pos->sock,&fdset)) //判断pos->sock这个文件描述符指向的客户端有没有数据写过来
- {
- bzero(rbuf,50);
- read(pos->sock,rbuf,50);
- printf("%s\n",rbuf);
- if(strcmp(rbuf,"quit")==0) //若客户端发来的信息为quit,则取消这个客户端的结点。
- {
- del_node(head,pos->sock);
- }
- write_to_client(head,rbuf,50); //把写过来的信息转发给队列中的其他客户端。
- }
- }
- }
- return 0;
- }</pre>
- <pre></pre>
- <br>
- //客户端
- #include"myhead.h"
- int main(int argc, char const *argv[])
- {
- int sockfd;
- char rbuf[50]={0};
- char wbuf[50]={0};
- char ipbuf[50]={0};
- int port;
- int max_sd;
- int size,on=1;
- int ret;
- fd_set fdset;
- struct sockaddr_in saddr;
- size = sizeof(struct sockaddr_in);
- saddr.sin_family = AF_INET;
- saddr.sin_port = htons(8888);
- saddr.sin_addr.s_addr = inet_addr("192.168.152.128");
- sockfd = socket(AF_INET,SOCK_STREAM,0);
- setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
- ret = connect(sockfd,(struct sockaddr*)&saddr,size);
- if(ret ==0)
- {
- printf("connect sucess\n");
- inet_ntop(AF_INET,(void*)&saddr.sin_addr.s_addr,ipbuf,50);
- port = ntohs(saddr.sin_port);
- printf("ip:%s,port:%d\n",ipbuf,port);
- }
- else if(ret == -1)
- {
- printf("failed to connect\n");
- return -1;
- }
- while(1)
- {
- FD_ZERO(&fdset);
- FD_SET(sockfd,&fdset); //把监测服务端的描述符集放到集合中
- FD_SET(STDIN_FILENO,&fdset); //STDIN_FILENO这个文件描述符用于监测标准输入(键盘)
- max_sd = sockfd>STDIN_FILENO?sockfd:STDIN_FILENO;
- select(max_sd+1,&fdset,NULL,NULL,NULL); //这里的select是设置为一直阻塞到有文件描述符发生响应
- if(FD_ISSET(sockfd,&fdset)) //判断是否服务端有数据发过来
- {
- bzero(rbuf,50);
- read(sockfd,rbuf,50);
- printf("%s\n",rbuf);
- }
- if(FD_ISSET(STDIN_FILENO,&fdset)) //判断键盘是否有数据传过来
- {
- bzero(wbuf,50);
- scanf("%s",wbuf);
- write(sockfd,wbuf,50); //把键盘传过来的数据发给服务端
- if(strcmp(wbuf,"quit")==0) //若键盘过来的数据为quit,则关闭这个客户端
- {
- printf("quit!\n");
- return 0;
- }
- }
- }
- return 0;
- }
select函数用法相关推荐
- linux c语言 select函数用法
原文地址:点击打开链接 linux c语言 select函数用法 Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如 co ...
- linux select函数用法
select系统调用是用来让我们的程序监视多个文件句柄的状态变化的.程序会停在select这里等待,直到被监视的文件句柄有一个或多个发生了状态改变.关于文件句柄,其实就是一个整数,我们最熟悉的句柄是0 ...
- select函数用法详解
1. select函数 select的作用: 轮询的方式,从多个文件描述符中获取状态变化后的情况. 头文件 #include <sys/time.h> //for struct timev ...
- select函数用法详解,及实例分析
select函数是系统调用函数,用于多路监控.当没有一个文件满足要求时,select将阻塞调用进程.在有些情况下,采用select函数可以大大简化程序结构.比如一个系统有10个输入设备,如果想实时读取 ...
- linux之select函数用法详解
select系统调用是用来让我们的程序监视多个文件句柄(file descriptor)的状态变化的.程序会停在select这里等待,直到被监视的文件句柄有某一个或多个发生了状态改变. 何为文件句 ...
- select()函数用法
select的函数格式(我所说的是Unix系统下的伯克利socket编程,和windows下的有区别,一会儿说明): int select(int maxfdp,fd_set *readfds,fd_ ...
- select 函数用法
Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect.accept.recv或recvfrom这样的阻塞程序( ...
- C++网络编程Select函数用法
Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如 connect.accept.recv或recvfrom这样的阻塞程序 ...
- select函数(一)
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); ...
最新文章
- 小猿圈讲解Java可以做什么?
- c++中结构体套结构体用 = {0}初始化编译报错解决办法(用memset或者={})(error: invalid conversion)
- 全国计算机二级vb得分技巧,全国计算机等级考试二级VB笔试各题型答题技巧(2)...
- 复习Python DB-API
- JDK8 Stream 操作
- 安全计算:AVG免费版提供免费病毒防护
- Ubuntu联网安装GCC
- halcon自动对焦
- 为什么要用大写L替换小写L(l),idea提醒literal ‘xxx‘ ends with lowercase ‘l‘
- [欣赏]——天长地久
- 中值滤波medianBlur函数的使用示例程序
- 飞腾cpu服务器浪潮信息,推动国产化进程 浪潮发布飞腾服务器
- evga x58服务器芯片组,何谓板皇?四大顶级X58主板巅峰对决
- 饥荒联机版-Centos7-阿里云服务器-搭建
- 解决 plt.savefig() 生成空白图片的问题
- 360 android系统 流量,360手机卫士Android版增流量监控
- stm32按键控制mg90s数字舵机、pwm调节舵机转动角度
- 阳性感染者被要求带病上班?广东省人社厅:阳性感染者应居家隔离
- u8用友服务器系统在哪,用友u8数据库服务器在哪
- 快速入门Unity机器学习:一: