今天需要做一个服务器端的tcp通信
因为之前没有用过qt的方法,只用过C语言版本的,所以干脆客户端和服务器端都查了下,做个笔记。
先上代码
客户端.h
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTcpSocket>
#include <QHostAddress>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_Connect_clicked();
void on_pushButton_Send_clicked();
void socket_Read_Data();
void socket_Disconnected();
private:
Ui::MainWindow *ui;
QTcpSocket *socket;
};
#endif // MAINWINDOW_H
客户端.cpp
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
socket = new QTcpSocket();
//连接信号槽
QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);
ui->pushButton_Send->setEnabled(false);
ui->lineEdit_IP->setText("192.168.0.109");
ui->lineEdit_Port->setText("8088");
}
MainWindow::~MainWindow()
{
delete this->socket;
delete ui;
}
void MainWindow::on_pushButton_Connect_clicked()
{
if(ui->pushButton_Connect->text() == tr("connect"))
{
int port;
//获取端口号
port = ui->lineEdit_Port->text().toInt();
//取消已有的连接
socket->abort();
//连接服务器
socket->connectToHost(ui->lineEdit_IP->text(), port);
//等待连接成功
if(!socket->waitForConnected(30000))
{
qDebug() << "Connection failed!";
return;
}
qDebug() << "Connect successfully!";
//发送按键使能
ui->pushButton_Send->setEnabled(true);
//修改按键文字
ui->pushButton_Connect->setText("断开连接");
}
else
{
//断开连接
socket->disconnectFromHost();
//修改按键文字
ui->pushButton_Connect->setText("连接");
ui->pushButton_Send->setEnabled(false);
}
}
void MainWindow::on_pushButton_Send_clicked()
{
qDebug() << "Send: " << ui->textEdit_Send->toPlainText();
//获取文本框内容并以ASCII码形式发送
socket->write(ui->textEdit_Send->toPlainText().toLocal8Bit());
socket->flush();
}
void MainWindow::socket_Read_Data()
{
//读取缓冲区数据
QByteArray buffer = socket->readAll();
if(!buffer.isEmpty())
{
QString str = ui->textEdit_Recv->toPlainText().fromLocal8Bit(buffer);
qDebug() << "recv data = " << str;
//刷新显示
ui->textEdit_Recv->setText(str);
}
}
void MainWindow::socket_Disconnected()
{
//发送按键失能
ui->pushButton_Send->setEnabled(false);
//修改按键文字
ui->pushButton_Connect->setText("连接");
qDebug() << "Disconnected!";
}
服务端.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui { class TcpServer; }
QT_END_NAMESPACE
class TcpServer : public QWidget
{
Q_OBJECT
public:
TcpServer(QWidget *parent = nullptr);
~TcpServer();
void setHostAddress(QString address){m_hostAddress=address;}
void setTcpServerPort(int port){m_tcpServerPort=port;}
protected slots:
void server_New_Connect();
void socket_Read_Data();
void socket_Disconnected();
private slots:
void on_writeBtn_clicked();
void on_setListen_clicked();
void on_setAdd_clicked();
void on_setPort_clicked();
private:
Ui::TcpServer *ui;
QTcpServer* mServer;
QTcpSocket* mSocket;
QString m_hostAddress = "192.168.0.100";//"192.168.0.109";
int m_tcpServerPort = 8000;//8080;
};
#endif // TCPSERVER_H
服务端.cpp
#include "tcpserver.h"
#include "ui_tcpserver.h"
TcpServer::TcpServer(QWidget *parent)
: QWidget(parent)
, ui(new Ui::TcpServer)
{
ui->setupUi(this);
//1.创建一个tcpServer对象
mServer = new QTcpServer(this);
mSocket= new QTcpSocket;
//2.监听一个端口,使得客户端可以使用这个端口访问服务器
// mServer->listen(QHostAddress::Any, 8080);
//3.链接信号槽
connect(mServer,&QTcpServer::newConnection,this,&TcpServer::server_New_Connect);
}
TcpServer::~TcpServer()
{
delete ui;
}
void TcpServer::server_New_Connect()
{
//获取客户端连接
mSocket = mServer->nextPendingConnection();
qDebug() << "A Client connect!";
//连接QTcpSocket的信号槽,以读取新数据
QObject::connect(mSocket, &QTcpSocket::readyRead, this, &TcpServer::socket_Read_Data);
QObject::connect(mSocket, &QTcpSocket::disconnected, this, &TcpServer::socket_Disconnected);
}
void TcpServer::socket_Read_Data()
{
//读取缓冲区数据
QByteArray buffer = mSocket->readAll();
if(!buffer.isEmpty())
{
ui->recvData->clear();
ui->recvData->setText(QString::fromLocal8Bit(buffer));
}
}
void TcpServer::socket_Disconnected()
{
//发送按键失能
qDebug() << "Disconnected!";
}
void TcpServer::on_writeBtn_clicked()
{
QString buf = "hello tcp " + ui->recvData->toPlainText();
// char *buffer = buf.toLatin1().data();
mSocket->write(buf.toLocal8Bit());
// qDebug() << "server wirte buffer = " << buffer;
mSocket->flush();
}
void TcpServer::on_setListen_clicked()
{
qDebug() << "start to listen";
mServer->listen(QHostAddress::Any, 8088);
}
void TcpServer::on_setAdd_clicked()
{
setHostAddress("192.168.0.109");
qDebug() << "set host address: " << "192.168.0.109";
}
void TcpServer::on_setPort_clicked()
{
setTcpServerPort(8088);
qDebug() << "set host port: " << 8088;
}
因为只是做个demo,不需要太过细节,所以服务端返回的数据就是在收到客户端数据的基础上加了hello tcp;
这个demo只能做一个简单的小框架。
qt的封装,利用信号和槽使tcp通讯十分方便
客户端
- socket = new QTcpSocket();//申请socket对象
- socket->connectToHost(ip, port);//链接已经在监听的服务器ip和端口
- socket->write();//对已经socket写入数据
- QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);//如果服务器端发送过来数据,就会触发readyRead这个信号,我们在客户端只需要完成他的槽函数里面的操作即可,发送接收数据要注意数据格式,防止中文出现乱码
服务器
1.需要同时用到QTcpServer类和QTcpSocket mServer = new QTcpServer; mSocket= new QTcpSocket; 2.监听一个端口,使得客户端可以使用这个端口访问服务器mServer->listen(QHostAddress::Any, 8080);3.链接信号槽 connect(mServer,&QTcpServer::newConnection,this,&TcpServer::server_New_Connect);
当有用户链接进来,就会触发newConnection信号,我们只需要实现槽函数
4. mSocket = mServer->nextPendingConnection();//获取客户端连接
//连接QTcpSocket的信号槽,以读取新数据
QObject::connect(mSocket, &QTcpSocket::readyRead, this, &TcpServer::socket_Read_Data);QObject::connect(mSocket, &QTcpSocket::disconnected, this, &TcpServer::socket_Disconnected);5.read和write数据 和客户端一样
记录下吧,后面用到udp的时候,再写精致点
ps: 链接时不能开翻墙软件,否则链接失败