Linux下的TCP通信流程

 

 Qt中基于TCP通信用到两个类,QTcpServer用于监听客户端请求,以及和客户端建立连接。QTcpSocket用于套接字通信。

服务器的通信流程

1、创建套接字服务器QTcpServer对象;

2、通过QTcpServer调用Listen来绑定地址和监听端口;

3、当有新的客户端请求连接会触发newConnection信号;

4、调用QTcpSocket *QTcpServer::nextPendingConnection()从中取出用于通信的QtcpSocket对象;

5、用QTcpSocket对象来和客户端通信。

客户端的通信流程

1、创建QTcpServer对象;

2、调用connectToHost连接服务器;

3、使用QTcpServer对象和服务器通信。

服务器窗口

 

 .h

class serverWidget : public QWidget
{
    Q_OBJECT

public:
    serverWidget(QWidget *parent = nullptr);
    ~serverWidget();

private slots:
    void on_btnstart_clicked();

    void on_btn_send_clicked();

    void on_btn_close_clicked();

private:
    Ui::serverWidget *ui;
    QTcpSocket *m_socket;  //用于通信
    QTcpServer *m_server;  //用于监听
};

.cpp

serverWidget::serverWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::serverWidget)
{
    ui->setupUi(this);
    m_server=NULL;
    m_socket=NULL;
    setWindowTitle("服务器");
    m_server = new QTcpServer(this);  //1、创建对象
     //有客户端连接会触发信号
    connect(m_server,&QTcpServer::newConnection,[=](){
        //3、取出用于通信的socket
        m_socket=m_server->nextPendingConnection();
        ui->textEdit_record->append("成功与服务器建立连接.....");
        //4、当有客户端发送消息会触发readyread信号
        connect(m_socket,&QTcpSocket::readyRead,[=](){
            //5、读客户端的信息
            QString rcvstr=m_socket->readAll();
            ui->textEdit_record->append("client say:"+rcvstr);
        });
          //7、客户端关闭连接
        connect(m_socket,&QTcpSocket::disconnected,[=](){
            ui->textEdit_record->append("client disconnected..");
            m_socket->deleteLater();

        });
    });


}

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


void serverWidget::on_btnstart_clicked()
{
    unsigned short port =ui->lineEdit_port->text().toInt();
    m_server->listen(QHostAddress::Any,port); //绑定地址结构监听端口
    ui->btnstart->setEnabled(false);
}

void serverWidget::on_btn_send_clicked()
{
    QString str = ui->textEdit_send->toPlainText();
     //6、向客户端发送消息
    m_socket->write(str.toUtf8());
    ui->textEdit_record->append("server say:"+str);
    ui->textEdit_send->clear();
}

//关闭服务器
void serverWidget::on_btn_close_clicked()
{
    if(NULL==m_socket)
    {
        return;
    }
    m_socket->disconnectFromHost();
    m_socket->close();
}

客户端窗口

 

 .h

class client : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_btn_connect_clicked();

    void on_btn_send_clicked();

    void on_btn_dis_clicked();

private:
    Ui::client *ui;
    QTcpSocket *m_socket;        //客户端没有QTcpServer
};

.cpp

client::client(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::client)
{
    ui->setupUi(this);
    setWindowTitle("客户端");
    m_socket=new QTcpSocket(this);
      //2、当客户端与服务器建立建立连接会触发connected信号
    connect(m_socket,&QTcpSocket::connected,[=](){
        ui->textEdit_record->append("成功与服务器连接!");

    });
        //4、读服务器消息
    connect(m_socket,&QTcpSocket::readyRead,[=](){
        QString str = m_socket->readAll();
        ui->textEdit_record->append("server say:"+str);

    });
    connect(m_socket,&QTcpSocket::disconnected,[=](){
        ui->textEdit_record->append("断开连接");
        ui->btn_connect->setEnabled(true);
        ui->btn_dis->setEnabled(false);
    });
}

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

void client::on_btn_connect_clicked()
{
    unsigned short port=ui->lineEdit_port->text().toInt();
    QString ip = ui->lineEdit_ip->text();
//1、客户端主动和服务器建立连接
    m_socket->connectToHost(QHostAddress(ip),port);
    ui->btn_connect->setEnabled(false);
    ui->btn_dis->setEnabled(true);
}

void client::on_btn_send_clicked()
{
    QString str = ui->textEdit_send->toPlainText();
      //3、给服务器发送消息
    m_socket->write(str.toUtf8());
    ui->textEdit_record->append("client says:"+str);
    ui->textEdit_send->clear();
}
//5、客户端主动断开连接
void client::on_btn_dis_clicked()
{
    m_socket->close();
    ui->btn_connect->setEnabled(true);
    ui->btn_dis->setEnabled(false);
}