原理仍是这张图
客户端主动连接服务器 客户端调用connecttohost函数 ,客户端如果连接成功会触发connected信号,连接成功后 可往服务器发送数据 write写入 发送成功对方的套接字在触发readyread信号
对该信号用信号和槽做处理来接受数据
服务器端监听客户端 如果有客户端连接 服务器端触发newconnection信号 ,此时可对建立好连接的通信套接字获取其中的内容 ,可往客户端发送数据 客户端发送数据过来 服务器端也会触发readyread信号 也可以对该信号做处理
客户端头文件
#ifndef CLIENTWIDGET_H
#define CLIENTWIDGET_H
#include <QWidget>
#include <QTcpSocket>
namespace Ui {
class ClientWidget;
}
class ClientWidget : public QWidget
{
Q_OBJECT
public:
explicit ClientWidget(QWidget *parent = nullptr);
~ClientWidget();
private slots:
void on_but_connect_clicked();
void on_send_clicked();
void on_close_disconnect_clicked();
private:
Ui::ClientWidget *ui;
QTcpSocket *csocket;
};
#endif // CLIENTWIDGET_H
客户端实现:
#include "clientwidget.h"
#include "ui_clientwidget.h"
#include <QHostAddress>
ClientWidget::ClientWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::ClientWidget)
{
ui->setupUi(this);
setWindowTitle("客户端");
csocket = NULL;
csocket = new QTcpSocket(this);
//csocket->connectToHost(QHostAddress::Any,8888);
//连接成功客户端触发 connected信号
connect(csocket,&QTcpSocket::connected,[=](){
ui->textEditread->setText("成功和服务建立连接");
});
//当发送数据成功 触发readyread信号
connect(csocket,&QTcpSocket::readyRead,[=](){
//读取里面的内容
//用字节数组接受
QByteArray arr = csocket->readAll();
//读取到的内容追加到编辑区中
ui->textEditread->append(arr);
});
}
ClientWidget::~ClientWidget()
{
delete ui;
}
void ClientWidget::on_but_connect_clicked()
{
//获取服务器和端口号
QString ip = ui->lineip->text();
quint64 port = ui->lineport->text().toInt();
//主动和服务器建立连接
csocket->connectToHost(QHostAddress(ip),port);
}
void ClientWidget::on_send_clicked()
{
//获取用户在编辑框的输入 发送到服务器
QString str = ui->textEditwrite->toPlainText();
csocket->write(str.toUtf8().data());
}
void ClientWidget::on_close_disconnect_clicked()
{
//主动和对方断开连接 和服务器断开连接
if(csocket==NULL)
{
return ;
}
csocket->disconnectFromHost(); //建立好连接的通信套接字 主动和服务器断开连接
csocket->close();
//断开后防止野指针
csocket =NULL;
}
服务器端头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_send_clicked();
void on_close_clicked();
private:
Ui::Widget *ui;
QTcpServer * server;
QTcpSocket * socket;
};
#endif // WIDGET_H
实现:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowTitle("服务器:8888");
//初始化server 和 socket
server = NULL;socket =NULL;
server = new QTcpServer(this);
server->listen(QHostAddress::Any,8888);
//当有人连接时发出 newConnection信号
connect(server,&QTcpServer::newConnection,[this](){
//取出对方的套接字
/*
从待处理的连接队列中取出下一个待处理的客户端连接
*/
socket = server->nextPendingConnection(); //取下一个连接
// QHostAddress peerAddress() 需要将网络地址转换为ipv4的地址
QString ip = socket->peerAddress().toString(); //将网络地址转换为字符串
quint16 port = socket->peerPort();
QString temp = QString("[%1:%2]成功连接").arg(ip).arg(port);
/*
QString::arg() 方法用于格式化字符串,将变量插入到占位符 %1 和 %2 的位置。
QString::arg() 方法允许你在字符串中使用占位符,并在运行时动态填充这些占位符。这是一种非常灵活的方式来构建带有变量的字符串。
*/
ui->read_->setText(temp);
connect(socket,&QTcpSocket::readyRead,[=](){
//从通信套接字取出内容
//读取所有的
//readall 返回值为字节数组
QByteArray array = socket->readAll();
//追加到 readedit中
ui->read_->append(array);
});
});
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_send_clicked()
{
if(socket==NULL)
{
return ;
}
QString str = ui->write_->toPlainText();//获取用户写入的内容
//write参数接受char * 型
//将string类型转换为 char*
socket->write(str.toUtf8().data());
}
void Widget::on_close_clicked()
{
if(socket==NULL)
{
return ;
}
socket->disconnectFromHost(); //建立好连接的通信套接字 主动和主机断开连接
socket->close();
//断开后防止野指针
socket =NULL;
}