这里使用到了QTcpSocket,QTcpServer和QHostAddress这三个头文件。
你应该先在项目的.pro文件里添加QT+=network这段文本。
先说服务端。
服务端的逻辑很简单,bind和listen一步到位,直接使用QTcpServer的对象的listen函数就行:
1
| server->listen(QHostAddress::Any, quint16(8888));
|
然后服务就打开啦!QHostAddress::Any的意思是任意ip段,quint16(8888)的意思是8888号端口。
也就是说我们打开了一个服务,它能够接受任意ip段的地址,而且它在监听8888端口。
然后我们来看服务端完整代码,代码里我做了关闭socket通信,发送消息,接受消息并将消息显示在textEdit控件上的操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| #include "serverwidget.h" #include "ui_serverwidget.h"
ServerWidget::ServerWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::ServerWidget), server(nullptr), socket(nullptr), sock_count(0) { ui->setupUi(this); server = new QTcpServer(this); server->listen(QHostAddress::Any, quint16(8888)); connect(server, &QTcpServer::newConnection, [=]() { std::cout << "Connected" << std::endl; socket = server->nextPendingConnection(); ui->textEdit->append(QString("ip: %1, port: %2 connected").arg(socket->peerAddress().toString()).arg(socket->peerPort())); if(sock_count == 0) { sock_count++; connect(socket, &QTcpSocket::readyRead, [=](){ QString msg = socket->readAll(); ui->textEdit->append(msg); }); connect(socket, &QTcpSocket::disconnected, [=](){ ui->textEdit->append("Disconnected."); }); } } ); }
ServerWidget::~ServerWidget() { delete ui; }
void ServerWidget::on_pushButton_clicked() { if(socket != nullptr) { QString msg = ui->textEdit_2->toPlainText(); socket->write(msg.toUtf8().data()); } }
void ServerWidget::on_pushButton_2_clicked() { if(socket != nullptr) { socket->disconnected(); socket->close(); ui->textEdit->append("Activily disconnected"); } }
|
其实最主要的就是readyRead, newConnection, disconnected这几个信号和readAll,write,listen等成员函数,其他的也没啥。
然后来看客户端的代码。
客户端我做了发送消息,接收消息,发起连接和关闭连接。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| #include "clientwidget.h" #include "ui_clientwidget.h" #include <iostream>
ClientWidget::ClientWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::ClientWidget) , socket(nullptr) { ui->setupUi(this); setWindowTitle("Client"); socket = new QTcpSocket(this); connect(socket, &QTcpSocket::connected, [=](){ ui->textEdit->append("Connect successful."); }); connect(socket, &QTcpSocket::readyRead, [=](){ QString msg; msg.prepend(socket->readAll()); ui->textEdit->append(msg); }); connect(socket, &QTcpSocket::disconnected, [=](){ ui->textEdit->append("Disconnected."); std::cout << "disconnected" << std::endl; socket->disconnectFromHost(); socket->close(); socket = nullptr; }); }
ClientWidget::~ClientWidget() { delete ui; }
void ClientWidget::on_connButton_clicked() { std::cout << "connecting" << std::endl; QString ip = ui->lineEdit->text(); QString port = ui->lineEdit_2->text(); quint16 p = port.toUInt(); socket->connectToHost(ip, p); }
void ClientWidget::on_closeButton_clicked() { if(socket != nullptr) { socket->disconnectFromHost(); socket->close(); } }
void ClientWidget::on_sendButton_clicked() { if(socket != nullptr) { QString msg = ui->textEdit_2->toPlainText(); socket->write(msg.toUtf8().data()); } }
|
相比于服务端,客户端要做的内容要简单一些,主要就是主动发起连接,收发信息以及关闭socket连接。
各段代码的内容我的注释写的很明白了,若是还不懂欢迎在我博客下方的评论区发起评论,我会在收到消息后第一时间与发起者进行技术讨论。
关键内容就是上面那些,那么下面来看看我的头文件:
server的头文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #ifndef SERVERWIDGET_H #define SERVERWIDGET_H
#include <QWidget> #include <iostream> #include <QTcpServer> #include <QTcpSocket> #include <QHostAddress>
QT_BEGIN_NAMESPACE namespace Ui { class ServerWidget; } QT_END_NAMESPACE
class ServerWidget : public QWidget { Q_OBJECT
public: ServerWidget(QWidget *parent = nullptr); ~ServerWidget();
private slots: void on_pushButton_clicked();
void on_pushButton_2_clicked();
private: Ui::ServerWidget *ui; QTcpServer* server; QTcpSocket* socket; char sock_count; }; #endif
|
client的头文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #ifndef CLIENTWIDGET_H #define CLIENTWIDGET_H
#include <QWidget> #include <QHostAddress> #include <QTcpSocket>
QT_BEGIN_NAMESPACE namespace Ui { class ClientWidget; } QT_END_NAMESPACE
class ClientWidget : public QWidget { Q_OBJECT
public: ClientWidget(QWidget *parent = nullptr); ~ClientWidget();
private slots: void on_connButton_clicked();
void on_closeButton_clicked();
void on_sendButton_clicked();
private: Ui::ClientWidget *ui; QTcpSocket* socket; }; #endif
|
最后再说一次,别忘记在项目的.pro文件里加上:
好了,本篇完。