博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
QT之TCP通信
阅读量:4303 次
发布时间:2019-05-27

本文共 11676 字,大约阅读时间需要 38 分钟。

QT中可以通过TCP协议让服务器和客户端之间行通信。所以下面我就围绕服务器和客户端来写。

这是我们写服务器和客户端的具体流程:

A、服务器:      

         1.创建QTcpServer对象

         2.启动服务器(监听)调用成员方法listen(QHostAddress::Any,端口号)
         3.当有客户端链接时候会发送newConnection信号,触发槽函数接受链接(得到一个与客户端通信的套接字QTcpSocket)
         4.QTcpsocket发送数据用成员方法write,
         5.读数据当客户端有数据来,QTcpSocket对象就会发送readyRead信号,关联槽函数读取数据

B、客户端  :  

        1.创建QTcpSocket对象

        2.链接服务器connectToHost(QHostAddress("ip"),端口号)
        3.QTcpsocket发送数据用成员方法write,
        4.读数据当对方有数据来,QTcpSocket对象就会发送readyRead信号,关联槽函数读取数据

 

我们需要调用到的头文件有两个:

#include 
#include

我们先要在工程文件中加入network

QT       += core gui network

下面我们来看看服务器程序步骤:

1、初始化服务器server对象

mServer = new QTcpServer();

2、启动监听服务器

mServer->listen(QHostAddress::Any,9988);//9988为端口号

3、当有客户端链接时候会发送newConnection信号,触发槽函数接受链接(得到一个与客户端通信的套接字QTcpSocket)

connect(mServer,SIGNAL(newConnection()),this,SLOT(new_client())); mSocket = mServer->nextPendingConnection();//与客户端通信的套接字

4、发送数据

mSocket->write(msg.toUtf8());

5、读数据当客户端有数据来,QTcpSocket对象就会发送readyRead信号,关联槽函数读取数据

connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_client_data()));

6、连接多个客户端

//可以实现同时读取多个客户端发送过来的消息 QTcpSocket *obj = (QTcpSocket*)sender();

7、检测掉线

connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_dis())); //检测掉线信号

下面是服务器的实现的具体代码:

复制代码

1 #include "tcpserver.h" 2 #include "ui_tcpserver.h" 3 #include 
4 TcpServer::TcpServer(QWidget *parent) : 5 QMainWindow(parent), 6 ui(new Ui::TcpServer) 7 { 8 ui->setupUi(this); 9 //初始化服务器server对象10 mServer = new QTcpServer();11 //关联客户端连接信号newConnection12 connect(mServer,SIGNAL(newConnection()),this,SLOT(new_client())); //连接客户端13 //启动服务器监听14 mServer->listen(QHostAddress::Any,9988);15 16 }17 18 TcpServer::~TcpServer()19 {20 delete ui;21 }22 23 void TcpServer::new_client()24 {25 qDebug()<<"新客户段连接";26 mSocket = mServer->nextPendingConnection();//与客户端通信的套接字27 //关联接收客户端数据信号readyRead信号(客户端有数据就会发readyRead信号)28 connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_client_data()));29 //检测掉线信号30 connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_dis()));31 32 }33 34 void TcpServer::read_client_data()35 {36 //可以实现同时读取多个客户端发送过来的消息37 QTcpSocket *obj = (QTcpSocket*)sender();38 QString msg = obj->readAll();39 qDebug()<
peerAddress().toString();//打印出掉线对象的ip46 }

复制代码

 

说完服务器那我们继续来看看客户端是怎么实现的:

1、创建QTcpSocket对象

mSocket = new QTcpSocket();

2、链接服务器connectToHost(QHostAddress("ip"),端口号),连接服务器ip和端口号

mSocket->connectToHost(ui->ipEdit->text(),ui->portEdit->text().toInt()); //ui->ipEdit->text():ip,ui->portEdit->text().toInt():端口号

3、发送数据

//取发送信息编辑框内容QString msg = ui->sendEdit->toPlainText();mSocket->write(msg.toUtf8());//转编码

4、检测链接成功信号关联槽函数

connect(mSocket,SIGNAL(connected()),this,SLOT(connect_suc()));

5、检测掉线信号

connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_dis()));

6、服务器和客户端关闭都可以使用close

mSocket->close();

这是客户端实现的具体代码

复制代码

1 #include "tcpclient.h" 2 #include "ui_tcpclient.h" 3 #include 
4 TcpClient::TcpClient(QWidget *parent) : 5 QMainWindow(parent), 6 ui(new Ui::TcpClient) 7 { 8 ui->setupUi(this); 9 //初始化套接字对象10 mSocket = new QTcpSocket();11 //关联数据信号12 connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_data()));13 14 }15 16 TcpClient::~TcpClient()17 {18 delete ui;19 }20 21 void TcpClient::read_data()22 {23 QString msg = mSocket->readAll();24 qDebug()<
connectToHost(ui->ipEdit->text(),ui->portEdit->text().toInt());35 36 }37 38 void TcpClient::on_btn_send_clicked()39 {40 //取发送信息编辑框内容41 QString msg = ui->sendEdit->toPlainText();42 mSocket->write(msg.toUtf8());//转编码43 }44 45 void TcpClient::connect_suc()46 {47 ui->btn_connectServer->setEnabled(false);//如果连接成功则连接按钮不能按下48 }49 void TcpClient::client_dis()50 {51 ui->btn_connectServer->setEnabled(true);//如果连接没有成功则连接按钮还可以按下52 }

复制代码

 

这是服务器和客户端分开两个文件夹写的程序,在这里我也实现了服务器和客户端写在同一个文件中

具体代码如下:

头文件:tcpapp.h

复制代码

1 #ifndef TCPAPP_H 2 #define TCPAPP_H 3  4 #include 
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 namespace Ui {12 class TcpApp;13 }14 15 class TcpApp : public QMainWindow16 {17 Q_OBJECT18 19 public:20 explicit TcpApp(QWidget *parent = 0);21 ~TcpApp();22 23 private slots:24 void on_severRB_clicked();//选择作为服务器25 26 void on_clientRB_clicked();//选择作为客户端27 28 void on_StartBt_clicked();//启动服务器或链接客户端29 30 void on_closeBt_clicked();//关闭服务器或断开客户端31 32 void on_onlineUserList_doubleClicked(const QModelIndex &index);//选择给哪个客户端发送数据33 34 void on_autoCB_clicked(bool checked);//选择自动发送还是手动发送35 36 void on_sendMsgBt_clicked();//发送信息37 38 //服务器39 void accept_connect();//与newconnection信号关联40 void recv_data(); //接收数据41 42 void auto_time_send();//定时器定时发送数据43 44 void client_disconnect();//关联掉线信号45 void connect_suc();//检测客户端连接成功信号46 47 void on_clearRcvBt_clicked();48 49 void on_clearSendBt_clicked();50 51 private:52 Ui::TcpApp *ui;53 QTimer *mTimer;//定时发送数据54 QTcpServer *mServer;55 QTcpSocket *mSocket;56 QVector
clients; //存储所有在线客户端(容器)57 58 bool isServer;//标志位,true为服务器,false为客户端59 60 //保存接收和发送数据的字节数61 quint64 recvSize;62 quint64 sendSize;63 64 qint16 onNum;65 bool isCheckServer;//判断是否选择了服务器66 bool isCheckClient;//判断是否选择了客户端67 68 69 };70 71 #endif // TCPAPP_H

复制代码

源文件:tcpapp.cpp

复制代码

1 #include "tcpapp.h"  2 #include "ui_tcpapp.h"  3   4 TcpApp::TcpApp(QWidget *parent) :  5     QMainWindow(parent),  6     ui(new Ui::TcpApp),  7     onNum(0)  8 {  9     ui->setupUi(this); 10     recvSize = 0; 11     sendSize = 0; 12     //初始化定时器 13     mTimer = new QTimer(); 14     connect(mTimer,SIGNAL(timeout()),this,SLOT(auto_time_send())); 15 } 16  17 TcpApp::~TcpApp() 18 { 19     delete ui; 20 } 21  22 //与newconnection信号关联 23 void TcpApp::accept_connect() 24 { 25     mSocket = mServer->nextPendingConnection(); //返回与客户端连接通信的套接字 26  27     //关联接收数据信号 28     connect(mSocket,SIGNAL(readyRead()),this,SLOT(recv_data())); 29     //关联掉线信号 30     connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_disconnect())); 31  32     //上线用户添加到客户列表容器 33     clients.append(mSocket); 34     //把用户添加到界面列表中 35     QString ip = mSocket->peerAddress().toString().remove("::ffff:");//去除客户端中多余的字符 36     ui->onlineUserList->addItem(ip); 37  38     //在线数量添加 39     onNum++; 40     ui->onlineUserCount->setText(QString::number(onNum));//显示在线数 41  42 } 43  44 //接收数据 45 void  TcpApp::recv_data() 46 { 47       QTcpSocket *obj = (QTcpSocket*)sender(); 48       //获取发送数据端的IP 49       QString ip = obj->peerAddress().toString(); 50       ip.remove("::ffff:"); 51       QString msg = obj->readAll(); 52       ui->receiveList->addItem(ip+":"+msg);//显示接收到的数据 53       recvSize += msg.size();//统计接收到的数据的字节数 54       ui->receiveNumLabel->setText(QString::number(recvSize)); 55 } 56  57 void TcpApp::client_disconnect() 58 { 59     QTcpSocket *obj = (QTcpSocket*)sender();//获取掉线对象 60     if(isServer) 61     { 62         int row = clients.indexOf(obj);//找到掉线对象的内容所在的行 63         QListWidgetItem *item = ui->onlineUserList->takeItem(row);//从界面列表中去除找到的一行内容 64         delete item; 65         clients.remove(row);//从容器中删除对象 66  67         //掉线时删除在线数量 68         onNum--; 69         ui->onlineUserCount->setText(QString::number(onNum)); 70     } 71     else 72     { 73         ui->StartBt->setEnabled(true);//断开连接的时候重新启用开始按钮 74     } 75 } 76  77  78 //客户端连接成功 79 void TcpApp::connect_suc() 80 { 81     ui->StartBt->setEnabled(false);//连接成功则禁用开始按钮 82 } 83 //定时器定时发送数据 84 void TcpApp::auto_time_send() 85 { 86     quint64 len = mSocket->write(ui->sendMsgEdit->toPlainText().toUtf8()); 87     if(len > 0) 88     { 89         sendSize += len;//统计发送的字节数 90         ui->sendNumLabel->setText(QString::number(sendSize));//把发送的字节数显示到sendNumLabel上 91  92     } 93 } 94  95 //选择作为服务器 96 void TcpApp::on_severRB_clicked() 97 { 98     this->isCheckServer = true; 99     this->isServer = true;100     //获取本地ip显示在IpEdit中101    ui->IpEdit->setText(QHostAddress(QHostAddress::LocalHost).toString());102    ui->IpEdit->setEnabled(false);//关闭ip输入编辑器103    this->isCheckClient = false;104 105 }106 107 //选择作为客户端108 void TcpApp::on_clientRB_clicked()109 {110     this->isCheckClient = true;111     this->isServer = false;112     ui->IpEdit->setEnabled(true);//打开ip输入编辑器113     this->isCheckServer = false;114 115 }116 117 //启动服务器或者链接服务器118 void TcpApp::on_StartBt_clicked()119 {120     if(isServer) //服务器121     {122         mServer = new QTcpServer();123         //关联新客户端链接信号124         connect(mServer,SIGNAL(newConnection()),this,SLOT(accept_connect()));125         mServer->listen(QHostAddress::Any,ui->PortEdit->text().toInt());//启动服务器监听126         ui->StartBt->setEnabled(false);//开始按钮禁用127     }128     if(isServer == false) //客户端129     {130         mSocket = new QTcpSocket();131         //检测链接成功信号132         connect(mSocket,SIGNAL(connected()),this,SLOT(connect_suc()));133         //设置服务器的 ip和端口号134         mSocket->connectToHost(ui->IpEdit->text(),ui->PortEdit->text().toInt());135 136 137         //关联接收数据信号138         connect(mSocket,SIGNAL(readyRead()),this,SLOT(recv_data()));139         //关联掉线信号140         connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_disconnect()));141     }142 143     if(isCheckServer == false && isCheckClient == false)//如果两个都没选择144     {145         QMessageBox::warning(this,"提示","请选择服务器或者客户端");146         ui->StartBt->setEnabled(true);147         return;148     }149 150     if(isCheckServer)//选择了服务器151     {152        if(ui->PortEdit->text().isEmpty() || ui->PortEdit->text() == "请输入端口号")153        {154            QMessageBox::warning(this,"提示","请输入端口号");155            ui->StartBt->setEnabled(true);156            return;157        }158     }159 160     if(isCheckClient)//选择了客户端161     {162         if(ui->IpEdit->text().isEmpty() || ui->IpEdit->text() == "请输入ip" || ui->IpEdit->text() == "请输入端口号")163         {164             QMessageBox::warning(this,"提示","请输入ip和端口号");165             ui->StartBt->setEnabled(true);166             return;167         }168     }169 170 }171 172 //关闭服务器或者断开173 void TcpApp::on_closeBt_clicked()174 {175     if(isServer)//服务器176     {177         for(int i=0;i
close();//关闭所有客户端180 }181 182 //关闭所有服务器之后开始按钮才能启用183 mServer->close();184 ui->StartBt->setEnabled(true);185 }186 else //客户端187 {188 mSocket->close();//关闭客户端189 ui->StartBt->setEnabled(true);//启用开始按钮190 }191 192 }193 194 //双击选择要发送的客户端195 void TcpApp::on_onlineUserList_doubleClicked(const QModelIndex &index)196 {197 mSocket = clients.at(index.row());198 199 }200 201 //自动发送数据202 void TcpApp::on_autoCB_clicked(bool checked)203 {204 if(checked)205 206 {207 if(ui->autoTimeEdit->text().toInt() <= 0)208 {209 QMessageBox::warning(this,"提示","请输入时间值ms");210 ui->autoCB->setChecked(false);//把按钮重新置于没选中的状态211 return;212 }213 mTimer->start(ui->autoTimeEdit->text().toInt());//启动定时器214 }215 else216 {217 mTimer->stop();//停止定时器218 }219 220 }221 222 //手动发送数据223 void TcpApp::on_sendMsgBt_clicked()224 {225 auto_time_send();226 227 }228 229 //清空接收区230 void TcpApp::on_clearRcvBt_clicked()231 {232 ui->receiveNumLabel->clear();233 this->recvSize = 0;234 ui->receiveNumLabel->setText(QString::number(recvSize));235 }236 237 //清空发送区238 void TcpApp::on_clearSendBt_clicked()239 {240 ui->sendNumLabel->clear();241 this->sendSize = 0;242 ui->sendNumLabel->setText(QString::number(sendSize));243 }

复制代码

界面文件tcpapp.ui如下图

 

此外这里还使用到了容器,在这里讲讲容器的使用

1、定义容器对象

QVector
clients; //存储所有在线客户端(容器) 解释:QTcpSocke* 容器的类型 clients 容器名

2、往容器中添加成员

//上线用户添加到客户列表容器 clients.append(mSocket);

3、寻找某个成员在容器中位置

int row = clients.indexOf(obj);//找到掉线对象的内容所在的行

4、从容器中删除成员

clients.remove(row);//从容器中删除成员

转载地址:http://lnmws.baihongyu.com/

你可能感兴趣的文章
期货市场技术分析07_摆动指数和相反意见理论
查看>>
满屏的指标?删了吧,手把手教你裸 K 交易!
查看>>
不吹不黑 | 聊聊为什么要用99%精度的数据回测
查看>>
X 分钟速成 Python
查看>>
对于模拟交易所引发的思考
查看>>
高频交易的几种策略
查看>>
量化策略回测TRIXKDJ
查看>>
量化策略回测唐安奇通道
查看>>
CTA策略如何过滤部分震荡行情?
查看>>
量化策略回测DualThrust
查看>>
量化策略回测BoolC
查看>>
量化策略回测DCCV2
查看>>
mongodb查询优化
查看>>
五步git操作搞定Github中fork的项目与原作者同步
查看>>
git 删除远程分支
查看>>
删远端分支报错remote refs do not exist或git: refusing to delete the current branch解决方法
查看>>
python multiprocessing遇到Can’t pickle instancemethod问题
查看>>
APP真机测试及发布
查看>>
通知机制 (Notifications)
查看>>
10 Things You Need To Know About Cocoa Auto Layout
查看>>