添加network
QT += core gui network
二 .h头文件中的定义
private slots:
void on_pushButton_clicked();
void on_pushButton_4_clicked();
void on_pushButton_5_clicked();
//客户端读取发送端发来的数据的槽函数
void cread_data();
void on_pushButton_2_clicked();
//客户端点击 连接服务器,连接上会触发服务器发出newConnection的信号,进入receive_clien函数中
void receive_client();
//服务器读取客户端发来的数据的槽函数
void sread_data();
void on_pushButton_3_clicked();
void on_pushButton_6_clicked();
private:
Ui::MainWindow *ui;
//客户端的套接字
QTcpSocket csocket;
//声明一个QTcpserver的对象,用于监听
QTcpServer sserver;
//创建服务器的套接字,用于与客户端进行通信
QTcpSocket *ssocket;
QTcpSocket *ssocket;服务器的套接字,用于与客户端进行通信。由于这个套接字是在服务器的receive-client这个槽函数中函数中获取的,又要在服务端的发送函数中使用,所以要变成全局变量。
服务端点击启动服务器,服务器就开始监听
//启动服务器
void MainWindow::on_pushButton_2_clicked()
{
//监听----------启动服务器
//QHostAddress::Any 地址,接纳所有的地址
//端口号 ui->sportEdit->text()获得输入的字符串,转换成无符号短整型
sserver.listen(QHostAddress::Any,ui->sportEdit->text().toUShort());
}
当服务器发现有人要来连接时,就会发出newconnection 的信号,从而触发槽函数receive_client(自行编写的槽函数)
在MainWindow::MainWindow(QWidget *parent) :
里面添加connect关联函数
//客户端点击 连接服务器,连接上会触发服务器发出newConnection的信号,server进入new_client函数中
//动作的发出者&sserver 服务器,发出的信号是newConnection
//&QTcpServer中的这个函数newConnection会发出一个信号 动作的发出者是mserver服务器
connect(&sserver,&QTcpServer::newConnection,this,&MainWindow::receive_client);
receive_client(自行编写的槽函数)
//建立接收客户端连接的槽函数,有人连接就触发这个槽函数
void MainWindow::receive_client()
{
//获取这个服务器sserver与客户端通信的套接字
ssocket=sserver.nextPendingConnection();
//拿到套接字后,服务器可利用ssocket这个套接字中的write(),间接的向客户端发送数据,
ssocket->write("connect");
//客户端如有写入,就会触发readyread这个信号
//关联一下客户端的写入信号,本来就是指针,不用取地址
//写在这里是确保客户端连接了服务器
//信号的发出者是ssocket 服务器与客户端之间通信的套接字
//当有东西写入的时候,就会发出readyread的信号
connect(ssocket,&QTcpSocket::readyRead,this,&MainWindow::sread_data);
}
想了很久,参考了其他的博客
我是这么理解的
在sserver这个服务器的进程汇总,调用nextPendingConnection()这个函数,获得了一个QtcpSocket类型的指针,就是服务端的套接字,用来和客户端通信的,所以在后面的内容中,直接向ssocket里面写入内容,客户端就可以收到。但是返回的这个QtcpSocket类型的指针不可以用于另一个线程。
在接收到新客户的这个函数中,再定义一个connect,是确保客户端连接了服务器,信号的发出者是ssocket,发出的信号是准备读readyRead,触发服务器去执行sread_data这个槽函数。
//槽函数
//服务器读取客户端csocket发来的数据的槽函数,然后显示在服务器端的stextBrowser中
void MainWindow::sread_data()
{
// //获得信号的发送者的套接字
// //sender()用于服务器获取客户端在发送内容的时候的套接字,其实获取到的内容就是sscoket
// //dynamic_cast 将sender获得的内容强制转换成QTcpSocket*
// QTcpSocket *msocket = dynamic_cast(sender());
// //读取数据
// QString msg = msocket->readAll();
// //还可以读取对方的ip
// QString ip = msocket->peerAddress().toString();
// //去掉前面的#ffff
// ip.remove("::ffff:");
QString msg = ssocket->readAll();
QString ip = ssocket->peerAddress().toString();
//调用文本浏览框,显示内容
ui->stextBrowser->append(ip+":"+msg);
}
服务器读取客户发来的信息的时候,也是要先获取发送者的套接字QTcpSocket *msocket = dynamic_cast
赋值给msock,这个临时创建的套接字,然后从这个临时创建的套接字中读取信息,还可以读取ip
sender()函数,返回的是信号来源的对象,返回的就是,是谁进入了发出的信号,进入的这个槽函数。
//服务器端的 发送按钮 向客户端csocket写入数据
void MainWindow::on_pushButton_3_clicked()
{
//获取数据 toPlainText()这个组件转字符串
QString data = ui->stextEdit->toPlainText();
ssocket->write(data.toUtf8());
}
由于ssocket是全局变量,所以上面在第三步中给它赋值了,这里就可以直接用了,直对它写入数据即可。
//服务器端的清空按钮
void MainWindow::on_pushButton_6_clicked()
{
//清空一下textedit
ui->stextEdit->clear();
}
//client端的连接服务器按钮
void MainWindow::on_pushButton_clicked()
{
// 根据输入的ip和port连接指定的服务器
csocket.connectToHost(ui->cipEdit->text(),ui->cportEdit->text().toUShort());
qDebug()<<"客户端连接服务器";
}
//client端 发送按钮
void MainWindow::on_pushButton_4_clicked()
{
//获取数据 toPlainText()这个组件转字符串
QString data = ui->ctextEdit->toPlainText();
//向服务器发送数据, 转成字符数组
csocket.write(data.toUtf8());
}
//client端 清空按钮
void MainWindow::on_pushButton_5_clicked()
{
//清空一下textedit
ui->ctextEdit->clear();
}
首先在MainWindow::MainWindow(QWidget *parent) :
中建立connect连接
//关联一下信号 作用是读取服务端发来的数据
//当客户端发现有数据要进来的时候,就会发出readyread这个信号,触发读取并显示数据的槽函数
connect(&csocket,&QTcpSocket::readyRead,this,&MainWindow::cread_data);
槽函数
//client端的接收服务器发来的数据的槽函数
void MainWindow::cread_data()
{
//通过套接字读取,保存服务器发过来的数据
QString msg = csocket.readAll();
//把数据放到文本浏览框中显示
ui->ctextBrowser->append(msg);
}
客户端和服务端一边一个套接字,服务器端还要加一个服务端的对象用于监听
客户端的套接字csocket(是一个变量)可以直接使用,但是服务端的套接字ssocket的赋值是在服务器对象监听到有东西来连接的时候,通过nextPendingConnection获得的,是一个指针。
服务器向客户端写东西:sscoket->write()
客户端向服务器写东西:cscoket.write()
读取服务器获得的内容ssocket->readAll();
读取客户端获得的内容 csocket.readAll();