qt tcp

服务器

server.h

#ifndef SERVER_H
#define SERVER_H

#include <QTcpServer>
#include <QObject>
#include <QList>
#include "tcpclientsocket.h"


class Server : public QTcpServer
{
    Q_OBJECT
public:
    explicit Server(QObject *parent = 0, int port = 0);
    QList<TcpClientSocket*> tcpclientsocketlist;

protected:
    virtual void incomingConnection(qintptr socketDescriptor);  //只要出现一个新的连接,就会自动调用这个函数

protected slots:
    void slotupdateserver(QString, int);    //用来处理tcpclient发过来的信号
    void slotclientdisconnect(int);

signals:
    void updateserver(QString, int);    //发送信号给界面, 让界面更新信息

};

#endif // SERVER_H

server.cpp

#include "server.h"
#include "tcpclientsocket.h"
#include <QHostAddress>
#include <QDebug>

Server::Server(QObject *parent, int port) : QTcpServer(parent)
{
    listen(QHostAddress::Any, port);   //监听

}

void Server::incomingConnection(qintptr socketDescriptor)
{
    //只要有新连接就生成一个新的套接字
    TcpClientSocket *tcpclientsocket = new TcpClientSocket(this);
    tcpclientsocket->setSocketDescriptor(socketDescriptor);

    //将新创建的套接字加入到客户端套接字列表中
    tcpclientsocketlist.append(tcpclientsocket);

    //接收到tcpclientsocket发过来的更新界面的信号
    connect(tcpclientsocket, &TcpClientSocket::updateserver, this, &Server::slotupdateserver);
    connect(tcpclientsocket, &TcpClientSocket::clientDisconnected, this, &Server::slotclientdisconnect);

    //return emit  QTcpServer::newConnection();
}

void Server::slotupdateserver(QString msg, int length)
{
    //将这个信号发送给界面
    emit updateserver(msg, length);

    QString userName = msg.section("##", 0, 0);
    QString text = msg.section("##", 1, 1);

    //将收到的信号发送给每个客户端,从套接字列表中找到需要接收的套接字
    for(int i = 0; i < tcpclientsocketlist.count(); i++) {
        QTcpSocket *item = tcpclientsocketlist.at(i);

        QString sendInfo = userName + " ";
        item->write(sendInfo.toUtf8().data());
        //处理数据,按格式发送
        QString str = text;
        string buf = str.toLatin1().data();
        string sendText;   //存放要发送的数据
        size_t j = 0;
        while(j < buf.size()) {
            for(size_t i = 1; i <= 11; i++) {
                if((j + i) <= buf.size()) {

                    if(i == 11) {
                        i = 1;
                    }

                    sendText = buf.substr(j, i);
                    //发送数据
                    sendText =  sendText + "~~~";
                    //tcpsocket->write(sendText.data());

                    item->write(sendText.data());
                }
                else {
                    sendText = buf.substr(j, (buf.size() - j));
                    //发送数据
                    sendText = sendText + "~~~";
                    item->write(sendText.data());
                    break;
                }
                j += i;
//                if(i == 255) {
//                    i = 1;
//                }
                sendText.clear();
            }
            break;
        }




    }
}

void Server::slotclientdisconnect(int descriptor)
{
    for(int i = 0; i < tcpclientsocketlist.count(); i++) {
        QTcpSocket *item = tcpclientsocketlist.at(i);
        //如果有客户端断开连接,将列表中的套接字删除
        if(item->socketDescriptor() == descriptor) {
            tcpclientsocketlist.removeAt(i);
            return;
        }
    }
    return;
}

widget.h

#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QWidget>
#include "server.h"

namespace Ui {
class Widget;
}

class TcpServer : public QWidget
{
    Q_OBJECT

public:
    explicit TcpServer(QWidget *parent = 0);
    ~TcpServer();

protected slots:
    void slotupdateserver(QString, int);  //接收server发过来的信号就更新界面信息

private slots:
    void on_Button_waitConnect_clicked();

    void on_pushButton_clicked();

private:
    Ui::Widget *ui;

    int port;
    Server *server;

};

#endif // TCPSERVER_H

widget.cpp

#include "widget.h"
#include "server.h"
#include "ui_widget.h"
#include <QDebug>

TcpServer::TcpServer(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    port = 8888;
}

TcpServer::~TcpServer()
{
    delete ui;
}


void TcpServer::on_Button_waitConnect_clicked()
{
    server  = new Server(this, port);

    connect(server, &Server::updateserver, this, &TcpServer::slotupdateserver);


    ui->textEdit->append("创建成功,可以连接");

    ui->Button_waitConnect->setEnabled(false);
}


void TcpServer::slotupdateserver(QString msg, int length)
{
    ui->textEdit->append(msg);
}


void TcpServer::on_pushButton_clicked()
{
    TcpServer another;
    another.show();
}

tcpclientsocket.h

#ifndef TCPCLIENTSOCKET_H
#define TCPCLIENTSOCKET_H

#include <QTcpSocket>
#include <iostream>
#include <string>
using namespace std;


class TcpClientSocket : public QTcpSocket
{
    Q_OBJECT
public:
    explicit TcpClientSocket(QObject *parent = nullptr);

protected slots:
    void recvdata();  //处理readyRead信号读取数据
    void slotclientdisconneceted();  //客户端断开触发disconnected,处理这个信号

signals:
    void updateserver(QString, int);  //用来告诉tcpserver需要更新界面
    void clientDisconnected(int);   //告诉server有客户端断开

public slots:

private:
    size_t strSize;
};

#endif // TCPCLIENTSOCKET_H

tcpclientsocket.cpp

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

TcpClientSocket::TcpClientSocket(QObject *parent) : QTcpSocket(parent)
{
    //客户端发过来的数据触发readyRead信号
    connect(this, &TcpClientSocket::readyRead, this, &TcpClientSocket::recvdata);
    connect(this, &TcpClientSocket::disconnected, this, &TcpClientSocket::slotclientdisconneceted);
}

void TcpClientSocket::recvdata()
{
    QByteArray array = readAll();
    int length = array.size();

    QString userName = QString(array).section("##", 0, 0);

    strSize = QString(array).section("##", 1, 1).toInt();
    //正文内容
    string strText = QString(array).section("##", 2, 2).toLatin1().data();
    string buf;
    for(size_t i = 0; i < strText.size(); i++) {
        buf.append(strText.substr(i, 1));
    }
    if(strSize != buf.size()) {
        qDebug() << "读取出错";
        return;
    }

    if(buf.size() == 0) {
        QString msg = userName;
        emit updateserver(msg, length);
    }
    else {
        QString msg = userName + "##" + buf.data();
        emit updateserver(msg, length);
    }

}

void TcpClientSocket::slotclientdisconneceted()
{
    emit clientDisconnected(this->socketDescriptor());
}

客户端

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <iostream>
#include <string>
#include <QHostAddress>
using namespace std;

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();


private slots:
    void on_send_clicked();

    void on_connectordisconnect_clicked();

    void slotconnectedsuccess();

    void slotreceive();

    void slotdisconnected();

private:
    Ui::Widget *ui;
    bool status;
    size_t strSize;
    int port;
    QHostAddress *serverIp;
    QString userName;
    QTcpSocket *tcpSocket;

};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include <QMessageBox>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    setWindowTitle("Client");
    status = false;
    port = 8899;
    ui->port->setText(QString::number(port));
    serverIp = new QHostAddress();
    ui->send->setEnabled(true);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_send_clicked()
{
    if(ui->lineEdit->text() == "")
    {
        return;
    }
    QString str = ui->lineEdit->text();
    qint64 textSize = str.size();
    QString strHead = QString("%1##%2##%3").arg(userName+": ").arg(textSize).arg(str);
    tcpSocket->write(strHead.toUtf8().data());
    ui->lineEdit->clear();
}

void Widget::on_connectordisconnect_clicked()
{
    if(status == false)
    {
        QString ip = ui->ip->text();
        if(!serverIp->setAddress(ip))
        {
            QMessageBox::warning(this,"错误","ip地址不正确");
            return;
        }

        if(ui->username->text() == "")
        {
            QMessageBox::warning(this,"错误","用户名不能为空");
            return;
        }
        userName = ui->username->text();
        tcpSocket = new QTcpSocket(this);
        tcpSocket->connectToHost(*serverIp,port);
        connect(tcpSocket,&QTcpSocket::connected,this,&Widget::slotconnectedsuccess);
        connect(tcpSocket,&QTcpSocket::readyRead,this,&Widget::slotreceive);
        status = true;
    }
    else {
        QString msg = userName + ":disconnected";
        tcpSocket->write(msg.toUtf8().data());
        tcpSocket->disconnectFromHost();
        status = false;
        connect(tcpSocket,&QTcpSocket::disconnected,this,&Widget::slotdisconnected);
    }
}

void Widget::slotconnectedsuccess()
{
    ui->textEdit->append("连接成功");
    ui->send->setEnabled(true);
    ui->connectordisconnect->setText("断开服务器");
    QString msg = userName+":connected";
    tcpSocket->write(msg.toUtf8().data());
}

void Widget::slotreceive()
{
    QByteArray array = tcpSocket->readAll();
    ui->textEdit->append(array.data());
}

void Widget::slotdisconnected()
{
    ui->send->setEnabled(false);
    ui->connectordisconnect->setText("连接服务器");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值