(四) 用poll实现TCP服务端
来源:互联网 发布:在vb中chr是什么意思 编辑:程序博客网 时间:2024/05/20 20:56
1.首先,大概说一下poll函数的工作大概:(包含在#include<poll.h>当中)
poll 是通过监听一个结构体变量来对 文件描述符进行监听的(当然,socket也算是一个文件描述符)
这个结构体的大概结构是:
(!!如果不想了解poll工作原理的。可以直接拉下去看代码)
struct pollfd //这个结构体一般会被定义为结构体数组{ int fd; //要监听的文件描述符 short events; //期待fd发生的事件 ,其中 events把他设置成 POLLIN就够用了,表示检测该fd有没有可读数据 short revents; //fd实际发生的事件};
而poll()是通过监听上述结构体数组 来监听一堆文件描述符的
2.再来了解poll()函数详细信息:
(一)首先是他的输入参数:
int poll(struct pollfd *name,int num,int timeout);
一共有三个,分别是监听的结构体数组的数组名,实际监听着多少个结构体数组成员,阻塞时间控制参数。
其中timeout参数 ==0,是非阻塞,== -1 是阻塞,>0是阻塞 xx毫秒
(一)首先是他的输入参数:
int poll(struct pollfd *name,int num,int timeout);
一共有三个,分别是监听的结构体数组的数组名,实际监听着多少个结构体数组成员,阻塞时间控制参数。
其中timeout参数 ==0,是非阻塞,== -1 是阻塞,>0是阻塞 xx毫秒
(二)然后是他的返回值
poll()函数的返回值 ,表示同时有响应的文件描述符个数。
poll()函数的返回值 ,表示同时有响应的文件描述符个数。
接下来看看 poll()的大致使用例子:
3.给出代码:(在这之前先看看代码的大致实现逻辑)
首先把 监听套接字sock 和 标准输入 先放到 监听的结构体数组中
while(1)循环是必须的,在循环中,用poll()进行监听,然后判断是sock是否响应,是的话,就调用accept来获取连接进来的客户端的信息,并把接收到的socket放到结构体数组中。否则就继续往下(判断是否标准输入响应,是就读信息),再往下,判断是哪些客户端socket发生可读响应,有的话,就读。
//服务端#include"myhead.h"#define CLI_NUM 10char rbuf[50];char wbuf[50];char ipbuf[50];int recv_num;struct pollfd pollfd[CLI_NUM];void write_all(char *wbuf,int max){int i = 2;for(i;i<(max+2);i++){write(pollfd[i].fd,wbuf,50);}}int main(){int sockfd;int size,port;int new_sock;int on = 1;int i;int max = 0;int ret;struct sockaddr_in saddr;struct sockaddr_in caddr;size = sizeof(struct sockaddr_in);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));bind(sockfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr));listen(sockfd,10);//init pollfdfor(i=0;i<10;i++) //把pollfd置 -1,当然不一定是-1,只是文件描述符不可能为负,所以就置成一个负数{pollfd[i].fd = -1;}pollfd[0].fd = sockfd;pollfd[0].events = POLLIN;pollfd[1].fd = STDIN_FILENO;pollfd[1].events = POLLIN;int len = sizeof(struct sockaddr);while(1){puts("waiting poll");ret = poll(pollfd,max+2,-1); //ret表示发生响应的文件描述符个数,接下来就要对这些响应的文件描述符都处理一次if(ret ==0){perror("timeout");exit(-1);}if((pollfd[0].revents& POLLIN) == POLLIN){puts("waiting accept");new_sock = accept(sockfd,(struct sockaddr*)&caddr,&len);write(new_sock,"get",4);if(new_sock>0){//fcntl(new_sock,F_SETFL,fcntl(new_sock,F_GETFL)|O_NONBLOCK);printf("newfd =%d\n",new_sock);i = 2;for(i;i<CLI_NUM;i++){if(pollfd[i].fd != -1)continue;else if(pollfd[i].fd == -1){pollfd[i].fd = new_sock;pollfd[i].events = POLLIN;max +=1;printf("max=%d\n",max);ret-=1; //每处理一个就 -1if(ret <= 0 ) //要是响应的文件描述符都处理完了,就退出循环。{break;}}}}}if((pollfd[1].revents & POLLIN) == POLLIN) //是否从键盘有信息读入{bzero(wbuf,50);scanf("%s",wbuf);write_all(wbuf,max); ret-=1; //每处理一个就 -1if(ret<=0)continue;}for(i=2;i<CLI_NUM && pollfd[i].fd!=-1;i++) //接收来自其他客户端的信息{if((pollfd[i].revents & POLLIN)==POLLIN){puts("enter read");bzero(rbuf,50);recv_num = recv(pollfd[i].fd,rbuf,50,0);if(recv_num == 0) //当recv_num 为0,表示客户端已经退出了{printf("client close\n");close(pollfd[i].fd);pollfd[i].fd = -1; //既然客户端退出了,那原本该客户端占着的位置就重新置 -1continue;}printf("%s,from:%d\n",rbuf,pollfd[i].fd);write_all(rbuf,max);ret -=1; if(ret<=0)break;}}}}
接下来是客户端:
//客户端相对而言就比较简单
#include"myhead.h"char rbuf[50];char wbuf[50];char ipbuf[50];int main(){int sockfd;int ret,port;struct pollfd pollfd[2];struct sockaddr_in saddr;int size = sizeof(struct sockaddr_in);bzero(&saddr,size);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);ret=connect(sockfd,(struct sockaddr*)&saddr,sizeof(struct sockaddr));if(ret == 0){inet_ntop(AF_INET,(void*)&saddr.sin_addr.s_addr,ipbuf,50);port = ntohs(saddr.sin_port);printf("%s,%d\n",ipbuf,port);}pollfd[0].fd = STDIN_FILENO;pollfd[0].events = POLLIN;pollfd[1].fd = sockfd;pollfd[1].events = POLLIN;while(1){poll(pollfd,2,-1);if((pollfd[0].revents & POLLIN)==POLLIN){puts("message from keyboard");bzero(wbuf,50);scanf("%s",wbuf);write(sockfd,wbuf,50);}if((pollfd[1].revents & POLLIN)==POLLIN){bzero(rbuf,50);read(sockfd,rbuf,50);printf("%s\n",rbuf);}}return 0;}
0 0
- (四) 用poll实现TCP服务端
- 实现TCP并发服务器之四(poll函数)
- poll服务端代码实现
- (五)epoll实现TCP服务端
- (六)多进程实现TCP服务端
- TCP小型服务器(poll)
- WinSock客户端服务端实现--TCP
- node.js tcp服务端实现
- TCP通讯(服务端)
- linux网络编程之用socket实现简单客户端和服务端的通信(基于TCP)
- Socket的实现,服务端和客户端(TCP)
- 客户端与服务端的TCP通信实现(Qt)
- linux C++ poll实现的聊天室程序 客户端----服务端
- 使用poll实现的io多路复用服务端和客户端
- poll服务端程序例子
- Mina框架实现最简单的服务端(四)
- 远程服务HttpInvoker源码解析(四)服务端实现
- Linux网络编程——tcp并发服务器(poll实现)
- pbpaste & pbcopy in Mac OS X (or: Terminal + Clipboard = Fun!)
- iso checksum 文件使用
- 通过ThoughtWorks.QRCode和ZXing识别二维码
- 欢迎使用CSDN-markdown编辑器
- 羽毛球杂说
- (四) 用poll实现TCP服务端
- 多线程程序中操作的原子性
- Spring核心框架体系结构
- GitHud中重要的命令(随时需要用到)
- Linux下进程同步问题小例
- C语言宏的几个注意点
- Convolutional Neural Networks (CNNs / ConvNets) 翻译第二段
- div a标签的隐藏/显示
- 主流JS框架中DOMReady事件的实现