[QT] Detailed explanation and implementation of TCP/UDP

TCP/IP model

The TCP model is a common network protocol reference model, also known as the TCP/IP model or the Internet model. It refers to a set of protocols in the TCP/IP protocol suite for data communication in computer networks. The TCP model consists of four levels, namely:

  1. Application Layer:

    The application layer is the layer closest to the user, providing users with various network application services.
    Including common application layer protocols, such as HTTP, FTP, SMTP, DNS, etc.
    This layer defines communication rules and data formats between applications.

  2. Transport Layer:

    The transport layer is responsible for providing reliable end-to-end communication and data transfer services.
    The most commonly used transport layer protocols are TCP and UDP.
    TCP provides reliable, connection-oriented communication services to ensure data reliability, order and flow control.
    UDP is a connectionless transmission protocol that provides simple, unreliable data transmission services.

  3. Network Layer:

    The network layer is responsible for transferring data from source hosts to destination hosts, handling path selection and packet forwarding between hosts.
    The most commonly used network layer protocol is IP (Internet Protocol).
    The IP protocol defines the addressing and routing mechanism of data in the network, and divides the data into data packets for transmission.

  4. Link Layer:

    The link layer is the lowest layer, responsible for the actual physical link transmission and network adaptation.
    Including different link layer protocols such as Ethernet, Wi-Fi, and PPP.
    The link layer encapsulates data packets into frames and transmits them through the physical medium.
    The TCP model is a layered structure, each layer has specific functions and responsibilities, and communicates through different layers of protocols. It provides a standardized network communication framework, enabling different computers and network devices to communicate and exchange data with each other. The TCP/IP model is widely used in the Internet and many local area networks, and has become the basis of modern computer networks.

TCP protocol

header format

insert image description here

  1. Serial number: The random number generated by the computer is used as the initial value when the connection is established, and is sent to the receiving host through the SYN packet. Every time data is sent, the size of the "number of data bytes" is "accumulated". It is used to solve the problem of out-of-order network packets.
  2. Confirmation response number: refers to the serial number of the data that is "expected" to be received next time. After receiving this confirmation response, the sender can consider that the data before this serial number has been received normally. Used to solve the problem of packet loss.
  3. ACK: When this bit is 1, the field of "acknowledgment response" becomes valid, and TCP stipulates that this bit must be set to 1 except for the SYN packet when the connection is initially established.
  4. RST: When this bit is 1, it means that an exception occurs in the TCP connection and the connection must be forcibly disconnected.
  5. SYN: When this bit is 1, it means to establish a connection, and set the initial value of the serial number in the "serial number" field.
  6. FIN: When this bit is 1, it means that there will be no more data to be sent in the future and the connection is expected to be disconnected. When the communication ends and the connection is desired to be disconnected, the hosts on both sides of the communication can exchange TCP segments with the FIN bit set to 1.

three handshake

  1. First handshake (SYN):

    The client sends a SYN (synchronization) packet to the server, indicating that the client requests to establish a connection, and specifying the initial sequence number.
    The client sets the Sequence Number of the SYN packet to a random number, which is used to identify the sequence number of the subsequent data transmission.

Verify the sending capability of the client and the receiving capability of the server

  1. The second handshake (SYN-ACK):

    After receiving the SYN packet from the client, the server sends a SYN-ACK (synchronization-confirmation) packet to the client as a response.
    The server sets its own Sequence Number as a random number, which is used for sequence number identification of subsequent data transmission.
    At the same time, the server sets the ACK flag and the confirmation sequence number to the client's initial sequence number plus 1, and puts its own initial sequence number into the ACK packet, indicating that the server accepts the client's connection request.

Verify the sending ability of the server and the receiving ability of the client

  1. The third handshake (ACK):

    After receiving the SYN-ACK packet from the server, the client sends an ACK (confirmation) packet to the server to confirm the connection request.
    The client sets its own Sequence Number to the server's initial sequence number plus 1, and sets the ACK flag and confirmation sequence number to the server's initial sequence number plus 1, indicating that the client confirms the server's connection response.

Verify the sending and receiving capabilities of the client and server
insert image description here

Section: Through this three-way handshake, both the client and the server can confirm each other's communication capabilities and establish a reliable two-way connection. Each handshake process includes the exchange of sequence numbers and confirmation sequence numbers to ensure reliable data transmission. At the same time, the three-way handshake can also prevent incorrect connection establishment caused by old connection requests staying in the network.

waved four times

TCP's four-way wave is a wave process used when closing a TCP connection to ensure that both parties complete the data transmission and close the connection safely. The following is the detailed process of TCP four-way wave:

  1. First Wave (FIN):

    The client sends a FIN (end) packet to the server, indicating that the client has no more data to send.
    The client enters the FIN_WAIT_1 state, waiting for the server's confirmation.

  2. Second wave (ACK):

    After receiving the client's FIN packet, the server sends an ACK (confirmation) packet to the client as a response.
    The server enters the CLOSE_WAIT state, indicating that the data transmission from the client to the server has been closed.

  3. Third wave (FIN):

    After the server finishes processing the data , the server sends a FIN packet to the client, indicating that the server has no more data to send.
    The server enters the LAST_ACK state and waits for the client's confirmation.

  4. Fourth wave (ACK):

    After receiving the FIN packet from the server, the client sends an ACK packet to the server as confirmation.
    The client enters the TIME_WAIT state, waiting for a period of time to ensure that the server has received the acknowledgment, and to allow time long enough to process late data that may arrive.
    After receiving the confirmation from the client, the server closes the connection and enters the CLOSED state.
    After the client waits for a period of time, it closes the connection and enters the CLOSED state.
    insert image description here
    Subsection: Through these four waved hands, the two parties confirm that they will no longer send data to each other and complete the closing process of the connection. This ensures that both parties have sufficient time to process unprocessed data and avoid data loss or interruption. During the four hand waves, each hand wave includes the exchange of sequence numbers and confirmation sequence numbers to ensure reliable transmission of data and correct closing of connections.

UDP protocol

Compared with the TCP protocol, UDP data transmission is based on non-connection. UDP data transmission is to simply encapsulate the data and then send it out through the network card. There is no state link between data packets.

header format

insert image description here

  1. Destination and source ports: mainly to tell the UDP protocol which process the message should be sent to.
  2. Packet length: This field stores the sum of the length of the UDP header and the length of the data.
  3. Checksum: Checksum is designed to provide reliable UDP headers and data, preventing UDP packets from being damaged during network transmission.

Socket programming

tcp

  1. Create a socket (Socket):

    Both the client and the server need to create a socket object for establishing a TCP connection.
    In C/C++, you can use the socket() function to create a socket object, and specify the protocol family (such as AF_INET) and socket type (such as SOCK_STREAM).

  2. Bind address and port (server side):

    On the server side, the socket needs to be bound to a specific IP address and port in order to listen to the client's connection request.
    A socket can be bound with an address and port using the bind() function.

  3. Listen for connection requests (server side):

    On the server side, you need to start listening for connection requests from clients.
    You can use the listen() function to set the socket to the listening state and specify the maximum number of connections (backlog).

  4. Initiate connection (client):

    On the client side, a connection needs to be established with the server.
    A socket can be connected to the server's address and port using the connect() function.

  5. Accept connection (server side):

    When the server receives the connection request from the client, it needs to accept the connection.
    You can use the accept() function to accept the client's connection request and return a new socket object for communicating with the client.

  6. data transmission:

    Once the connection is established, the client and server can transmit data through the socket.
    On the client side, you can use the send() function to send data to the server side.
    On the server side, you can use the recv() function to receive data sent by the client.

  7. Close the connection:

    When the data transfer is complete or the connection is no longer needed, the connection needs to be closed.
    On both the client and server side, a socket can be closed using the close() or closesocket() functions.

udp

  1. Create a socket (Socket):

    Both the client and the server need to create a UDP socket object for UDP communication.
    In C/C++, you can use the socket() function to create a socket object, and specify the protocol family (such as AF_INET) and socket type (such as SOCK_DGRAM).

  2. Bind address and port (server side):

    On the server side, the socket needs to be bound to a specific IP address and port in order to listen to the client's connection request.
    A socket can be bound with an address and port using the bind() function.

  3. Send data (client):

    On the client side, you can use the sendto() function to send packets to the server.
    You need to specify the IP address and port of the server, as well as the data to be sent.

  4. Receive data (server side):

    On the server side, you can use the recvfrom() function to receive data packets sent by the client.
    You can use this function to get the IP address and port of the client, as well as the received data.

  5. Data processing:

    After the data is received, it can be processed and parsed.
    According to application requirements, operations such as parsing, verification, and processing can be performed on the data.

  6. Send response (server side):

    On the server side, you can use the sendto() function to send a response packet to the client.
    You need to specify the IP address and port of the client, and the response data to be sent.

  7. Close the socket:

    The socket needs to be closed when the UDP communication is done or is no longer needed.
    A socket can be closed using the close() or closesocket() functions.

Code

The experiment consists of a client program and a server program, using QT to achieve connection and communication. The running interface is as follows:
insert image description here

Server:

server.h:

#ifndef SERVER_H
#define SERVER_H

#include <QMainWindow>
#include<QTcpServer>
#include<QTcpSocket>
#include<QUdpSocket>

QT_BEGIN_NAMESPACE
namespace Ui {
    
     class server; }
QT_END_NAMESPACE

class server : public QMainWindow
{
    
    
    Q_OBJECT

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

private slots:
    void on_pushButton_listen_clicked();

    void server_new_connect();

    void socket_read_data();

    void read_data();



private:
    Ui::server *ui;
    QUdpSocket *uServer;
    QTcpServer *mServer;
    QTcpSocket *mSocket;
    int i1,i2;
    int j1,j2;
};
#endif // SERVER_H

server.cpp

#include "server.h"
#include "ui_server.h"
#include<qdebug.h>

server::server(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::server)
{
    
    
    ui->setupUi(this);
    ui->portEdit->setText("8080");

    mServer=new QTcpServer;

    connect(mServer,&QTcpServer::newConnection,this,&server::server::server_new_connect);

    uServer=new QUdpSocket;
    uServer->bind(QHostAddress("192.168.1.107"),8080);
    QObject::connect(uServer,&QUdpSocket::readyRead,this,&server::read_data);
}

void server::read_data()
{
    
    
    qDebug()<<"recv_UDP";
    if(ui->radioButton_UDP->isChecked())
    {
    
    
        qDebug()<<"recv_UDP";

        QByteArray arr;//创建QByteArray对象存储缓冲区数据
        arr.resize(uServer->bytesAvailable());//设置字符串大小
        uServer->readDatagram(arr.data(),arr.size());//读取缓冲区数据
        qDebug()<<uServer->readDatagram(arr.data(),arr.size());

        QString str ;//创建QString对象用于进行缓冲数据的处理
        str.prepend(arr);//QByteArray转QString
        qDebug()<<"str="<<str;
        ui->textEdit->setText("udp:"+str);
    }
}

server::~server()
{
    
    
    uServer->close();
    uServer->deleteLater();
    mServer->close();
    mServer->deleteLater();
    delete ui;
}

void server::on_pushButton_listen_clicked()
{
    
    
    if(ui->pushButton_listen->text() == QString::fromLocal8Bit("侦听"))
    {
    
    
        int port = ui->portEdit->text().toInt();
        if(!mServer->listen(QHostAddress("192.168.1.107"),port))//判断侦听本机端口和地址是否成功
        {
    
    
            ui->portEdit_state->setText(QString::fromLocal8Bit("侦听失败!"));//侦听失败
            qDebug()<<mServer->errorString();
            return;
        }
        ui->pushButton_listen->setText(QString::fromLocal8Bit("取消侦听"));//改变按键功能
        ui->portEdit_state->setText(QString::fromLocal8Bit("侦听成功!"));//侦听成功
        qDebug()<<"Listen successful!";
    }
    else//侦听失败
    {
    
    
        mSocket->abort();//销毁TCP套接字对象
        mServer->close();
        ui->portEdit_state->setText(QString::fromLocal8Bit("侦听失败!"));//返回侦听失败
        ui->pushButton_listen->setText(QString::fromLocal8Bit("侦听"));//改变按键功能

    }
}

void server::server_new_connect()
{
    
    
    mSocket = mServer->nextPendingConnection();
    QObject::connect(mSocket,&QTcpSocket::readyRead,this,&server::socket_read_data);//连接函数槽
    ui->portEdit_state->setText(QString::fromLocal8Bit("连接成功!"));
    qDebug()<<"A client connect!";
}

void server::socket_read_data()
{
    
    
    if(ui->radioButton_TCP->isChecked())
    {
    
    
        QString str= mSocket->readAll();
        qDebug()<<str;
        qDebug()<<"recv_TCP";
        ui->textEdit->setText("tcp:"+str);

    }

}
client:

client.h

#ifndef CLIENT_H
#define CLIENT_H

#include <QMainWindow>
#include<QTcpServer>
#include<QTcpSocket>
#include<QHostAddress>
#include<QFile>
#include<QTimer>
#include<QMessageBox>
#include<QUdpSocket>

QT_BEGIN_NAMESPACE
namespace Ui {
    
     class client; }
QT_END_NAMESPACE

class client : public QMainWindow
{
    
    
    Q_OBJECT

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


private slots:
    void socket_disconnected();
    void on_pushButtonconnect_clicked();
    void on_pushButton_send_clicked();


private:
    Ui::client *ui;
    QTcpSocket *mSocket;
    QUdpSocket *uSocket;
    QTimer *tim;
};
#endif // CLIENT_H

client.cpp

#include "client.h"
#include "ui_client.h"
#include<qdebug.h>

client::client(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::client)
{
    
    
    ui->setupUi(this);
    ui->ipEdit->setText("192.168.1.107");//默认显示ip为192.168.1.44
    ui->portEdit->setText("8080");//默认显示端口为8080
    mSocket = new QTcpSocket();//TCP套接字初始化
    ui->pushButton_send->setEnabled(true);
    //QObject::connect(mSocket,&QTcpSocket::readyRead,this,&client::on_pushButton_send_clicked);
    QObject::connect(mSocket,&QTcpSocket::disconnected,this,&client::socket_disconnected);
    uSocket = new QUdpSocket(this);//UDP套接字初始化

    tim = new QTimer();//初始化计时器对象
    tim->setInterval(1000);//设置计时器间隔时间为1s

    connect(tim,SIGNAL(timeout()),this,SLOT(onTimeOut()));//连接信号槽
    tim->start();//初始化计时器状态


}

client::~client()
{
    
    
    delete this->uSocket;
    delete this->mSocket;
    delete ui;
}

/*TCP连接*/
void client::on_pushButtonconnect_clicked()
{
    
    
    if(ui->pushButtonconnect->text() == QString::fromLocal8Bit("连接"))
        {
    
    
            QString IP;
            int port;
            IP = ui->ipEdit->text(); //获取IP地址
            port = ui->portEdit->text().toInt(); //获取端口号
            mSocket->abort();//取消已有的连接
            mSocket->connectToHost(IP, port);//连接服务器
            if(!mSocket->waitForConnected(3000))//等待连接成功
            {
    
    
                qDebug() << "Connection failed!";
                ui->lineEdit_state->setText(QString::fromLocal8Bit("连接失败!"));
                return;
            }
            qDebug() << "Connect successfully!";
            ui->lineEdit_state->setText(QString::fromLocal8Bit("连接成功!"));
            ui->pushButton_send->setEnabled(true);//发送按键使能
            ui->pushButtonconnect->setText(QString::fromLocal8Bit("断开连接"));//修改按键文字
        }
        else
        {
    
    
            mSocket->disconnectFromHost();//断开连接
            ui->pushButtonconnect->setText(QString::fromLocal8Bit("连接"));//修改按键文字
            ui->pushButton_send->setEnabled(true);//发送按键使能
        }
}

/*发送数据*/
void client::on_pushButton_send_clicked()
{
    
    
    qDebug()<<"Send: "<<ui->textEdit_enter->toPlainText().toLatin1();

    if(ui->radioButton_TCP->isChecked())//判断使用TCP协议
    {
    
    
        qDebug()<<"TCP";
        mSocket->write(ui->textEdit_enter->toPlainText().toLatin1());//tcp协议下客户端发送框内容写入缓冲
        mSocket->flush();
    }
    else if(ui->radioButton_UDP->isChecked())//判断使用UDP协议
    {
    
    
        qDebug()<<"UDP";
        uSocket->writeDatagram(ui->textEdit_enter->toPlainText().toLatin1(),QHostAddress("192.168.1.107"),8080);//udp协议下客户端发送框内容写入缓冲
        uSocket->flush();
    }
    else
    {
    
    
        ui->lineEdit_state->setText("choose TCP or UDP ");//未选择协议
    }
}

/*断开连接*/
void client::socket_disconnected()
{
    
    
    ui->pushButton_send->setEnabled(false);//关闭发送按键
    ui->pushButtonconnect->setText(QString::fromLocal8Bit("连接"));//显示
    qDebug()<<"Disconnected!";
}

Summarize

TCP (Transmission Control Protocol) and UDP (User Datagram Protocol) are two commonly used transport layer protocols for transmitting data in computer networks. They have different characteristics and applicable scenarios. The following is a summary of TCP and UDP:
TCP

  • TCP is a connection-oriented protocol that provides reliable data transmission and error detection mechanisms.
  • TCP uses a three-way handshake to establish a connection to ensure the reliability and order of data.
  • TCP provides streaming, divides data into TCP segments, and ensures the correctness and integrity of data through sequence numbers and confirmation responses.
  • TCP has a congestion control mechanism that can dynamically adjust the transmission rate according to network conditions to avoid network congestion.
  • TCP is suitable for applications that require reliable transmission, such as file transfer, email, web browsing, etc.

UDP

  • UDP is a connectionless protocol that provides low-latency and high-efficiency data transmission.
  • UDP does not establish a connection, but directly sends data packets, and does not guarantee the reliability and order of data.
  • UDP is a stateless protocol that does not maintain connection state information, and each data packet is independent.
  • UDP is suitable for applications with high real-time requirements, such as real-time audio and video transmission, online games, etc.
  • Compared with TCP, UDP has smaller overhead and faster transmission speed, but does not provide congestion control and retransmission mechanism.
  • Since UDP does not guarantee data reliability, applications need to deal with data loss, duplication, and order issues by themselves.

Choosing to use TCP or UDP depends on the needs and characteristics of the application. If the application requires reliable transmission, ordering, and congestion control, TCP should be chosen. And if the application has high real-time requirements, can tolerate some data loss or disordered order, and requires low latency, then UDP is more suitable.

Guess you like

Origin blog.csdn.net/qq_44878985/article/details/131075119