QT:TCP网络编程实现

QT TCP编程

QTcpServer    QTcpSocket

《案例》网络聊天室(局域网)
① 服务器
1 )使用QTcpServer创建并发服务器
2 )保存所有客户端的socket套接字
3 )接收客户端的消息
4 )转发消息给所有的客户端
工程名:Server
类名:TcpServer

② 客户端
1 )使用QTcpSocket创建tcp客户端
2 )连接到指定的服务器
3 )发送消息到服务器
4 )接收聊天消息并显示
工程名:Client
类名:TcpClient


/* 客户端 - 代码演示 */

// logindialog.h
#ifndef LOGINDIALOG_H
#define LOGINDIALOG_H
#include <QDialog>
namespace Ui {
class LoginDialog;
}
class LoginDialog : public QDialog
{
    Q_OBJECT
public:
    explicit LoginDialog(QWidget *parent = 0);
    ~LoginDialog();
private slots:
    void on_pushButton_clicked();
private:
    Ui::LoginDialog *ui;
};
#endif // LOGINDIALOG_H

// logindialog.cpp
#include "logindialog.h"
#include "ui_logindialog.h"
LoginDialog::LoginDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::LoginDialog)
{
    ui->setupUi(this);
}
LoginDialog::~LoginDialog()
{
    delete ui;
}
void LoginDialog::on_pushButton_clicked()
{
    qDebug("登录成功!");
    close();
}

// TcpClient.h
#ifndef TCPCLIENT_H
#define TCPCLIENT_H
#include <QDialog>
#include <QHostAddress>
#include <QTcpSocket>
namespace Ui {
class TcpClient;
}
class TcpClient : public QDialog
{
    Q_OBJECT
public:
    explicit TcpClient(QWidget *parent = 0);
    ~TcpClient();
private slots:
    //发生消息按钮槽函数
    void on_sendButton_clicked();
    //连接服务器按钮槽函数
    void on_connectButton_clicked();
    //和服务器建立连接槽函数
    void onConnected();
    //和服务器断开连接槽函数
    void onDisconnected();
    //接收服务器消息的槽函数
    void slotDataRecived();
private:
    Ui::TcpClient *ui;
    //标记客户端连接状态 ture->在线 flase->离线
    bool status;
    QTcpSocket tcpSocket;
    quint16 port;//服务器端口
    QHostAddress serverIp;//服务器的IP
    QString userName;//聊天昵称
};
#endif // TCPCLIENT_H

// TcpClient.cpp
#include "TcpClient.h"
#include "ui_TcpClient.h"
TcpClient::TcpClient(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TcpClient)
{
    ui->setupUi(this);
    status = false;//初始化连接状态:离线
    //和服务器连接是发送信号connected()
    connect(&tcpSocket,SIGNAL(connected()),
            this,SLOT(onConnected()));
    //和服务器断开连接是发送信号disconnected()
    connect(&tcpSocket,SIGNAL(disconnected()),
            this,SLOT(onDisconnected()));
    //套接字有数据到来是发送信号readyRead
    connect(&tcpSocket,SIGNAL(readyRead()),
            this,SLOT(slotDataRecived()));
}
TcpClient::~TcpClient(  )
{
    delete ui;
}
//发送消息按钮的槽函数
void TcpClient::on_sendButton_clicked()
{
    //获取用户输入的消息
    QString msg = ui->sendEdit->text();
    if( msg == ""){
        return;
    }
    msg = userName + ":" + msg;
    //发送消息
    tcpSocket.write(msg.toLocal8Bit());
    //清空输入组件
    ui->sendEdit->clear();
}
void TcpClient::on_connectButton_clicked()
{
    //如果当前是离线状态则连接服务器
    if(status == false){
        status = true;
        //获取服务器IP
        serverIp.setAddress(ui->serverIpEdit->text());
        //获取聊天昵称
        userName = ui->userEdit->text();
        //获取服务器端口
        port = ui->portEdit->text().toShort();
        //向服务器发送连接请求
        tcpSocket.connectToHost(serverIp,port);
    }
    else{ //如果当前是在线状态则断开连接
        //发送下线消息
        QString msg = userName + ":离开聊天室";
        tcpSocket.write(msg.toLocal8Bit());
        //断开和服务器的连接
        tcpSocket.disconnectFromHost();
        status = false;
    }
}
//和服务器建立连接槽函数
void TcpClient::onConnected()
{
    //使能发送消息按钮
    ui->sendButton->setEnabled(true);
    //"连接服务器" 内容改为 "离开聊天室"
    ui->connectButton->setText("离开聊天室");
    //禁用输入组件
    ui->serverIpEdit->setEnabled(false);
    ui->portEdit->setEnabled(false);
    ui->userEdit->setEnabled(false);
    //发送上线消息
    QString msg = userName + ":进入聊天室";
    tcpSocket.write(msg.toLocal8Bit());
}
//和服务器断开连接槽函数
void TcpClient::onDisconnected()
{
    //禁用发送消息按钮
    ui->sendButton->setEnabled(false);
    //使能输入组件
    ui->serverIpEdit->setEnabled(true);
    ui->portEdit->setEnabled(true);
    ui->userEdit->setEnabled(true);
    // "离开聊天室" 内容改为 "连接服务器"
    ui->connectButton->setText("连接服务器");
}
//接收服务器消息的槽函数
void TcpClient::slotDataRecived()
{
    if(tcpSocket.bytesAvailable()){
        QByteArray datagram;
        datagram.resize(tcpSocket.bytesAvailable());
        //读取消息
        tcpSocket.read(datagram.data(),datagram.size());
        //显示到ui
        ui->listWidget->addItem(datagram);
    }
}

// main.cpp
#include "TcpClient.h"
#include "logindialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    LoginDialog login;
    login.show();
    login.exec();
    TcpClient w;
    w.show();
    return a.exec();
}


/* 服务器端 - 代码演示 */

// TcpServer.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QDialog>
#include <QTcpServer>
#include <QTcpSocket>
namespace Ui {
class TcpServer;
}
class TcpServer : public QDialog
{
    Q_OBJECT
public:
    explicit TcpServer(QWidget *parent = 0);
    ~TcpServer();
private slots:
    //创建按钮信号对应的操函数
    void on_createButton_clicked();
    //客户端和服务器建立连接时,发送信号newConection
    void onNewConnection(void);
    //接收客户端数据的槽函数
    void slotDataReceived(void);
private:
    //转发消息到所有的客户端
    void sendMessage(const QByteArray&);
private:
    Ui::TcpServer *ui;
    QTcpServer tcpServer;//服务器对象
    quint16 port;//服务器端口
    //容器:保存所有和客户端通信的socket
    QList <QTcpSocket*> tcpClientList;
};
#endif // TCPSERVER_H

// TcpServer.cpp
#include "TcpServer.h"
#include "ui_TcpServer.h"
TcpServer::TcpServer(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TcpServer)
{
    ui->setupUi(this);
    connect(&tcpServer,SIGNAL(newConnection()),
            this,SLOT(onNewConnection()));
}
TcpServer::~TcpServer()
{
    delete ui;
}
//创建服务器
void TcpServer::on_createButton_clicked()
{
    //获取端口号
    port = ui->portEdit->text().toShort();
    //开启服务器
    tcpServer.listen(QHostAddress::Any,port);
    //禁用创建服务器按钮和端口输入
    ui->createButton->setEnabled(false);
    ui->portEdit->setEnabled(false);
}
//客户端和服务器建立连接时,发送信号newConection
void TcpServer::onNewConnection(void)
{
    //获取和客户端通信的tcp套接子
    QTcpSocket* tcpClient =
            tcpServer.nextPendingConnection();
    //保存当前套接子到容器
    tcpClientList.append(tcpClient);
    //当客户端给服务器发送消息时,发送信号readyRead
    connect(tcpClient,SIGNAL(readyRead()),
            this,SLOT(slotDataReceived()));
}
//接收客户端数据的槽函数
void TcpServer::slotDataReceived(void)
{
    //遍历所有客户端
    for(int i=0; i<tcpClientList.count(); i++){
        //检查当前客户端套接子是否有数据到来
        if(tcpClientList.at(i)->bytesAvailable()){
            //读取消息
            QByteArray readbuf =
                    tcpClientList.at(i)->readAll();
            //显示消息到服务器Ui
            ui->listWidget->addItem(readbuf);
            //转发消息给所有的客户端
            sendMessage(readbuf);
        }
    }
}
//转发消息到所有的客户端
void TcpServer::sendMessage(const QByteArray& msg)
{
    for(int i=0; i<tcpClientList.count(); i++){
        tcpClientList.at(i)->write(msg);
    }
}

// main.cpp
#include "TcpServer.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    TcpServer w;
    w.show();
    return a.exec();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姜源Jerry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值