第二步,实现TcpServer的通信功能。
C:\Users\Minwei\Projects\Qt\TcpServer\tcpserverwindow.h:
x1
2
3
4
5
6
7
8
9QT_BEGIN_NAMESPACE
10namespace Ui { class TcpServerWindow; }
11QT_END_NAMESPACE
12
13class TcpServerWindow : public QMainWindow
14{
15 Q_OBJECT
16
17public:
18 TcpServerWindow(QWidget *parent = nullptr);
19 ~TcpServerWindow();
20
21private slots:
22 void on_m_actListen_triggered();
23 void on_m_actClose_triggered();
24 void on_m_actClear_triggered();
25
26 void on_m_btnSend_clicked();
27
28 void on_m_server_newConnection();
29
30 void on_m_socket_readyRead();
31 void on_m_socket_disconnected();
32
33 void on_m_socket_stateChanged(
34 QAbstractSocket::SocketState socketState);
35 void on_m_socket_error(
36 QAbstractSocket::SocketError socketError);
37
38private:
39 Ui::TcpServerWindow *ui;
40 QLabel* m_labListenState;
41 QLabel* m_labSocketState;
42 QLabel* m_labSocketError;
43 QTcpServer* m_server;
44 QTcpSocket* m_socket;
45};
46
47// TCPSERVERWINDOW_H
C:\Users\Minwei\Projects\Qt\TcpServer\tcpserverwindow.cpp:
xxxxxxxxxx
1
2
3
4
5
6
7TcpServerWindow::TcpServerWindow(QWidget *parent)
8 : QMainWindow(parent)
9 , ui(new Ui::TcpServerWindow)
10 , m_labListenState(new QLabel("监听状态:关闭"))
11 , m_labSocketState(new QLabel(" 套接字状态:"))
12 , m_labSocketError(new QLabel(" 套接字错误:"))
13 , m_server(new QTcpServer(this))
14 , m_socket(Q_NULLPTR)
15{
16 ui->setupUi(this);
17
18 for (QHostAddress address : QHostInfo::fromName(
19 QHostInfo::localHostName()).addresses())
20 if(address.protocol() == QAbstractSocket::IPv4Protocol)
21 ui->m_comboLocalAddr->addItem(address.toString());
22
23 m_labListenState->setMinimumWidth(196);
24 ui->m_statusBar->addWidget(m_labListenState);
25 m_labSocketState->setMinimumWidth(197);
26 ui->m_statusBar->addWidget(m_labSocketState);
27 m_labSocketError->setMinimumWidth(197);
28 ui->m_statusBar->addWidget(m_labSocketError);
29
30 connect(m_server, SIGNAL(newConnection()),
31 this, SLOT(on_m_server_newConnection()));
32}
33
34TcpServerWindow::~TcpServerWindow()
35{
36 delete ui;
37}
38
39void TcpServerWindow::on_m_actListen_triggered()
40{
41 QHostAddress address(ui->m_comboLocalAddr->currentText());
42 quint16 port = ui->m_editLocalPort->text().toUShort();
43
44 if (m_server->listen(address, port))
45 {
46 ui->m_editOutput->appendPlainText(QString("监听%1:%2成功").
47 arg(address.toString()).arg(port));
48 m_labListenState->setText(QString("监听状态:%1:%2").
49 arg(address.toString()).arg(port));
50 }
51 else
52 ui->m_editOutput->appendPlainText(QString("监听%1:%2失败").
53 arg(address.toString()).arg(port));
54}
55
56void TcpServerWindow::on_m_actClose_triggered()
57{
58 m_server->close();
59
60 ui->m_editOutput->appendPlainText("关闭监听");
61 m_labListenState->setText("监听状态:关闭");
62}
63
64void TcpServerWindow::on_m_actClear_triggered()
65{
66 ui->m_editOutput->clear();
67}
68
69void TcpServerWindow::on_m_btnSend_clicked()
70{
71 QByteArray data((ui->m_editSend->text() + "\n").toUtf8());
72
73 qint64 nbytes = m_socket->write(data);
74
75 if (nbytes == -1)
76 ui->m_editOutput->appendPlainText("发送失败");
77 else
78 ui->m_editOutput->appendPlainText(QString("向%1:%2发送%3字节:%4").
79 arg(m_socket->peerAddress().toString()).arg(m_socket->peerPort()).
80 arg(nbytes).arg(QString(data).trimmed()));
81}
82
83void TcpServerWindow::on_m_server_newConnection()
84{
85 if (m_socket != Q_NULLPTR &&
86 m_socket->state() == QAbstractSocket::ConnectedState)
87 m_socket->disconnectFromHost();
88
89 m_socket = m_server->nextPendingConnection();
90
91 connect(m_socket, SIGNAL(readyRead()),
92 this, SLOT(on_m_socket_readyRead()));
93 connect(m_socket, SIGNAL(disconnected()),
94 this, SLOT(on_m_socket_disconnected()));
95
96 connect(m_socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
97 this, SLOT(on_m_socket_stateChanged(QAbstractSocket::SocketState)));
98 connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)),
99 this, SLOT(on_m_socket_error(QAbstractSocket::SocketError)));
100
101 ui->m_editOutput->appendPlainText(QString("接受%1:%2连接").
102 arg(m_socket->peerAddress().toString()).arg(m_socket->peerPort()));
103
104 ui->m_btnSend->setEnabled(true);
105}
106
107void TcpServerWindow::on_m_socket_readyRead()
108{
109 while (m_socket->canReadLine())
110 {
111 QByteArray data = m_socket->readLine();
112
113 ui->m_editOutput->appendPlainText(QString("从%1:%2接收%3字节:%4").
114 arg(m_socket->peerAddress().toString()).arg(m_socket->peerPort()).
115 arg(data.size()).arg(QString(data).trimmed()));
116 }
117}
118
119void TcpServerWindow::on_m_socket_disconnected()
120{
121 ui->m_btnSend->setEnabled(false);
122
123 ui->m_editOutput->appendPlainText(QString("断开%1:%2连接").
124 arg(m_socket->peerAddress().toString()).arg(m_socket->peerPort()));
125
126 m_socket->deleteLater();
127 m_socket = Q_NULLPTR;
128}
129
130void TcpServerWindow::on_m_socket_stateChanged(
131 QAbstractSocket::SocketState socketState)
132{
133 m_labSocketState->setText(QString(" 套接字状态:%1").arg(
134 QMetaEnum::fromType<QAbstractSocket::SocketState>().
135 valueToKey(socketState)));
136}
137
138void TcpServerWindow::on_m_socket_error(
139 QAbstractSocket::SocketError socketError)
140{
141 m_labSocketError->setText(QString(" 套接字错误:%1").arg(
142 QMetaEnum::fromType<QAbstractSocket::SocketError>().
143 valueToKey(socketError)));
144}
运行效果如图所示:
这个版本的TCP服务器只能和一个TCP客户机保持连接并通信。当有新客户机向服务器发起连接时,服务器会断开与之前客户机的连接。这主要体现在服务器程序处理QTcpServer对象发射的newConnection信号的槽函数上:
211...
2TcpServerWindow::TcpServerWindow(QWidget *parent)
3 ...
4{
5 ...
6 connect(m_server, SIGNAL(newConnection()),
7 this, SLOT(on_m_server_newConnection()));
8 ...
9}
10...
11void TcpServerWindow::on_m_server_newConnection()
12{
13 ...
14 if (m_socket != Q_NULLPTR &&
15 m_socket->state() == QAbstractSocket::ConnectedState)
16 m_socket->disconnectFromHost();
17 ...
18 m_socket = m_server->nextPendingConnection();
19 ...
20}
21...