io复用文章:https://blog.csdn.net/qq_25490573/article/details/102457943

部分函数:getpeername   根据句柄得到ip地址

struct sockaddr_storage addr;

socklen_t len = sizeof(addr);

getpeername(fd,(struct sockaddr *)&addr,&len);

struct sockaddr_in *in = (struct sockaddr_in *)&addr;

inet_ntop(AF_INET,&IN->sin_addr,ipbuf,MAXBUFLEN);

strncmp(buffer, "end", 3)

循环读取只到完毕(解决粘包问题)

 char * packetptr;int isend nbytesneed bytesum;
while(nbytesneed>0)
{isend = read(epollfd,packetptr,nbytesneed);if(isend == -1||isend ==0)break;nbytesneed -=isend;packetptr += isend;bytesum += isend;
}

epoll端代码:

#include "stdio.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "arpa/inet.h"
#include "sys/epoll.h"
#include "fcntl.h"
#include "stdlib.h"
#include <string.h>#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT "6666"
#define CLIENT_NAMBER 128
struct epoll_event ep_ev;
int listen_sock,epoll_fd,control_sock=-1;
struct epoll_event ready_ev[128];
int maxnum = 128;
int timeout = 1000;//设置超时时间 若为-1则永久等待
int ret = 0;
int done = 0;
char buf[1024];
char * databuf;
static int recvstat = 0;
int clientnum[128] = {0};
int creat_socket(char *ip,char *port)
{int sock = socket(AF_INET,SOCK_STREAM,0);if(sock<0){perror("socket");exit(2);}int opt = 1;//设置socket 先断开时 避免进入time_wait状态,属性SO_REUSEADDR,是使其地址能够重用if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))<0){perror("setsockopt");exit(3);}struct sockaddr_in local;local.sin_family = AF_INET;local.sin_port = htons(atoi(port));local.sin_addr.s_addr = inet_addr(ip);if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0){perror("bind");exit(4);}if(listen(sock,5)<0){perror("listen");exit(5);}printf("listen and bind succeed\n");return sock;
}
int set_noblock(int sock)
{int fl = fcntl(sock,F_GETFL);return fcntl(sock,F_SETFL,fl|O_NONBLOCK);
}
void Server_Init()
{databuf = (char*)malloc(1024*128);memset(databuf,'\0',sizeof(databuf));listen_sock = creat_socket(SERVER_ADDR,SERVER_PORT);epoll_fd = epoll_create(255);if(epoll_fd <0){perror("epoll_create");exit(6);}ep_ev.events = EPOLLIN;ep_ev.data.fd = listen_sock;if (epoll_ctl(epoll_fd,EPOLL_CTL_ADD,listen_sock,&ep_ev)<0){perror("epoll_ctl");exit(7);}clientnum[0] = listen_sock;memset(buf,'\0',sizeof(buf));
}
void creattoclient(int fd){for (int i = 0; i < CLIENT_NAMBER; ++i){if(clientnum[i]!=0){}else{clientnum[i] = fd;return;}}
}
void deletetoclient(int fd){for (int i = 0; i < CLIENT_NAMBER; ++i){if(clientnum[i]!=0){if(clientnum[i] == fd)clientnum[i] = 0;}else{return;}}
}
void Epoll_Listen()
{while(!done){if (recvstat==1){}else if (recvstat == 0){memset(databuf,'\0',sizeof(databuf));}switch(ret = epoll_wait(epoll_fd,ready_ev,maxnum,timeout)){case -1:perror("epoll_wait");exit(8);break;case 0:recvstat = -1;//      perror("time out ...\n");break;default://      printf("a new sigle!\n");       for (int i = 0; i < ret; ++i){//判断是否是监听套接字,是的话acceptint fd = ready_ev[i].data.fd;if ((fd==listen_sock)&&(ready_ev[i].events&EPOLLIN)){struct sockaddr_in remote;socklen_t len = sizeof(remote);int accept_sock = accept(listen_sock,(struct sockaddr*)&remote,&len);if (accept<0){perror("accept");continue;}//printf("accept a clinent..[ip]:%s,[port]:%d\n",inet_ntoa(remote.sin_addr),ntohs(remote.sin_port));ep_ev.events = EPOLLIN|EPOLLET;ep_ev.data.fd = accept_sock;set_noblock(accept_sock);if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,accept_sock,&ep_ev)<0){perror("epoll_ctl");close(accept_sock);}creattoclient(accept_sock);}else{if(ready_ev[i].events&EPOLLIN){//申请空间同时存文件描述符合缓冲区地址memset(buf,'\0',sizeof(buf));fflush(stdout);ssize_t _s = recv(fd,buf,sizeof(buf)-1,0);if (control_sock!=0){if(buf=="control:connect")control_sock = fd;}else if(control_sock == fd){if (!strncasecmp(buf,"quit",4)){exit(0);}}if (_s<0){perror("recv");continue;}else if(_s==0){deletetoclient(fd);epoll_ctl(epoll_fd,EPOLL_CTL_DEL,fd,NULL);close(fd);}else{strcat(databuf,buf);//printf("client#%s\n",buf);recvstat = 1;// ep_ev.data.fd = fd;// ep_ev.events = EPOLLOUT|EPOLLET;// epoll_ctl(epoll_fd,EPOLL_CTL_MOD,fd,&ep_ev);}}else if(ready_ev[i].events&EPOLLOUT){//const char * msg = ".................";if (databuf[0]!='\0'){send(fd,databuf,strlen(databuf),0);}//   epoll_ctl(epoll_fd,EPOLL_CTL_DEL,fd,NULL);//   close(fd);}}}break;}if(recvstat == 1){ep_ev.events = EPOLLOUT|EPOLLET;for (int i = 0; i < CLIENT_NAMBER; ++i){if(clientnum[i]==0){continue;}ep_ev.data.fd = clientnum[i];epoll_ctl(epoll_fd,EPOLL_CTL_MOD,clientnum[i],&ep_ev);}}else if(recvstat == 0){ep_ev.events = EPOLLIN|EPOLLET;for (int i = 0; i < CLIENT_NAMBER; ++i){if(clientnum[i]==0){continue;}ep_ev.data.fd = clientnum[i];epoll_ctl(epoll_fd,EPOLL_CTL_MOD,clientnum[i],&ep_ev);}}}
}int main(int argc,char *argv[])
{Server_Init();Epoll_Listen();
}

qt工程:

主线程.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <stdio.h>
#include <unistd.h>#include <QMainWindow>
#include "conturlserver.h"namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();void addevent();signals:void sendinfo(QString);
public slots:void showrecvtext(QString);private:Ui::MainWindow *ui;conturlserver * sockthread;};#endif // MAINWINDOW_H

MainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);sockthread = new conturlserver;addevent();
}
void MainWindow::addevent(){connect(ui->start,&QPushButton::clicked,sockthread,&conturlserver::timejishi);connect(ui->stop,&QPushButton::clicked,[=](){if(sockthread->isRunning()){emit sendinfo("control:gameover");}});connect(this,&MainWindow::sendinfo,sockthread,&conturlserver::sendinfo);connect(ui->send,&QPushButton::clicked,[=](){QString str = ui->sendtext->text();emit sendinfo(str);ui->sendtext->setText("");});connect(sockthread,&conturlserver::recviinfor,this,&MainWindow::showrecvtext);
}void MainWindow::showrecvtext(QString info){ui->recvtext->append(info);
}MainWindow::~MainWindow()
{delete ui;
}

子线程conturlserver.h

#ifndef CONTURLSERVER_H
#define CONTURLSERVER_H#include "QThread"
#include "QDebug"
#include "QTcpServer"
#include "QHostAddress"
#include "QTcpSocket"
#include "QTimer"class conturlserver : public QThread
{Q_OBJECT
public:conturlserver();void run();signals:void recviinfor(QString info);
public slots:void sendinfo(QString info);void timejishi();private:QHostAddress myaddr;QTcpServer * mytcpfd;QTcpSocket * mysockfd;quint16 port = 6666;QTimer *timeout;QTimer *writetime;QByteArray recvdata;QByteArray senddata;bool sockstat;};#endif // CONTURLSERVER_H

子线程conturlserver.cpp

#include "conturlserver.h"conturlserver::conturlserver()
{myaddr = "192.168.10.127";mysockfd = new QTcpSocket(this);writetime = new QTimer(this);connect(writetime,&QTimer::timeout,[=](){});
}void conturlserver::run(){sockstat = false;if(mysockfd->ConnectedState == QAbstractSocket::UnconnectedState){emit recviinfor("sockect is busying!!!\n");return;}while(1){if(mysockfd->isReadable()){recvdata = mysockfd->read(1024);if(!recvdata.isEmpty())emit recviinfor(recvdata.data());}sleep(1);}}void conturlserver::timejishi(){mysockfd->connectToHost(myaddr,port);if(mysockfd->waitForConnected()){mysockfd->write(QByteArray("control:connect"));this->start();emit recviinfor("sockect is connect success!!!\n");}else{emit recviinfor("sockect connecting is failder...\n");this->exit();}
}void conturlserver::sendinfo(QString info){senddata = info.toLatin1();if(mysockfd->isWritable()){qint64 i = mysockfd->write(senddata);if(i>0){if(senddata=="control:gameover"){emit recviinfor("epoll_server quit !!!\n");this->exit();}}}else{emit recviinfor("send faile...\n");}
}

Linux服务器开发实战——QT控制界面+epoll聊天服务相关推荐

  1. 红黑树在linux内核中的应用场景(红黑树,进程管理CFS,内存管理)丨epoll丨c/c++linux服务器开发丨linux后台开发

    红黑树在linux内核中的应用场景(红黑树,进程管理CFS,内存管理) 视频讲解如下: 红黑树在linux内核中的应用场景(红黑树,进程管理CFS,内存管理)丨epoll丨c/c++linux服务器开 ...

  2. 深入分析websocket协议,从3个方面设计网络应用层协议丨网络编程|网络IO|epoll|socket|网络协议丨c/c++linux服务器开发

    深入分析websocket协议,从3个方面设计网络应用层协议 视频讲解如下: 深入分析websocket协议,从3个方面设计网络应用层协议丨网络编程|网络IO|epoll|socket|网络协议丨c/ ...

  3. epoll原理剖析以及reactor模型应用丨网络编程|网络IO|select|poll|socket|reactor多核实现丨c/c++linux服务器开发

    epoll原理剖析以及reactor模型应用 视频讲解如下,点击观看: epoll原理剖析以及reactor模型应用丨网络编程|网络IO|select|poll|socket|reactor多核实现丨 ...

  4. 90分钟详解网络编程相关的细节处理丨 reactor丨网络io丨epoll丨C/C++丨Linux服务器开发丨后端开发丨Linux后台开发

    90分钟搞懂网络编程相关细节处理 1. 网络编程四要素 2. io多路复用 3. reactor三种基础封装方式 视频讲解如下,点击观看: 90分钟详解网络编程相关的细节处理丨 reactor丨网络i ...

  5. Linux服务器开发初步

      服务器开发需要考虑的内容很多,比如服务器的架构.稳定性.性能以及负载能力等等. 事实上,在开发服务器的过程中,需要综合考虑各种因素,比如就客户端连接时间较短却又比较频繁的服务器(例如HTTP服务器 ...

  6. php服务器视频教程,从PHP基础到实战高手 高性能Linux服务器构建实战 千峰教育PHP全新版高级视频教程...

    从PHP基础到实战高手 高性能Linux服务器构建实战 千峰教育PHP全新版高级视频教程 非常厉害的一套PHP实战课程,系统的学习完成后可以从零基础的PHP新手, 成长为能独立完成高性能服务器部署的实 ...

  7. C/C++Linux服务器开发高级架构师/Linux后台开发架构师丨高级进阶学习

    01 课程介绍 [录播]课程介绍(66分钟) 免费试学 [录播]磁盘存储链式的B树与B+树(131分钟) 免费试学 免费学习视频链接点击:C/C++Linux服务器开发高级架构师/Linux后台架构师 ...

  8. 【零声教育】C/C++Linux服务器开发/高级架构师 课程

    随着去年年底的疫情,很多线下的学习都变成了网课的形式,各种付费学习也萌生出来,很多决定要报名付费网课例如零声学院C/C++linux后台服务器高级架构师的程序员,报名之前总会问我这样一个问题,除了视频 ...

  9. 关于2022年12代C/C++Linux服务器开发高级架构师课程体系分析

    对于零声教育的C/C++Linux服务器高级架构师的课程到2022目前已经迭代到12代了,像之前小编也总结过,但是课程每期都有做一定的更新,也是为了更好的完善课程跟上目前互联网大厂的岗位技术需求,之前 ...

  10. C/C++Linux服务器开发完整学习路线(含免费学习资料下载地址)

    C/C++Linux服务器开发完整学习路线(含免费学习资料下载地址) 相信大部分同学刚毕业或者想转行做c++服务端开发的时候都很迷茫不知道从哪里开始学习,于是准备参加各种培训班或者网络培训,有不知道该 ...

最新文章

  1. 1048 数字加密 (20 分)java
  2. Mysql VARCHAR(X) vs TEXT
  3. 技术人如何自我提升?阿里技术带来丰富学习资源
  4. 读取无线手柄数据_《宇宙机器人》×PS5手柄使用体验:登月级进化
  5. 2017.0613.《计算机组成原理》总线控制-通信控制
  6. windows下OpenSSL加密证书安装步骤与使用方法
  7. 使用jQuery的ajax同步请求吃过的亏
  8. 《深入浅出DPDK》读书笔记(十二):DPDK虚拟化技术篇(半虚拟化Virtio)
  9. 数据访问类用静态方法。。。当多个人调用时返回值会返回别人的?。。。特别奇怪的问题???...
  10. 静态路由的不通配置方式
  11. 【转贴】没有div没有float没有clear没有hack的超强CSS布局
  12. 快手AI技术副总裁郑文:为什么说AI是短视频平台的核心能力
  13. javaweb网上人才招聘系统的设计与实现
  14. 国开大学计算机原理边学边练,国家开放大学计算机组成原理
  15. Android 长按Menu键的监听
  16. net_speeder发双倍包加速
  17. python 爬取《时间的形状》微信公号
  18. 你看这雪花如此的美丽
  19. Windows内核安全与驱动编程学习笔记----1.WDK安装
  20. 微服务拆分:业务横向拆分和纵向拆分

热门文章

  1. leetcode-739:每日温度
  2. manjaro 安装搜狗拼音输入法
  3. 读书笔记:《Being Mortal》
  4. Rosalind第11题:Mortal Fibonacci Rabbits
  5. 博客显示ip签名图片html代码,如何制作显示IP的签名图片
  6. 线性代数【8】-1 线性方程组 - 非常重要的概念 - 三个基本的问题
  7. 算法系列之算法学习书籍以及资料推荐
  8. R语言期末考试复习题第一天整理内容(自己整理+参考博主:紧到长不胖 )请多关注 紧到长不胖 ,每天有惊喜!
  9. 宁录哨兵机器人_当天启碰上哨兵机器人孰强孰弱?这部漫画给出了答案!
  10. ibm的odm使用_使用IBM ODM API生成规则工件