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 <QTcpServer>
#include <QTcpSocket>

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

QT       += core gui network

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

1、初始化服务器server对象

mServer = new QTcpServer();

2、启动监听服务器

  mServer->listen(QHostAddress::Any,);//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())); //检测掉线信号

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

 #include "tcpserver.h"
#include "ui_tcpserver.h"
#include <QDebug>
TcpServer::TcpServer(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::TcpServer)
{
ui->setupUi(this);
//初始化服务器server对象
mServer = new QTcpServer();
//关联客户端连接信号newConnection
connect(mServer,SIGNAL(newConnection()),this,SLOT(new_client())); //连接客户端
//启动服务器监听
mServer->listen(QHostAddress::Any,); } TcpServer::~TcpServer()
{
delete ui;
} void TcpServer::new_client()
{
qDebug()<<"新客户段连接";
mSocket = mServer->nextPendingConnection();//与客户端通信的套接字
//关联接收客户端数据信号readyRead信号(客户端有数据就会发readyRead信号)
connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_client_data()));
//检测掉线信号
connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_dis())); } void TcpServer::read_client_data()
{
//可以实现同时读取多个客户端发送过来的消息
QTcpSocket *obj = (QTcpSocket*)sender();
QString msg = obj->readAll();
qDebug()<<msg;
} void TcpServer::client_dis()
{
QTcpSocket *obj = (QTcpSocket*)sender();//掉线对象
qDebug()<<obj->peerAddress().toString();//打印出掉线对象的ip
}

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

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();

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

 #include "tcpclient.h"
#include "ui_tcpclient.h"
#include <QDebug>
TcpClient::TcpClient(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::TcpClient)
{
ui->setupUi(this);
//初始化套接字对象
mSocket = new QTcpSocket();
//关联数据信号
connect(mSocket,SIGNAL(readyRead()),this,SLOT(read_data())); } TcpClient::~TcpClient()
{
delete ui;
} void TcpClient::read_data()
{
QString msg = mSocket->readAll();
qDebug()<<msg;
} void TcpClient::on_btn_connectServer_clicked()
{
//检测链接成功信号关联槽函数
connect(mSocket,SIGNAL(connected()),this,SLOT(connect_suc()));
//检测掉线信号
connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_dis()));
//连接服务器,设置ip和端口号
mSocket->connectToHost(ui->ipEdit->text(),ui->portEdit->text().toInt()); } void TcpClient::on_btn_send_clicked()
{
//取发送信息编辑框内容
QString msg = ui->sendEdit->toPlainText();
mSocket->write(msg.toUtf8());//转编码
} void TcpClient::connect_suc()
{
ui->btn_connectServer->setEnabled(false);//如果连接成功则连接按钮不能按下
}
void TcpClient::client_dis()
{
ui->btn_connectServer->setEnabled(true);//如果连接没有成功则连接按钮还可以按下
}

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

具体代码如下:

头文件:tcpapp.h

 #ifndef TCPAPP_H
#define TCPAPP_H #include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QFile>
#include <QTimer>
#include <QMessageBox>
namespace Ui {
class TcpApp;
} class TcpApp : public QMainWindow
{
Q_OBJECT public:
explicit TcpApp(QWidget *parent = );
~TcpApp(); private slots:
void on_severRB_clicked();//选择作为服务器 void on_clientRB_clicked();//选择作为客户端 void on_StartBt_clicked();//启动服务器或链接客户端 void on_closeBt_clicked();//关闭服务器或断开客户端 void on_onlineUserList_doubleClicked(const QModelIndex &index);//选择给哪个客户端发送数据 void on_autoCB_clicked(bool checked);//选择自动发送还是手动发送 void on_sendMsgBt_clicked();//发送信息 //服务器
void accept_connect();//与newconnection信号关联
void recv_data(); //接收数据 void auto_time_send();//定时器定时发送数据 void client_disconnect();//关联掉线信号
void connect_suc();//检测客户端连接成功信号 void on_clearRcvBt_clicked(); void on_clearSendBt_clicked(); private:
Ui::TcpApp *ui;
QTimer *mTimer;//定时发送数据
QTcpServer *mServer;
QTcpSocket *mSocket;
QVector<QTcpSocket*> clients; //存储所有在线客户端(容器) bool isServer;//标志位,true为服务器,false为客户端 //保存接收和发送数据的字节数
quint64 recvSize;
quint64 sendSize; qint16 onNum;
bool isCheckServer;//判断是否选择了服务器
bool isCheckClient;//判断是否选择了客户端 }; #endif // TCPAPP_H

源文件:tcpapp.cpp

 #include "tcpapp.h"
#include "ui_tcpapp.h" TcpApp::TcpApp(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::TcpApp),
onNum()
{
ui->setupUi(this);
recvSize = ;
sendSize = ;
//初始化定时器
mTimer = new QTimer();
connect(mTimer,SIGNAL(timeout()),this,SLOT(auto_time_send()));
} TcpApp::~TcpApp()
{
delete ui;
} //与newconnection信号关联
void TcpApp::accept_connect()
{
mSocket = mServer->nextPendingConnection(); //返回与客户端连接通信的套接字 //关联接收数据信号
connect(mSocket,SIGNAL(readyRead()),this,SLOT(recv_data()));
//关联掉线信号
connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_disconnect())); //上线用户添加到客户列表容器
clients.append(mSocket);
//把用户添加到界面列表中
QString ip = mSocket->peerAddress().toString().remove("::ffff:");//去除客户端中多余的字符
ui->onlineUserList->addItem(ip); //在线数量添加
onNum++;
ui->onlineUserCount->setText(QString::number(onNum));//显示在线数 } //接收数据
void TcpApp::recv_data()
{
QTcpSocket *obj = (QTcpSocket*)sender();
//获取发送数据端的IP
QString ip = obj->peerAddress().toString();
ip.remove("::ffff:");
QString msg = obj->readAll();
ui->receiveList->addItem(ip+":"+msg);//显示接收到的数据
recvSize += msg.size();//统计接收到的数据的字节数
ui->receiveNumLabel->setText(QString::number(recvSize));
} void TcpApp::client_disconnect()
{
QTcpSocket *obj = (QTcpSocket*)sender();//获取掉线对象
if(isServer)
{
int row = clients.indexOf(obj);//找到掉线对象的内容所在的行
QListWidgetItem *item = ui->onlineUserList->takeItem(row);//从界面列表中去除找到的一行内容
delete item;
clients.remove(row);//从容器中删除对象 //掉线时删除在线数量
onNum--;
ui->onlineUserCount->setText(QString::number(onNum));
}
else
{
ui->StartBt->setEnabled(true);//断开连接的时候重新启用开始按钮
}
} //客户端连接成功
void TcpApp::connect_suc()
{
ui->StartBt->setEnabled(false);//连接成功则禁用开始按钮
}
//定时器定时发送数据
void TcpApp::auto_time_send()
{
quint64 len = mSocket->write(ui->sendMsgEdit->toPlainText().toUtf8());
if(len > )
{
sendSize += len;//统计发送的字节数
ui->sendNumLabel->setText(QString::number(sendSize));//把发送的字节数显示到sendNumLabel上 }
} //选择作为服务器
void TcpApp::on_severRB_clicked()
{
this->isCheckServer = true;
this->isServer = true;
//获取本地ip显示在IpEdit中
ui->IpEdit->setText(QHostAddress(QHostAddress::LocalHost).toString());
ui->IpEdit->setEnabled(false);//关闭ip输入编辑器
this->isCheckClient = false; } //选择作为客户端
void TcpApp::on_clientRB_clicked()
{
this->isCheckClient = true;
this->isServer = false;
ui->IpEdit->setEnabled(true);//打开ip输入编辑器
this->isCheckServer = false; } //启动服务器或者链接服务器
void TcpApp::on_StartBt_clicked()
{
if(isServer) //服务器
{
mServer = new QTcpServer();
//关联新客户端链接信号
connect(mServer,SIGNAL(newConnection()),this,SLOT(accept_connect()));
mServer->listen(QHostAddress::Any,ui->PortEdit->text().toInt());//启动服务器监听
ui->StartBt->setEnabled(false);//开始按钮禁用
}
if(isServer == false) //客户端
{
mSocket = new QTcpSocket();
//检测链接成功信号
connect(mSocket,SIGNAL(connected()),this,SLOT(connect_suc()));
//设置服务器的 ip和端口号
mSocket->connectToHost(ui->IpEdit->text(),ui->PortEdit->text().toInt()); //关联接收数据信号
connect(mSocket,SIGNAL(readyRead()),this,SLOT(recv_data()));
//关联掉线信号
connect(mSocket,SIGNAL(disconnected()),this,SLOT(client_disconnect()));
} if(isCheckServer == false && isCheckClient == false)//如果两个都没选择
{
QMessageBox::warning(this,"提示","请选择服务器或者客户端");
ui->StartBt->setEnabled(true);
return;
} if(isCheckServer)//选择了服务器
{
if(ui->PortEdit->text().isEmpty() || ui->PortEdit->text() == "请输入端口号")
{
QMessageBox::warning(this,"提示","请输入端口号");
ui->StartBt->setEnabled(true);
return;
}
} if(isCheckClient)//选择了客户端
{
if(ui->IpEdit->text().isEmpty() || ui->IpEdit->text() == "请输入ip" || ui->IpEdit->text() == "请输入端口号")
{
QMessageBox::warning(this,"提示","请输入ip和端口号");
ui->StartBt->setEnabled(true);
return;
}
} } //关闭服务器或者断开
void TcpApp::on_closeBt_clicked()
{
if(isServer)//服务器
{
for(int i=;i<clients.count();i++)
{
clients.at(i)->close();//关闭所有客户端
} //关闭所有服务器之后开始按钮才能启用
mServer->close();
ui->StartBt->setEnabled(true);
}
else //客户端
{
mSocket->close();//关闭客户端
ui->StartBt->setEnabled(true);//启用开始按钮
} } //双击选择要发送的客户端
void TcpApp::on_onlineUserList_doubleClicked(const QModelIndex &index)
{
mSocket = clients.at(index.row()); } //自动发送数据
void TcpApp::on_autoCB_clicked(bool checked)
{
if(checked) {
if(ui->autoTimeEdit->text().toInt() <= )
{
QMessageBox::warning(this,"提示","请输入时间值ms");
ui->autoCB->setChecked(false);//把按钮重新置于没选中的状态
return;
}
mTimer->start(ui->autoTimeEdit->text().toInt());//启动定时器
}
else
{
mTimer->stop();//停止定时器
} } //手动发送数据
void TcpApp::on_sendMsgBt_clicked()
{
auto_time_send(); } //清空接收区
void TcpApp::on_clearRcvBt_clicked()
{
ui->receiveNumLabel->clear();
this->recvSize = ;
ui->receiveNumLabel->setText(QString::number(recvSize));
} //清空发送区
void TcpApp::on_clearSendBt_clicked()
{
ui->sendNumLabel->clear();
this->sendSize = ;
ui->sendNumLabel->setText(QString::number(sendSize));
}

界面文件tcpapp.ui如下图

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

1、定义容器对象

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

2、往容器中添加成员

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

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

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

4、从容器中删除成员

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

QT之TCP通信的更多相关文章

  1. QT实现TCP通信服务器端和客户端(支持多个客户端)精简版

    上星期接了个私活,工期两星期,报酬3000,写一个小软件,采集定向网络上的数据,并进行双向通信,捣鼓了两天,终于把QT中tcp通信这块调通了,找过N多例子,绝大部分都是基本的一个服务端一个客户端通信的 ...

  2. QT 简单 TCP 通信,发送数据到服务器

    1.首先 添加头文件 #include <QtNetwork/QTcpSocket> 并且 在 xxx.pro(xxx指工程的名称) 中QT += core gui下面,添加 下面两句句话 ...

  3. QT创建TCP Socket通信

    最近在学习QT,了解到QT可以进行SOCKET网络通信,进行学习,并建立一个简单的聊天DEMO.为了测试是否能与VS2012下的程序进行通信,在VS2012下建立一个客户端程序,进行通信测试,发现可以 ...

  4. QT之UDP通信

    前言:前一篇讲了TCP通信,这篇来看看UDP通信. 这里说明一下,UDP通信中分为三种通信分别为单播.组播和广播,下面将一一为大家介绍. 同样的我们都需要在工程文件中添加network QT += c ...

  5. 界面编程之QT的Socket通信20180730

    /*******************************************************************************************/ 一.linu ...

  6. Qt基于tcp协议网络编程

    基于Qt网络编程: 基于tcp协议 c/s模式编程 所需要的类:QTcpServer QTcpSocket 利用qt基于tcp协议编写c/s模式程序: 两个类中的信号: QTcpServer : ne ...

  7. 【转】Qt Socket简单通信

    最近要用到Qt的Socket部分,网上关于这部分的资料都比较复杂,我在这总结一下,把Socket的主要部分提取出来,实现TCP和UDP的简单通信. 1.UDP通信 UDP没有特定的server端和cl ...

  8. 套接字、UDP通信、TCP通信、TCP/IP协议簇

    一.套接字(socket) 1.英语单词socket:n.插座:穴:v.插入插座 2.套接字就是源IP地址和目的IP地址.源端口号和目的端口号的组合,是通过传输层进行通信的.IP指定电脑,端口指定某一 ...

  9. TCP通信

    //网络套接字编程实例,服务器端,TCP通信. #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib") #inc ...

随机推荐

  1. WCF 内置跟踪日志

    Web.config 配置文件修改: <system.serviceModel> <diagnostics> <messageLogging logEntireMessa ...

  2. Numpy数组索引为-1和None

    numpy的数组操作方便,可以用:来切片,用布尔数组或者布尔表达式来查找符合条件的数据,也可以用数组作为另一个数组的索引来查找指定的数据.但有时也会见到数组索引为-1和None.两者的用法如下: 1. ...

  3. Can you solve this equation?

    Can you solve this equation? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...

  4. 实例理解mapreduce任务的串行运行过程

    一.准备: eclipse,hadoop集群 注意:为了方便测试和修改,我用的是 windows 连接hadoop集群,这样在windows 下直接就能够执行 mapreduce 任务,方便程序调试. ...

  5. mouseover事件mouseenter事件

    1. mouseover:会在鼠标进入该元素或者该元素的子元素时触发 mouseenter:只在鼠标进入该元素时触发 mouseout:在鼠标移出该元素或则该元素的子元素时触发 mouseleave: ...

  6. DataFrame使用总结1(超实用)

    DataFrame使用总结1(超实用): 1. 合并两个表 frame = [df1, df2] df = pd.concat(frame) res = pd.merge(df, df1, on=[' ...

  7. 将Excel文件数据导入到SqlServer数据库的三种方案

    方案一: 通过OleDB方式获取Excel文件的数据,然后通过DataSet中转到SQL Server,这种方法的优点是非常的灵活,可以对Excel表中的各个单元格进行用户所需的操作. openFil ...

  8. C# 链接MySql数据库

    C# 链接MySql数据库只得注意的几点: 1.C#链接MySql数据库要在网上下载一个mysql-connector-net-6.0.4-noinstall.rar  这里面放的都是一堆dll .将 ...

  9. WPF 完美截图 <序>

    最近由于工作需要(话说总是工作需要哈),老大交给个任务,我鼓捣了2个星期,有点心得与大伙共享,希望对同被此问题困扰的同学有所帮助. 费话不说,上图: 此为完成后运行时状态图,先扔在这,下午有空开始正式 ...

  10. RabbitMQ的简单应用

    虽然后台使用了读写分离技术,能够在一定程度上抗击高并发,但是如果并发量特别巨大时,主数据库不能同时处理高并发的请求,这时数据库容易宕机. 问题: 现在的问题是如何既能保证数据库正常运行,又能实现用户数 ...