Linux服务器开发实战——QT控制界面+epoll聊天服务
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聊天服务相关推荐
- 红黑树在linux内核中的应用场景(红黑树,进程管理CFS,内存管理)丨epoll丨c/c++linux服务器开发丨linux后台开发
红黑树在linux内核中的应用场景(红黑树,进程管理CFS,内存管理) 视频讲解如下: 红黑树在linux内核中的应用场景(红黑树,进程管理CFS,内存管理)丨epoll丨c/c++linux服务器开 ...
- 深入分析websocket协议,从3个方面设计网络应用层协议丨网络编程|网络IO|epoll|socket|网络协议丨c/c++linux服务器开发
深入分析websocket协议,从3个方面设计网络应用层协议 视频讲解如下: 深入分析websocket协议,从3个方面设计网络应用层协议丨网络编程|网络IO|epoll|socket|网络协议丨c/ ...
- epoll原理剖析以及reactor模型应用丨网络编程|网络IO|select|poll|socket|reactor多核实现丨c/c++linux服务器开发
epoll原理剖析以及reactor模型应用 视频讲解如下,点击观看: epoll原理剖析以及reactor模型应用丨网络编程|网络IO|select|poll|socket|reactor多核实现丨 ...
- 90分钟详解网络编程相关的细节处理丨 reactor丨网络io丨epoll丨C/C++丨Linux服务器开发丨后端开发丨Linux后台开发
90分钟搞懂网络编程相关细节处理 1. 网络编程四要素 2. io多路复用 3. reactor三种基础封装方式 视频讲解如下,点击观看: 90分钟详解网络编程相关的细节处理丨 reactor丨网络i ...
- Linux服务器开发初步
服务器开发需要考虑的内容很多,比如服务器的架构.稳定性.性能以及负载能力等等. 事实上,在开发服务器的过程中,需要综合考虑各种因素,比如就客户端连接时间较短却又比较频繁的服务器(例如HTTP服务器 ...
- php服务器视频教程,从PHP基础到实战高手 高性能Linux服务器构建实战 千峰教育PHP全新版高级视频教程...
从PHP基础到实战高手 高性能Linux服务器构建实战 千峰教育PHP全新版高级视频教程 非常厉害的一套PHP实战课程,系统的学习完成后可以从零基础的PHP新手, 成长为能独立完成高性能服务器部署的实 ...
- C/C++Linux服务器开发高级架构师/Linux后台开发架构师丨高级进阶学习
01 课程介绍 [录播]课程介绍(66分钟) 免费试学 [录播]磁盘存储链式的B树与B+树(131分钟) 免费试学 免费学习视频链接点击:C/C++Linux服务器开发高级架构师/Linux后台架构师 ...
- 【零声教育】C/C++Linux服务器开发/高级架构师 课程
随着去年年底的疫情,很多线下的学习都变成了网课的形式,各种付费学习也萌生出来,很多决定要报名付费网课例如零声学院C/C++linux后台服务器高级架构师的程序员,报名之前总会问我这样一个问题,除了视频 ...
- 关于2022年12代C/C++Linux服务器开发高级架构师课程体系分析
对于零声教育的C/C++Linux服务器高级架构师的课程到2022目前已经迭代到12代了,像之前小编也总结过,但是课程每期都有做一定的更新,也是为了更好的完善课程跟上目前互联网大厂的岗位技术需求,之前 ...
- C/C++Linux服务器开发完整学习路线(含免费学习资料下载地址)
C/C++Linux服务器开发完整学习路线(含免费学习资料下载地址) 相信大部分同学刚毕业或者想转行做c++服务端开发的时候都很迷茫不知道从哪里开始学习,于是准备参加各种培训班或者网络培训,有不知道该 ...
最新文章
- 1048 数字加密 (20 分)java
- Mysql VARCHAR(X) vs TEXT
- 技术人如何自我提升?阿里技术带来丰富学习资源
- 读取无线手柄数据_《宇宙机器人》×PS5手柄使用体验:登月级进化
- 2017.0613.《计算机组成原理》总线控制-通信控制
- windows下OpenSSL加密证书安装步骤与使用方法
- 使用jQuery的ajax同步请求吃过的亏
- 《深入浅出DPDK》读书笔记(十二):DPDK虚拟化技术篇(半虚拟化Virtio)
- 数据访问类用静态方法。。。当多个人调用时返回值会返回别人的?。。。特别奇怪的问题???...
- 静态路由的不通配置方式
- 【转贴】没有div没有float没有clear没有hack的超强CSS布局
- 快手AI技术副总裁郑文:为什么说AI是短视频平台的核心能力
- javaweb网上人才招聘系统的设计与实现
- 国开大学计算机原理边学边练,国家开放大学计算机组成原理
- Android 长按Menu键的监听
- net_speeder发双倍包加速
- python 爬取《时间的形状》微信公号
- 你看这雪花如此的美丽
- Windows内核安全与驱动编程学习笔记----1.WDK安装
- 微服务拆分:业务横向拆分和纵向拆分
热门文章
- leetcode-739:每日温度
- manjaro 安装搜狗拼音输入法
- 读书笔记:《Being Mortal》
- Rosalind第11题:Mortal Fibonacci Rabbits
- 博客显示ip签名图片html代码,如何制作显示IP的签名图片
- 线性代数【8】-1 线性方程组 - 非常重要的概念 - 三个基本的问题
- 算法系列之算法学习书籍以及资料推荐
- R语言期末考试复习题第一天整理内容(自己整理+参考博主:紧到长不胖 )请多关注 紧到长不胖 ,每天有惊喜!
- 宁录哨兵机器人_当天启碰上哨兵机器人孰强孰弱?这部漫画给出了答案!
- ibm的odm使用_使用IBM ODM API生成规则工件