TCP 协议(Transmission Control Protocol)全称是传输控制协议是一种面向连接的、可靠的、
基于字节流的传输层通信协议。
tcp服务端使用QTcpServer、QTcpSocket。
tcp客户端使用QTcpSocket
1.在工程文件(工程文件.pro)中的第一行添加network 如
QT += core gui network //network是添加之后的
2.引用头文件
#include
#include
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
#include
#include 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 m_clientList; //存放客户端socket的容器
};#endif // CTCPSERVER_H
#include "CTcpServer.h"
#include 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()
{//循环获取客户端socketwhile (this->hasPendingConnections()){QTcpSocket *clientTemp = this->nextPendingConnection(); //拿到当前的socketm_clientList.append(clientTemp); //将当前socket添加到列表中(方便操作)connect(clientTemp, &QTcpSocket::readyRead, this, &CTcpServer::readyReadData);}
}void CTcpServer::readyReadData()
{//拿到发送信号的客户端指针,通过该指针读取数据QTcpSocket *curClient = dynamic_cast(sender());emit recvDataSignal(curClient->readAll());
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include
#include
#include "ctcpserver.h"namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic: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
#include 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 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
#include
#include "ctcpsocket.h"namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic: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);
}