QT TCP练习

QT TCP练习

一、简述

    简单的单个服务器端与多个客户端的基于TCP协议的双向通信 练习

二、效果


三、工程结构


四、源码文件

TcpClient.pro文件

QT +=widgets gui network

HEADERS += \
    tcpclient.h

SOURCES += \
    main.cpp \
    tcpclient.cpp

tcpclient.h文件

#ifndef TCPCLIENT_H
#define TCPCLIENT_H

#include <QWidget>
#include <QTcpSocket>
#include <QTcpSocket>
#include <QGridLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QTextBrowser>
class TcpClient : public QWidget
{
    Q_OBJECT
public:
    explicit TcpClient(QWidget *parent = 0);

signals:

public slots:
    void MySend();//向服务端发送数据
    void MyReceive();//接收数据
private:
    QTcpSocket* _socket;//通信socket
    QLineEdit* _lineEdit;//行文本编辑框,编写要发送给服务器的信息
    QTextBrowser* _text;//展示接收到的信息

};

#endif // TCPCLIENT_H

tcpclient.cpp文件

#include "tcpclient.h"
#include <QDebug>
TcpClient::TcpClient(QWidget *parent) :
    QWidget(parent)
{
    //创建通信socket
    _socket = new QTcpSocket();


    //指定要通信的服务器的ip地址以及端口
    _socket->connectToHost("127.0.0.1", 8899);

    //创建行文本编辑框
    _lineEdit = new QLineEdit;

    //创建“发送”按钮
    QPushButton* sendBtn = new QPushButton("发送");

    //创建QTextBrowser,用来展示服务器端的信息
    _text = new QTextBrowser;

    //创建一个QGridLayout网格布局
    QGridLayout* glayout = new QGridLayout(this);
    //将_text、_lineEdit和sendBtn添加到QHBoxLayout布局
    glayout->addWidget(_lineEdit,0,0,1,2);//将_lineEdit添加到第0行第0列,占据1行、2列
    glayout->addWidget(sendBtn,0,2,1,1);//将sendBtn添加到第0行第2列,占据1行、1列
    glayout->addWidget(_text,1,0,1,3);//将_text添加到第1行第0列,占据1行、3列

    //连接发送按钮点击触发的事件
    connect(sendBtn, SIGNAL(clicked()), this, SLOT(MySend()));
    //当焦点在行文本编辑框时,按下回车键触发的事件
    connect(_lineEdit, SIGNAL(returnPressed()), this, SLOT(MySend()));

    //连接_socket收到数据时的处理函数
    connect(_socket, SIGNAL(readyRead()),this, SLOT(MyReceive()));
}

void TcpClient::MySend()
{
    //获取行文本编辑框的文本内容,即要发送给服务器的信息
    QString text = _lineEdit->text();

    if(!text.isEmpty())//如果信息不为空
    {
        //将信息发送给服务端,可以选择QByteArray格式
        _socket->write(text.toUtf8());
        //发送完毕将编辑框清空
        _lineEdit->clear();
    }
}

void TcpClient::MyReceive()
{
    qDebug()<<"text";
    // 接收数据,判断是否有数据,如果有,通过readAll函数获取所有数据
    while(_socket->bytesAvailable() > 0)
    {
        QByteArray buf = _socket->readAll();//获取所有数据
        _text->append(buf);//在QTextBrowser上展示收到的信息
    }
}

main.cpp文件

扫描二维码关注公众号,回复: 1443046 查看本文章
#include <QApplication>
#include <tcpclient.h>

int main(int argc,char* argv[])
{
    QApplication app(argc,argv);

    TcpClient client; //创建客户端窗体
    client.setWindowTitle("客户端");//设置窗体标题
    client.show();//show出客户端窗体

    return app.exec();
}

TcpServer.pro文件

QT += widgets gui network

HEADERS += \
    tcpserver.h

SOURCES += \
    main.cpp \
    tcpserver.cpp

tcpserver.h文件

#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTextBrowser>
#include <QGridLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>
#include <QComboBox>
#include <QList>

class TcpServer : public QWidget
{
    Q_OBJECT
public:
    explicit TcpServer(QWidget *parent = 0);

signals:

public slots:
    void MyConnection();//处理客户端连接
    void MyReceive();//接收客户端信息
    void MySend();//向客户端发送信息
    void MyDisconnected();//断开连接时处理对应的socket
private:
    QTcpServer* _server;//服务器
    QTcpSocket* _socket;//通信socket
    QTextBrowser* _text;//展示接收到的信息
    QComboBox* _sendAddrCbb;//保存客户端的IP、端口
    QLineEdit* _lineEdit;//行文本编辑框,编写要发送给客户端的信息
    QList<QTcpSocket*> _socketList;//通信socket列表

};

#endif // TCPSERVER_H

tcpserver.cpp文件

#include "tcpserver.h"
#include <QDebug>

TcpServer::TcpServer(QWidget *parent) :
    QWidget(parent)
{
    // 创建服务器
    _server = new QTcpServer(this);
    //监听服务器的所有ip地址的8899端口
    _server->listen(QHostAddress::Any, 8899);

    // 当有客户端来请求连接的是_server监听的端口时,调用MyConnection方法
    connect(_server, SIGNAL(newConnection()),this, SLOT(MyConnection()));


    //创建QLabel标签
    QLabel* sendAddrLbl = new QLabel("发送至");

    //创建QComboBox
    _sendAddrCbb = new QComboBox();
    _sendAddrCbb->addItem("请选择IP及端口");
    //创建行文本编辑框
    _lineEdit = new QLineEdit;

    //创建“发送”按钮
    QPushButton* sendBtn = new QPushButton("发送");

    //创建QTextBrowser,用来展示客户端的信息
    _text = new QTextBrowser;

    //创建一个QGridLayout网格布局
    QGridLayout* glayout = new QGridLayout(this);
    //将_text、_lineEdit和sendBtn添加到QHBoxLayout布局
    glayout->addWidget(sendAddrLbl,0,0,1,1);//将sendAddrLbl添加到第0行第0列,占据1行、1列
    glayout->addWidget(_sendAddrCbb,0,1,1,2);//将sendAddrCbb添加到第0行第1列,占据1行、2列
    glayout->addWidget(_lineEdit,1,0,1,2);//将_lineEdit添加到第1行第0列,占据1行、2列
    glayout->addWidget(sendBtn,1,2,1,1);//将sendBtn添加到第1行第2列,占据1行、1列
    glayout->addWidget(_text,2,0,1,3);//将_text添加到第2行第列,占据1行、3列


    //连接发送按钮点击触发的事件
    connect(sendBtn, SIGNAL(clicked()), this, SLOT(MySend()));
    //当焦点在行文本编辑框时,按下回车键触发的事件
    connect(_lineEdit, SIGNAL(returnPressed()), this, SLOT(MySend()));

}

void TcpServer::MyConnection()
{
    // 循环处理待处理的连接
    while(_server->hasPendingConnections())
    {
        //调用nextPeddingConnection去获得连接的socket,
        //即取得与具体某一个客户端通信socket,一个通信socket对应一个一个客户端
        _socket = _server->nextPendingConnection();
        //添加到soclet列表
        _socketList.append(_socket);

        //在ComBoBox添加已经连接上服务器的客户端ip、端口
         _sendAddrCbb->addItem(_socket->peerAddress().toString()+":"+QString::number(_socket->peerPort()));

        //为新的socket提供槽函数,来接收数据
        connect(_socket, SIGNAL(readyRead()),this, SLOT(MyReceive()));
        connect(_socket, SIGNAL(disconnected()),this, SLOT(MyDisconnected()));//与客户端断开连接时,进行相应处理
    }
}

void TcpServer::MyReceive()
{
    for(int i=0;i<_socketList.size();++i)
    {
        // 接收数据,判断是否有数据,如果有,通过readAll函数获取所有数据
        while(_socketList.at(i)->bytesAvailable() > 0)
        {
             QByteArray buf = ("["+_socketList.at(i)->peerAddress().toString()+":"+QString::number(_socketList.at(i)->peerPort())+"]").toUtf8();
             buf.append(_socketList.at(i)->readAll());//获取所有数据
            _text->append(buf);//在QTextBrowser上展示收到的信息
        }
    }
}

void TcpServer::MySend()
{
    //获取行文本编辑框的文本内容,即要发送给客户端的信息
    QString text = _lineEdit->text();
    int index = _sendAddrCbb->currentIndex();
    //如果信息不为空且已经选择了已经连接的客户端IP地址及端口
    if(!text.isEmpty() && index != 0)
    {
        //根据index找到客户端对应的socket将信息发送给客户端,以QByteArray格式发送数据
        if(index-1<=_socketList.size())
        {
            _socketList.at(index-1)->write(text.toUtf8());
        }

        //发送完毕将编辑框清空
        _lineEdit->clear();
    }
}

void TcpServer::MyDisconnected()
{
    for(int i=0;i<_socketList.size();++i)
    {
        //找到已经断开连接的socket
        if(_socketList.at(i)->state() == QAbstractSocket::UnconnectedState)
        {
            _sendAddrCbb->removeItem(i+1);//在选择列表中去掉断开连接的IP地址、端口
            _socketList.removeAt(i);//去掉断开连接的socket
            break;
        }
    }
}

main.cpp文件

#include <QApplication>
#include <tcpserver.h>

int main(int argc,char* argv[])
{
    QApplication app(argc,argv);

    TcpServer server; //创建服务器窗体
    server.setWindowTitle("服务器端");//设置窗体标题
    server.show();//show出服务器窗体

    return app.exec();
}

猜你喜欢

转载自blog.csdn.net/nanfeibuyi/article/details/80337492