这段时间用到了QT的TCP通信,做了初步的学习与尝试,编写了一个客户端和服务器基于窗口通信的小例程。
使用QT的网络套接字需要.pro文件中加入一句:
QT += network
一、客户端
1、客户端的代码比服务器稍简单,总的来说,使用QT中的QTcpSocket类与服务器进行通信只需要以下5步:
(1)创建QTcpSocket套接字对象
socket = new QTcpSocket();
(2)使用这个对象连接服务器
socket->connectToHost(IP, port);
(3)使用write函数向服务器发送数据
socket->write(data);
(4)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据
1 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
2
3 void MainWindow::socket_Read_Data()
4 {
5 QByteArray buffer;
6 //读取缓冲区数据
7 buffer = socket->readAll();
8 }
(5)断开与服务器的连接(关于close()和disconnectFromHost()的区别,可以按F1看帮助)
socket->disconnectFromHost();
2、以下是客户端的例程
首先是mainwindow.h文件:
1 //mainwindow.h
2 #ifndef MAINWINDOW_H
3 #define MAINWINDOW_H
4
5 #include <QMainWindow>
6 #include <QTcpSocket>
7
8 namespace Ui {
9 class MainWindow;
10 }
11
12 class MainWindow : public QMainWindow
13 {
14 Q_OBJECT
15
16 public:
17 explicit MainWindow(QWidget *parent = 0);
18 ~MainWindow();
19
20 private slots:
21
22 void on_pushButton_Connect_clicked();
23
24 void on_pushButton_Send_clicked();
25
26 void socket_Read_Data();
27
28 void socket_Disconnected();
29
30 private:
31 Ui::MainWindow *ui;
32 QTcpSocket *socket;
33 };
34
35 #endif // MAINWINDOW_H
然后是mainwindow.cpp文件:
1 //mainwindow.cpp
2 #include "mainwindow.h"
3 #include "ui_mainwindow.h"
4
5 MainWindow::MainWindow(QWidget *parent) :
6 QMainWindow(parent),
7 ui(new Ui::MainWindow)
8 {
9 ui->setupUi(this);
10
11 socket = new QTcpSocket();
12
13 //连接信号槽
14 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
15 QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
16
17 ui->pushButton_Send->setEnabled(false);
18 ui->lineEdit_IP->setText("127.0.0.1");
19 ui->lineEdit_Port->setText("8765");
20
21 }
22
23 MainWindow::~MainWindow()
24 {
25 delete this->socket;
26 delete ui;
27 }
28
29 void MainWindow::on_pushButton_Connect_clicked()
30 {
31 if(ui->pushButton_Connect->text() == tr("连接"))
32 {
33 QString IP;
34 int port;
35
36 //获取IP地址
37 IP = ui->lineEdit_IP->text();
38 //获取端口号
39 port = ui->lineEdit_Port->text().toInt();
40
41 //取消已有的连接
42 socket->abort();
43 //连接服务器
44 socket->connectToHost(IP, port);
45
46 //等待连接成功
47 if(!socket->waitForConnected(30000))
48 {
49 qDebug() << "Connection failed!";
50 return;
51 }
52 qDebug() << "Connect successfully!";
53
54 //发送按键使能
55 ui->pushButton_Send->setEnabled(true);
56 //修改按键文字
57 ui->pushButton_Connect->setText("断开连接");
58 }
59 else
60 {
61 //断开连接
62 socket->disconnectFromHost();
63 //修改按键文字
64 ui->pushButton_Connect->setText("连接");
65 ui->pushButton_Send->setEnabled(false);
66 }
67 }
68
69 void MainWindow::on_pushButton_Send_clicked()
70 {
71 qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
72 //获取文本框内容并以ASCII码形式发送
73 socket->write(ui->textEdit_Send->toPlainText().toLatin1());
74 socket->flush();
75 }
76
77 void MainWindow::socket_Read_Data()
78 {
79 QByteArray buffer;
80 //读取缓冲区数据
81 buffer = socket->readAll();
82 if(!buffer.isEmpty())
83 {
84 QString str = ui->textEdit_Recv->toPlainText();
85 str+=tr(buffer);
86 //刷新显示
87 ui->textEdit_Recv->setText(str);
88 }
89 }
90
91 void MainWindow::socket_Disconnected()
92 {
93 //发送按键失能
94 ui->pushButton_Send->setEnabled(false);
95 //修改按键文字
96 ui->pushButton_Connect->setText("连接");
97 qDebug() << "Disconnected!";
98 }
最后是ui的设计:
二、服务器
1、服务器除了使用到了QTcpSocket类,还需要用到QTcpSever类。即便如此,也只是比客户端复杂一点点,用到了6个步骤:
(1)创建QTcpSever对象
server = new QTcpServer();
(2)侦听一个端口,使得客户端可以使用这个端口访问服务器
server->listen(QHostAddress::Any, port);
(3)当服务器被客户端访问时,会发出newConnection()信号,因此为该信号添加槽函数,并用一个QTcpSocket对象接受客户端访问
1 connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
2
3 void MainWindow::server_New_Connect()
4 {
5 //获取客户端连接
6 socket = server->nextPendingConnection();
7 }
(4)使用socket的write函数向客户端发送数据
socket->write(data);
(5)当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据
1 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
2
3 void MainWindow::socket_Read_Data()
4 {
5 QByteArray buffer;
6 //读取缓冲区数据
7 buffer = socket->readAll();
8 }
(6)取消侦听
server->close();
2、以下是服务器的例程
首先是mainwindow.h文件:
1 //mainwindow.h
2 #ifndef MAINWINDOW_H
3 #define MAINWINDOW_H
4
5 #include <QMainWindow>
6 #include <QTcpServer>
7 #include <QTcpSocket>
8
9 namespace Ui {
10 class MainWindow;
11 }
12
13 class MainWindow : public QMainWindow
14 {
15 Q_OBJECT
16
17 public:
18 explicit MainWindow(QWidget *parent = 0);
19 ~MainWindow();
20
21 private slots:
22 void on_pushButton_Listen_clicked();
23
24 void on_pushButton_Send_clicked();
25
26 void server_New_Connect();
27
28 void socket_Read_Data();
29
30 void socket_Disconnected();
31
32 private:
33 Ui::MainWindow *ui;
34 QTcpServer* server;
35 QTcpSocket* socket;
36 };
37
38 #endif // MAINWINDOW_H
然后是mainwindow.cpp文件:
1 #include "mainwindow.h"
2 #include "ui_mainwindow.h"
3
4 MainWindow::MainWindow(QWidget *parent) :
5 QMainWindow(parent),
6 ui(new Ui::MainWindow)
7 {
8 ui->setupUi(this);
9
10 ui->lineEdit_Port->setText("8765");
11 ui->pushButton_Send->setEnabled(false);
12
13 server = new QTcpServer();
14
15 //连接信号槽
16 connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect);
17 }
18
19 MainWindow::~MainWindow()
20 {
21 server->close();
22 server->deleteLater();
23 delete ui;
24 }
25
26 void MainWindow::on_pushButton_Listen_clicked()
27 {
28 if(ui->pushButton_Listen->text() == tr("侦听"))
29 {
30 //从输入框获取端口号
31 int port = ui->lineEdit_Port->text().toInt();
32
33 //监听指定的端口
34 if(!server->listen(QHostAddress::Any, port))
35 {
36 //若出错,则输出错误信息
37 qDebug()<<server->errorString();
38 return;
39 }
40 //修改按键文字
41 ui->pushButton_Listen->setText("取消侦听");
42 qDebug()<< "Listen succeessfully!";
43 }
44 else
45 {
46 /*
47 //如果正在连接(点击侦听后立即取消侦听,若socket没有指定对象会有异常,应修正——2017.9.30)
48 if(socket->state() == QAbstractSocket::ConnectedState)
49 {
50 //关闭连接
51 socket->disconnectFromHost();
52 }
53 */
54 socket->abort();
55 //取消侦听
56 server->close();
57 //修改按键文字
58 ui->pushButton_Listen->setText("侦听");
59 //发送按键失能
60 ui->pushButton_Send->setEnabled(false);
61 }
62
63 }
64
65 void MainWindow::on_pushButton_Send_clicked()
66 {
67 qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
68 //获取文本框内容并以ASCII码形式发送
69 socket->write(ui->textEdit_Send->toPlainText().toLatin1());
70 socket->flush();
71 }
72
73 void MainWindow::server_New_Connect()
74 {
75 //获取客户端连接
76 socket = server->nextPendingConnection();
77 //连接QTcpSocket的信号槽,以读取新数据
78 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
79 QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
80 //发送按键使能
81 ui->pushButton_Send->setEnabled(true);
82
83 qDebug() << "A Client connect!";
84 }
85
86 void MainWindow::socket_Read_Data()
87 {
88 QByteArray buffer;
89 //读取缓冲区数据
90 buffer = socket->readAll();
91 if(!buffer.isEmpty())
92 {
93 QString str = ui->textEdit_Recv->toPlainText();
94 str+=tr(buffer);
95 //刷新显示
96 ui->textEdit_Recv->setText(str);
97 }
98 }
99
100 void MainWindow::socket_Disconnected()
101 {
102 //发送按键失能
103 ui->pushButton_Send->setEnabled(false);
104 qDebug() << "Disconnected!";
105 }
最后是ui的设计:
三、运行结果