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. 基于vip和twemproxy代理实现redis集群的无感知弹性扩容

    目标是实现redis集群的无感知弹性扩容 关键点 1是无感知,即对redis集群的用户来说服务ip和port保持不变 2.弹性扩容,指的是在需要时刻可以按照业务扩大redis存储容量. 最原始的twe ...

  2. LeetCode 54. Spiral Matrix(螺旋矩阵)

    Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral or ...

  3. SpringMVC的流程分析(一)—— 整体流程概括

    SpringMVC的整体概括 之前也写过springmvc的流程分析,只是当时理解的还不透彻所以那篇文章就放弃了,现在比之前好了些,想着写下来分享下,也能增强记忆,也希望可以帮助到人,如果文章中有什么 ...

  4. Java基础笔记14

    1.反射. Class:反射类 任何一个类都有一个Class反射类.(影子) java.lang.reflect.*; Field:字段类 Method:方法类类 Constructor:构造方法类. ...

  5. Eclipse+Spring+SpringMVC+Maven+Mybatis+MySQL+Tomcat项目搭建

    ---恢复内容开始--- 1. 建表语句及插入数据 CREATE TABLE `book_user` ( user_id INT(11) NOT NULL AUTO_INCREMENT, user_n ...

  6. 简单的一句sql

    表1 Id Name 1 张三 2 李四 3 王五 表二 Id Name1 Name2 1 1 2 2 2 1 3 2 3 4 1 3 我现在要查出结果如下: Id Name1 Name2 1 张三 ...

  7. 紧跟腾讯大王卡:B站2233卡“基友号”即将上线

    来自B站官方的消息显示,B站在近期也将推出"基友号"功能,功能的内容是通话免费,考虑到这类互联网套餐都是中国联通在运营,因此在内容上可能也会效仿腾讯大王卡实现免费通话. 目前,B站 ...

  8. 1192: [HNOI2006]鬼谷子的钱袋

    1192: [HNOI2006]鬼谷子的钱袋 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3530  Solved: 2575[Submit][St ...

  9. Android 开发笔记___时间选择器---timePicker

    像datepicker一样,也有timepicker. 同样有timepickerdialog 所用到的方法还是一样,监听时间选择器的变化. package com.example.alimjan.h ...

  10. Android 开发笔记___滚动视图__scroll view

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...