2. TCP服务器基础监听

任务目标

实现一个基于QTcpServer的TCP服务器,监听指定端口(默认8888),接受客户端连接,并将收到的消息原样回显给客户端。通过QT自带的客户端工具或telnet即可验证功能。

环境依赖

Qt 5.12+(含Network模块),在.pro文件中添加:

QT += core network

关键完整代码


// tcp_echo_server.h
#ifndef TCP_ECHO_SERVER_H
#define TCP_ECHO_SERVER_H

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>

class TcpEchoServer : public QObject
{
    Q_OBJECT
public:
    explicit TcpEchoServer(quint16 port, QObject *parent = nullptr);

private slots:
    void onNewConnection();
    void onReadyRead();
    void onClientDisconnected();

private:
    QTcpServer *m_server;
};

#endif // TCP_ECHO_SERVER_H

// tcp_echo_server.cpp
#include "tcp_echo_server.h"
#include <QDebug>

TcpEchoServer::TcpEchoServer(quint16 port, QObject *parent)
    : QObject(parent), m_server(new QTcpServer(this))
{
    if (!m_server->listen(QHostAddress::Any, port)) {
        qDebug() << "监听失败:" << m_server->errorString();
        return;
    }
    qDebug() << "服务器已启动,监听端口:" << port;
    connect(m_server, &QTcpServer::newConnection,
            this, &TcpEchoServer::onNewConnection);
}

void TcpEchoServer::onNewConnection()
{
    while (m_server->hasPendingConnections()) {
        QTcpSocket *client = m_server->nextPendingConnection();
        qDebug() << "新客户端连接:" << client->peerAddress().toString()
                 << ":" << client->peerPort();
        connect(client, &QTcpSocket::readyRead,
                this, &TcpEchoServer::onReadyRead);
        connect(client, &QTcpSocket::disconnected,
                this, &TcpEchoServer::onClientDisconnected);
    }
}

void TcpEchoServer::onReadyRead()
{
    QTcpSocket *client = qobject_cast<QTcpSocket*>(sender());
    if (!client) return;
    QByteArray data = client->readAll();
    qDebug() << "收到消息:" << QString::fromUtf8(data);
    client->write(data);  // 回显
}

void TcpEchoServer::onClientDisconnected()
{
    QTcpSocket *client = qobject_cast<QTcpSocket*>(sender());
    if (!client) return;
    qDebug() << "客户端断开:" << client->peerAddress().toString();
    client->deleteLater();
}

// main.cpp
#include <QCoreApplication>
#include "tcp_echo_server.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    quint16 port = 8888;
    if (argc > 1) {
        port = QString(argv[1]).toUShort();
    }
    TcpEchoServer server(port);
    return a.exec();
}

运行与验证

编译运行:

qmake
make
./tcp_echo_server 8888

验证步骤:

  1. 启动服务器,控制台输出“服务器已启动,监听端口: 8888”;
  2. 打开终端,使用telnet连接:telnet 127.0.0.1 8888;
  3. 在telnet中输入任意文本(如“hello”),按回车;
  4. 服务器控制台打印“收到消息: hello”,同时telnet窗口立即显示“hello”回显;
  5. 输入多行不同内容,每次均能收到相同回显,说明回显功能正常;
  6. 关闭telnet,服务器控制台打印“客户端断开: 127.0.0.1”,服务器不崩溃,可继续接受新连接。

通过条件:客户端发送的每条消息都能被原样返回,且服务器日志中依次出现连接、收消息、断开的记录,即判定实现正确。

常见问题

  • 端口被占用:换用其他端口(如8889)启动,或先释放占用端口的进程。
  • telnet不可用:Windows需在“启用或关闭Windows功能”中勾选Telnet客户端;Linux使用apt install telnet安装。
  • 中文乱码:本示例使用UTF-8收发,若客户端发送GBK编码,可在onReadyRead中改用QString::fromLocal8Bit(data)接收。