The application of Qtcpserver, Qtcpsocket and Qudpsocket in the chat program

Source: Internet
Author: User
first, TCP/UDP communication programming in QT implementation method:


Similar to Linux's TCP/UDP communication interface (socket sockets), which is equivalent to a part of the linuxsocket socket merging and packaging, the specific graphical analysis is as follows:



1, detailed explanation QT TCP communication (Qtcpsocket, Qtcpserver):
For the above diagram to do some simple analysis:
Qtcpserver is used to create server objects, after server objects are created, call member function listen () for connection listening, where listen () contains the operation of binding IP and port, specific parameters prot the specified port, IP can be the following parameters:


Qhostaddress::null      //Null Address object
qhostaddress::localhost     //Listener Local host IPV4, equivalent to Qhostaddress ("127.0.0.1")
Qhostaddress::localhostipv6//Monitor Local host IPV6, equivalent to Qhostaddress (":: 1")
Qhostaddress::broadcast     //ipv4 broadcast address, Equivalent to Qhostaddress ("255.255.255.255")
Qhostaddress::anyipv4       //Monitor all IPV4 of current NIC, equivalent to Qhostaddress ("0.0.0.0")
Qhostaddress::anyipv6       //Monitor all IPV6 of current NIC, equivalent to Qhostaddress ("::")
qhostaddress::any       // Monitor all IP of the current network card


The server is blocking listening, and the client creates the TCP communication object with Qtcpsocket, uses the member function connecttohost () to initiate the connection operation, and after the server receives the connection request completes three handshake, the connection succeeds, The server's Qtcpserver class object triggers a newconnection () signal, which we handle, In its slot function, remove the object created by the server-side Tcpsocket for communication (with a nextpendingconnection () member to get the first socket in the listening queue to make the connection complete), note: The server has two objects at this time. Qtcpserver and Qtcpsocket objects, one used to monitor a communication. After the connection succeeds, the client also triggers a connected () signal that the connection succeeds. This allows for data transfer to begin.



The server's Qtcpsocket object and the client's Qtcpsocket object are exchanged for data, then the sender sends the data (write ()), The End-to-end Heartbeat Readyread (), and if the sending succeeds, the readyread () signal is triggered. At this point, we only need to implement the data read (read (), ReadAll (), etc.) in the slot function of the readyread () signal.



If one side wants to disconnect, you need to use the Disconnectfromhost () member of the Qtcpsocket class object, and for the Disconnectfromhost () member function, describe the following:


void Qabstractsocket::d isconnectfromhost () attempts to close the

socket. If there is pending data waiting to being written, Qabstractsocket'll enter closingstate and wait until all data has been W Ritten. Eventually, it'll enter unconnectedstate and emit the disconnected () signal.


The shutdown connection operation is an attempt to turn off the connection operation, and if the connection request is closed and the data is not finished, wait for all data to be written, then modify the socket state (Unconnectedstate disconnected state) After the final completion, and send a disconnected () The signal indicates that the connection has been disconnected. The status of the socket is enumerated as follows:


Qabstractsocket::unconnectedstate   //the socket is not connected
qabstractsocket::hostlookupstate    //the The socket is performing a host name lookup.
Qabstractsocket::connectingstate    //the socket has started establishing a connection.
Qabstractsocket::connectedstate     //a Connection is established
qabstractsocket::boundstate     //the socket are bound to a address and port
qabstractsocket::closingstate//the sockets are about to close       (data could still be W Aiting to be written).
Qabstractsocket::listeningstate     //for internal use only.


2, Qt UDP communication (qudpsocket):
UDP is much simpler than TCP, because the server does not need to monitor, it appears and the client is the same, only need to know the IP and port to be able to carry out data transmission, but it is not guaranteed to be able to complete the arrival of the message (this is a major difference between TCP and UDP: TCP will stick to the packet but will not And UDP will lose the packet will not stick to the package, (we will be in the test with the same code to test the client and server, because for a single thread/process is actually no difference). Secondly, TCP and UDP data form different, UDP data receive member function, naturally can not use TCP simple read, write (streaming data), but to use Readdatagram, Writedatagram. second, the code simple test:



Note:"QT + + Network" and "CONFIG + + c++11" need to be added to ". Pro" Engineering files.



1. TCP Point-to-Point Chat:
Server:


/*severwidget.h*/
#ifndef SERVERWIDGET_H
#define SERVERWIDGET_H

#include <QWidget>
#include <QTcpServer> //Monitor socket
#include <QTcpSocket> //Communication socket

namespace Ui {
class ServerWidget;
}

class ServerWidget: public QWidget
{
    Q_OBJECT

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

private slots:
    void on_buttonClose_clicked();
    void on_buttonSend_clicked();
private:
    Ui::ServerWidget *ui;
    QTcpServer * tcpServer; //Monitor socket object
    QTcpSocket * tcpSocket; //Communication socket object
};

#endif // SERVERWIDGET_H
/*serverwidget.cpp*/
#include "serverwidget.h"
#include "ui_serverwidget.h"

#define PORT_SERVER 8888

ServerWidget::ServerWidget(QWidget *parent):
    QWidget(parent),
    ui(new Ui::ServerWidget)
{
    ui->setupUi(this);
    tcpSocket = NULL;
    tcpServer = NULL;

    //Monitor socket
    setWindowTitle("Server:8888");
    tcpServer = new QTcpServer(this); //Specify the parent object, automatically reclaim space
    //Specify the bound IP (Any refers to all IPs of the current network card) and port
    tcpServer->listen(QHostAddress::Any, PORT_SERVER);

    //Get connection
    connect(tcpServer, &QTcpServer::newConnection,
            [=](){
                //Remove the socket that has established a connection for communication
                //Fetch the next (first) connection in the listening queue
                tcpSocket = tcpServer->nextPendingConnection();

                //Get the other party's IP: port
                QString ipCli = tcpSocket->peerAddress().toString();
                qint16 portCli = tcpSocket->peerPort();
                QString temp = QString("[%1:%2]:Connection successful").arg(ipCli).arg(portCli);
                ui->textRead->setText(temp); //Display connection information

                //Read the communication socket
                connect(tcpSocket, &QTcpSocket::readyRead,
                        [=](){
                            //Retrieve content from the communication socket
                            QByteArray array = tcpSocket->readAll();
                            ui->textRead->append(array);
                        }
                        );
                connect(tcpSocket, &QTcpSocket::disconnected,
                        [=](){ui->textRead->setText("Disconnected");});
            }
            );

}

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

void ServerWidget::on_buttonClose_clicked()
{
    //Actively disconnect from the client
    if(tcpSocket != NULL){
        ui->textRead->setText("Disconnected");
        tcpSocket->disconnectFromHost();
        tcpSocket->close();
        tcpSocket = NULL;
    }
}

void ServerWidget::on_buttonSend_clicked()
{
    //Get the editor content
    if(tcpSocket != NULL){
        QString str = ui->textWrite->toPlainText();
        //Send data to the other party
        tcpSocket->write(str.toUtf8().data());
    }
} 
 

The

client:
Header file is basically consistent with the server, with only a few "Qtcpserver * tcpserver" pointers.


/*clientwidget.cpp*/
#include "clientwidget.h"
#include "ui_clientwidget.h"
#include <QHostAddress>
#include <QByteArray>

ClientWidget::ClientWidget(QWidget *parent):
    QDialog(parent),
    ui(new Ui::ClientWidget)
{
    ui->setupUi(this);
    setWindowTitle("Client");
    tcpSocket = NULL;

    //Allocate space to specify the parent object
    tcpSocket = new QTcpSocket(this);

    connect(tcpSocket, QTcpSocket::connected,
            [=](){ui->textRead->setText("Established a connection with the server successfully");});
    connect(tcpSocket, QTcpSocket::readyRead,
            [=](){
                //Get the content sent by the other party
                QByteArray array = tcpSocket->readAll();
                //Append to the editing area
                ui->textRead->append(array);
            }
            );
    connect(tcpSocket, &QTcpSocket::disconnected,
            [=](){ui->textRead->setText("Disconnected");});
}

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

void ClientWidget::on_buttonConnect_clicked()
{
    QString ipSer = ui->lineEditIP->text();
    qint16 portSer = ui->lineEditPort->text().toInt();

    //Actively establish a connection with the server
    tcpSocket->connectToHost(QHostAddress(ipSer),portSer);
}

void ClientWidget::on_buttonSend_clicked()
{
    //Get the content of the edit box
    QString str = ui->textWrite->toPlainText();
    //send data
    tcpSocket->write(str.toUtf8().data());
}

void ClientWidget::on_buttonClose_clicked()
{
    //Actively disconnect from the other party
    ui->textRead->setText("Disconnected");
    tcpSocket->disconnectFromHost();
    tcpSocket->close();
}


Because in the same project, you need to create an object in main for both the server and the client and call Show ():



Test Results:



2, UDP point to point chat:
Server and Client generic:
The header file is also basically the same as TCP, Tcpsocket changed to Udpsocket.


#include "widget.h" #include "ui_widget.h" #include <QHostAddress> #include <QKeyEvent> #include <QEvent> #define BUFFER_SIZE 1024 Widget::Widget(QWidget *parent):     QWidget(parent),     ui(new Ui::Widget) {     ui->setupUi(this);     QString str = QString("<h2>Please bind the port first!</h2>");     ui->textEditRead->setText(str);     //socket initialization     udpSocket = NULL; } Widget::~Widget() {     delete ui; } void Widget::dealMessage() {     char buf[BUFFER_SIZE]={0};     QHostAddress cliAddr;     quint16 cliPort;     qint64 ret = udpSocket->readDatagram(buf, BUFFER_SIZE, &cliAddr, &cliPort);     if(ret> 0){         QString str = QString("[%1:%2]:%3")                 .arg(cliAddr.toString())                 .arg(cliPort)                 .arg(buf);         ui->textEditRead->append(str);     } } void Widget::on_buttonSend_clicked() {     if(udpSocket == NULL){         return;     }//Cannot send data before binding the port     QString peer_ip = ui->lineEditIP->text();     qint64 peer_port = ui->lineEditPeerPort->text().toInt();     QString str = ui->textEditWrite->toPlainText();     udpSocket->writeDatagram(str.toUtf8(),QHostAddress(peer_ip),peer_port);     ui->textEditWrite->clear(); } void Widget::on_buttonBindOwnPort_clicked() {     //Allocate space, specify the parent object     quint64 port = ui->lineEditOwnPort->text().toInt();     udpSocket = new QUdpSocket(this);     udpSocket->bind(port);     QString str = QString("<h3>The port is bound successfully!</h3>");     ui->textEditRead->setText(str);     setWindowTitle(QString("Port:%1").arg(port));     connect(udpSocket, &QUdpSocket::readyRead, this, &dealMessage); } void Widget::on_buttonClose_clicked() {     close(); }





Test Results:
After closing, we directly exit the interface window, instead of disconnecting and not exiting the program like TCP, because UDP does not need to disconnect (the connection is never established), and here is a simple optimization of the TCP GUI chat, sending each time After that, the editing window is cleared. It can be seen that after the port is bound (even before the port is bound) the concept of server and client is basically indistinguishable. Note: In the UI interface file, set the textEditRead property that displays the received content to read-only:


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.