您的位置:首页 > 汽车 > 新车 > 个人主页设计模板图片_摩托车专业网站_软文广告属于什么营销_四川全网推网络推广

个人主页设计模板图片_摩托车专业网站_软文广告属于什么营销_四川全网推网络推广

2025/4/30 23:00:06 来源:https://blog.csdn.net/m0_73359068/article/details/146970028  浏览:    关键词:个人主页设计模板图片_摩托车专业网站_软文广告属于什么营销_四川全网推网络推广
个人主页设计模板图片_摩托车专业网站_软文广告属于什么营销_四川全网推网络推广

前言:
推荐大家阅读一手 详解epoll
重点了解 epoll本质是在操作系统注册了一个事件表,然后将只需要查询"活跃文件操作表"


服务器

无需多言,直接套用固定格式。

  int sockfd = socket(AF_INET, SOCK_STREAM, 0);errif(sockfd == -1, "socket create error");struct sockaddr_in serv_addr;bzero(&serv_addr,sizeof(serv_addr));serv_addr.sin_addr.s_addr=INADDR_ANY;serv_addr.sin_port=htons(8080);serv_addr.sin_family=AF_INET;errif(bind(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr))==-1,"socket bind error");errif(listen(sockfd,SOMAXCONN)==-1,"socket listen error");

说一下 bzero是初始化,将结构体化填充0字符,然后监听和绑定

//epoll 部分
int epfd=epoll_createl(0);//事件表
struct epoll_event events[1024],ev;//等待队列
bzero(&ev,sizeof(ev));
ev.data.fd=sockfd;
ev.events=EPOLLIN|EPOLLET
setnoblock(fd);
epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,-1)//添加数组 简单的实现了一个可读和ET触发监控

ET为边缘触发,即是只报告一次!
直接部分简单的实现了 一个将sockfd添加到epoll维护的事件表上。

//连接部分 
int nfds=epoll_wait(epfd,events,1024,-1);//等待就绪数组errif(nfds==-1,"epoll wait error");//查询for(int i=0; i<nfds;i++) {//连接if(events[i].data.fd==sockfd) {struct sockaddr_in clnt_addr;bzero(&clnt_addr,sizeof(clnt_addr));socklen_t clnt_addr_len=sizeof(clnt_addr);int clnt_sockfd=accept(sockfd,(sockaddr*)&clnt_addr,&clnt_addr_len);errif(clnt_sockfd==-1,"socket accept error");printf("new client fd %d! IP: %s Port: %d\n", clnt_sockfd, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port));//注册struct epoll_event ev;bzero(&ev,sizeof(ev));ev.data.fd=clnt_sockfd;ev.events=EPOLLIN|EPOLLET;setnoblock(clnt_sockfd);epoll_ctl(epfd,EPOLL_CTL_ADD,clnt_sockfd,&ev);}

就如上面那样 先通过epoll_wait 中的等待队列 找出就绪队列,
然后开始"轮询",检测到就绪队列中sockfd有"动作"(这个是tcp/ip),就进行连接,然后上同将客户端的sockfd添加进来。

//业务部分else if (events[i].events&EPOLLIN) {while(true){//读取char buf[1024];bzero(&buf,sizeof(buf));size_t read_bytes=read(events[i].data.fd,buf,sizeof(buf));if(read_bytes>0) {printf("Receive from client %d : %s\n",events[i].data.fd,buf);write(events[i].data.fd,buf,sizeof(buf));}else if(read_bytes==-1&&errno == EINTR) {客户端正常中断、继续读取printf("continue\n");continue;}else if(read_bytes==-1&& ((errno == EAGAIN) || (errno == EWOULDBLOCK))) {//非阻塞IO,这个条件表示数据全部读取完毕printf("finish reading once, errno: %d\n", errno);break;}else if(read_bytes == 0){  //EOF,客户端断开连接printf("EOF, client fd %d disconnected\n", events[i].data.fd);close(events[i].data.fd);   //关闭socket会自动将文件描述符从epoll树上移除break;}}}

检测到可读事件 ,然后进行操作。
简单讲一下阻塞和非阻塞

本质上就是一个异步和非异步的问题,只不过阻塞和非阻塞强调的是io部分的异步操作。在非阻塞模式下,I/O 操作不会等待操作完成,而是立即返回。如果数据尚未准备好,返回值会表明操作未完成(如返回 -1 并设置 errno 为 EAGAIN 或 EWOULDBLOC.为啥还有设置其他两个条件。

客户端

#include<sys/unistd.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include <cstdio>
#include <strings.h>
#include<cstring>void errif(bool condition,const char* errmsg) {if(condition) {perror(errmsg);exit(EXIT_FAILURE);}
}
int main() {int sockfd=socket(AF_INET,SOCK_STREAM,0);errif(sockfd==-1,"create socket error");struct sockaddr_in clnt_addr;clnt_addr.sin_family=AF_INET;clnt_addr.sin_port=htons(8080);clnt_addr.sin_addr.s_addr=inet_addr("127.0.0.1");errif(connect(sockfd,(sockaddr*)&clnt_addr,sizeof(clnt_addr))==-1,"socket connect error");while(true) {char buf[1024];bzero(&buf,sizeof(buf));printf("Enter message: ");scanf("%s",buf);size_t write_bytes=write(sockfd,buf,sizeof(buf));if (write_bytes == -1) {printf("Socket already disconnected, can't write any more!\n");break;}ssize_t read_bytes = read(sockfd, buf, sizeof(buf));if (read_bytes > 0) {printf("Message from server: %s\n", buf);} else if (read_bytes == 0) {printf("Server socket disconnected!\n");break;} else {printf("Socket read error\n");errif(true, "socket read error");return 1;}close(sockfd);}
}

客户端基本上一样,建议参考一下

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com