TCP 协议(Transmission Control Protocol)全称是传输控制协议是一种面向连接的、可靠的、
基于字节流的传输层通信协议。
tcp服务端使用QTcpServer、QTcpSocket。
tcp客户端使用QTcpSocket
1.在工程文件(工程文件.pro)中的第一行添加network 如
QT += core gui network //network是添加之后的
2.引用头文件
#include<QTcpServer>//监听套接字
#include<QTcpSocket>//通信套接字
服务端
1.创建QTcpServer对象
2.启动服务器(监听)调用成员方法listen(QHostAddress::Any,端口号)
3.当有客户端连接时候会发送newConnection信号,触发槽函数接受连接(调用 nextPendingConnection函数得到一个与客户端通信的套接字QTcpSocket),通过QTcpSocket对象调用peerAddress、peerPort得到客户端的ip地址和端口。
4.QTcpsocket发送数据用成员方法write
5.读数据当客户端有数据来,QTcpSocket对象就会发送readyRead信号,关联槽函数读取数据。
和客户端建立连接之后用于通信的 QTcpSocket 套接字对象,它是 QTcpServer 的一个子对象,当 QTcpServer 对象析构的时候会自动析构这个子对象,当然也可自己手动析构,建议用完之后自己手动析构这个通信的 QTcpSocket 对象
超时接受连接函数waitForNewConnection
bool QTcpServer::waitForNewConnection(int msec = 0, bool *timedOut = Q_NULLPTR);
msec:指定阻塞的最大时长,单位为毫秒(ms)
timeout:传出参数,如果操作超时 timeout 为 true,没有超时 timeout 为 false
常用信号
每次有新连接可用时都会发出 newConnection () 信号
当接受新连接导致错误时,将发射acceptError信号
#ifndef CTCPSERVER_H
#define CTCPSERVER_H
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
class CTcpServer : public QTcpServer
{
Q_OBJECT
public:
explicit CTcpServer(QTcpServer *parent = nullptr);
//发送信息到已连接的所有客户机
void sendData(QString data);
signals:
//通过该信号传递接收到的数据
void recvDataSignal(QString data);
public slots:
//当有新连接时的槽函数
void newClient();
//当有数据来时的槽函数
void readyReadData();
private:
QList<QTcpSocket *> m_clientList; //存放客户端socket的容器
};
#endif // CTCPSERVER_H
#include "CTcpServer.h"
#include <QTcpServer>
CTcpServer::CTcpServer(QTcpServer *parent) : QTcpServer(parent)
{
//设置可以连接的ip和端口号(此处为任意ip且端口号为6666的可以连接);若要指定ip,设置第一个参数即可
this->listen(QHostAddress::Any, 8866);
//连接相关的信号槽
connect(this, &CTcpServer::newConnection, this, &CTcpServer::newClient);
}
void CTcpServer::sendData(QString data)
{
//遍历客户端列表,将数据发送到所有客户端中(类似广播)
foreach (QTcpSocket *temp, m_clientList)
{
temp->write(data.toLocal8Bit(), data.length());
}
}
void CTcpServer::newClient()
{
//循环获取客户端socket
while (this->hasPendingConnections())
{
QTcpSocket *clientTemp = this->nextPendingConnection(); //拿到当前的socket
m_clientList.append(clientTemp); //将当前socket添加到列表中(方便操作)
connect(clientTemp, &QTcpSocket::readyRead, this, &CTcpServer::readyReadData);
}
}
void CTcpServer::readyReadData()
{
//拿到发送信号的客户端指针,通过该指针读取数据
QTcpSocket *curClient = dynamic_cast<QTcpSocket *>(sender());
emit recvDataSignal(curClient->readAll());
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtNetwork>
#include "ctcpserver.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_m_listenButton_clicked();
void on_m_sendButton_clicked();
void on_m_closeButton_clicked();
void on_m_exitButton_clicked();
void on_appendData(QString data); //将接收的数据显示
private:
Ui::MainWindow *ui;
CTcpServer *m_pserver;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_pserver(nullptr)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
if(m_pserver)
{
m_pserver->close();
delete m_pserver;
m_pserver = nullptr;
}
}
void MainWindow::on_m_listenButton_clicked()
{
m_pserver = new CTcpServer();
connect(m_pserver, &CTcpServer::recvDataSignal, this, &MainWindow::on_appendData);
}
void MainWindow::on_m_sendButton_clicked()
{
m_pserver->sendData(ui->m_sendlineEdit->text());
}
void MainWindow::on_m_closeButton_clicked()
{
if(m_pserver)
{
m_pserver->close();
delete m_pserver;
m_pserver = nullptr;
}
}
void MainWindow::on_m_exitButton_clicked()
{
}
void MainWindow::on_appendData(QString data)
{
ui->m_showtextBrowser->append(data);
}
客户端
1.创建QTcpSocket对象
2.链接服务器connectToHost(QHostAddress("ip"),端口号)
3.QTcpsocket发送数据用成员方法write
4.读数据当对方有数据来,QTcpSocket对象就会发送readyRead信号,关联槽函数读取数据
常用信号
readyRead
如果该类对象发射出 readyRead() 信号,说明对端发送的数据达到了,之后就可以调用 read 函数接收数据了。
connected
调用 connectToHost() 函数连接TCP服务器并成功建立连接之后发出 connected() 信号
disconnected
在套接字断开连接时发出 disconnected() 信号
#ifndef CTCPSOCKET_H
#define CTCPSOCKET_H
#include <QObject>
#include <QTcpSocket>
class CTcpSocket : public QTcpSocket
{
Q_OBJECT
public:
explicit CTcpSocket(QTcpSocket *parent = nullptr);
//通过改函数发送数据
void sendData(QString data);
signals:
//通过该信号传递接收到的数据
void recvDataSignal(QString data);
public slots:
//读取数据的槽函数
void readyReadData();
};
#endif // CTCPSOCKET_H
#include "CTcpSocket.h"
#include <QHostAddress>
CTcpSocket::CTcpSocket(QTcpSocket *parent) : QTcpSocket(parent)
{
//连接相应槽函数
connect(this, &CTcpSocket::readyRead, this, &CTcpSocket::readyReadData);
//指定ip且端口号为8866, (QHostAddress中指定的ip需本机存在或能连接到才可使用)
this->connectToHost(QHostAddress("127.0.0.1"), 8866);
}
void CTcpSocket::sendData(QString data)
{
this->write(data.toUtf8());
}
void CTcpSocket::readyReadData()
{
emit recvDataSignal(this->readAll());
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtNetwork>
#include "ctcpsocket.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_m_connectButton_clicked();
void on_m_sendButton_clicked();
void on_m_closeButton_clicked();
void on_appendData(QString data); //将接收的数据显示
private:
Ui::MainWindow *ui;
CTcpSocket *m_client;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_client(nullptr)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
if(m_client)
{
m_client->close();
delete m_client;
m_client = nullptr;
}
}
void MainWindow::on_m_connectButton_clicked()
{
m_client = new CTcpSocket;
connect(m_client, &CTcpSocket::recvDataSignal, this, &MainWindow::on_appendData);
}
void MainWindow::on_m_sendButton_clicked()
{
m_client->sendData(ui->m_sendlineEdit->text());
}
void MainWindow::on_m_closeButton_clicked()
{
if(m_client)
{
m_client->close();
delete m_client;
m_client = nullptr;
}
}
void MainWindow::on_appendData(QString data)
{
ui->m_showtextBrowser->append(data);
}