客户端与服务端的TCP通信实现(Qt)

一:TCP通信介绍
.TCP是面向连接的可靠传输的协议,协议规定交换的双方必须是服务端和客户端的两个角色:
---   服务端负责监听网络端口,等待客户端的连接,用连接的socket完成信息的交互;
---   客户端负责每次连接的发起,建立连接后才可以进行通信;
.TCP的连接是基于流的,数据按照正确的顺序存储在接收缓冲区中,它保证数据能正确的进行交换,但不能保证数据以发送端的数据帧的形式提交。

 

 

二:界面设计

客户端

 

客户端与服务端的TCP通信实现(Qt)_第1张图片

 

服务端

 

客户端与服务端的TCP通信实现(Qt)_第2张图片

 

三:客户端编码
     
客户端编码步骤如下:
(1)创建QTcpSocket套接字对象

socket = new QTcpSocket();

 

(2)使用这个对象连接服务器

//连接服务器
socket->connectToHost(IP,port);

 

(3)使用write函数向服务器发送数据

//获取文本框的数据并以ASCII码发送出去
void MainWindow::on_pushButton_Send_clicked()
{
    socket->write(ui->textEdit_Send->toPlainText().toLatin1());
    socket->flush();
}

 

(4)当socket接收缓冲区有新数据到来时,会发出readyRead()信号,因此为该信号添加槽函数以读取数据。

//构造函数中连接
QObject::connect(socket,&QTcpSocket::readyRead,this,&MainWindow::socket_Read_Data);

void MainWindow::socket_Read_Data()
{
    QByteArray buffer;
    //读取数据缓冲区数据
    buffer = socket->readAll();

}

 

(5)断开与服务器的连接

//断开连接
socket->disconnectFromHost();

 


四:服务端编码
     服务端编码步骤如下:
(1)创建QTcpServer对象

server = new QTcpServer();

 

(2)侦听一个端口,使得客户端可以使用这个端口访问服务器

//监听指定的端口
if(!server->listen(QHostAddress::Any,port)){
   qDebug()<errorString();
}

 

(3)当服务器被访问时,会发出newConnection()信号,所以为该信号添加槽函数,并用一个QTcpSocket对象接受客户端的访问

//构造函数中连接
connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connection);
void MainWindow::server_New_Connection()
{
    //获取客户端的连接
    socket = server->nextPendingConnection();
}

 

(4)使用socket的write函数向客户端发送数据

//客户端有新连接是发送信号
QObject::connect(socket,&QTcpSocket::readyRead,this,&MainWindow::socket_Read_Data);
void MainWindow::socket_Read_Data()
{
    QByteArray buffer;
    //读取数据缓冲中的数据
    buffer = socket->readAll();
}

 

(5)当socket接受缓冲区有新数据到来时,会发出readyRead()信号,为该信号添加槽函数

//获取文本框数据并且以ASCII码的形式发送
void MainWindow::on_pushButton_Send_clicked()
{
    socket->write(ui->textEdit_Send->toPlainText().toLatin1());
    socket->flush();
}

 

(6)取消侦听

server->close();

 

 

五:修改*.pro文件

在文件中添加网络应用的代码库network

QT       += core gui network

 

 

六:中文乱码处理

上述发送接收的代码都是单字节数据,对于发送中文数据,在发送和接收是需要做如下处理:

发送数据:

void MainWindow::on_pushButton_Send_clicked()
{
    qDebug()<<"Send: "<textEdit_Send->toPlainText();
    //兼容中文数据发送
    socket->write(ui->textEdit_Send->toPlainText().toLocal8Bit());
    socket->flush();
    //获取文本框数据并且以ASCII码的形式发送
    //socket->write(ui->textEdit_Send->toPlainText().toLatin1());
    //socket->flush();
}socket->write(ui->textEdit_Send->toPlainText().toLocal8Bit());
    socket->flush();
    //获取文本框数据并且以ASCII码的形式发送
    //socket->write(ui->textEdit_Send->toPlainText().toLatin1());
    //socket->flush();
}

接收数据:

void MainWindow::socket_Read_Data()
{
    QByteArray buffer;
    //读取数据缓冲区数据
    buffer = socket->readAll();
    if(!buffer.isEmpty()){
        QString str = ui->textEdit_Recv->toPlainText();
        QString strRecv = QString::fromLocal8Bit(buffer);
        str+=strRecv+"\n";
        //刷新显示
        ui->textEdit_Recv->setText(str);
    }
}QString strRecv = QString::fromLocal8Bit(buffer);
        str+=strRecv+"\n";
        //刷新显示
        ui->textEdit_Recv->setText(str);
    }
}


七:细节注意

     (1)Qt5 抛弃了QTextCodec::setCodecForTr()和QTextCodec::setCodecForCString()这两个函数。

直接将 QTextCodec::setCodecForLocale(QTextCodec::codecForName(“UTF8”)) 至于QApplication实例之前即可解决;

     (2)本示例中,newConnection信号是对于单线程适用的,nextPendingConnection()只能用于当前线程中,当服务端面向多连接服务时,需要重载incomingConnection()方法,用socket描述符socketDescriptor定义连接socket

 

代码连接地址:https://pan.baidu.com/s/1eSELrnO    提取码:2ym3

 

 

       欢迎进群,一起探讨NB的代码

 

你可能感兴趣的:(QT,C++,TCP通信,Protocol,Buffer)