一、TCP
服务器:socket、bind、listen、accept、send/recv
客户端:socket、connect(对应服务器的accept)、send/recv
二、TCP客户端
1、qt中所有跟网络相关的必须添加network
2、创建tcp对象
(1)在头文件中
#include <QTcpSocket>
#include <QHostAddress>//主机地址
#include <QMessageBox>
#include <QDebug>
#include <chat.h>
private:
Ui::Widget *ui;
QTcpSocket *socket;
(2)widget.cpp构造函数
socket = new QTcpSocket; //创建socket对象
(3)点击连接时,获取文本框的内容
void Widget::on_connectButton_clicked()
{
//获取ip地址和端口号
QString IP = ui->ipLineEdit->text();
QString port = ui->portLineEdit->text();
//连接服务器
//用ip构造一个QHostAddress对象,并将port转换成短整形
socket->connectToHost(QHostAddress(IP), port.toShort());
//连接服务器成功,socket对象会发出信号,判断这个信号有没有发出即可
connect(socket, &QTcpSocket::connected, [this]()
{
QMessageBox::information(this, "连接提示", "连接服务器成功");
this->hide();
Chat *c = new Chat(socket); //堆空间创建
c->show();
});
//连接断开,socket会发出信号
connect(socket, &QTcpSocket::disconnected, [this]()
{
QMessageBox::warning(this, "连接提示", "连接异常 网络断开");
});
}
(4)获取的数据从终端发出:
#include <QDebug>
qDebug()<<IP;
三、TCP服务器
服务器有对象,客户端没有对象,只需要有个socket即可
1、头文件中创建一个server指针
#include <QTcpServer>
#include <QTcpSocket>
#include <mythread.h>
#define PORT 8000
QTcpServer *server;
2、widget.cpp
(1)构造函数——监听等待客户端发起连接
server = new QTcpServer;//创建服务器对象
//此处不需要绑定,直接监听即可
//监听客户端(端口号和网卡)
server->listen(QHostAddress::AnyIPv4, PORT);
//客户端发起连接,server发出信号,
connect(server, &QTcpServer::newConnection, this, &Widget::newClientHandler);
(2)构造函数——建立TCP连接、获取客户端的端口号和地址并显示在界面上
void Widget::newClientHandler()
{
//建立TCP连接
QTcpSocket *socket = server->nextPendingConnection();
//socket->peerAddress(); //获取客户端地址(地址保存在连接之中)
//socket->peerPort(); //获取客户端的端口号
ui->ipLineEdit->setText(socket->peerAddress().toString());
ui->portLineEdit->setText(QString::number(socket->peerPort()));
}
四、建立新窗口
1、启动新的窗口——连接成功后,原窗口隐藏,显示新的界面
this->hide();
Chat *c = new Chat(socket); //堆空间创建
c->show();
2、新界面
(1)清空健——将输入信息清空
void Chat::on_clearButton_clicked()
{
ui->lineEdit->clear();
}
(2)启动新的界面
首先在widget.h中包含#include<chat.h>
this->hide();//把当前的界面隐藏
Chat *c = new Chat(socket); //启动新的界面,堆空间创建
c->show();
不能是Chat c;因为这样在栈空间创建,函数结束后,就没有了
(3)chat.cpp——创建chat的界面,即清空、发送健、和文本框
void Chat::on_clearButton_clicked()//清空健
{ ui->lineEdit->clear(); }
void Chat::on_sendButton_clicked(){//发送健
QByteArray ba;
ba.append(ui->lineEdit->text());
socket->write(ba);
}
void Chat::recvInfoSlot()//获取的文本
{ ui->recvLineEdit->setText(QString(socket->readAll())); }
(4)在服务器处添加获取客户端信息的代码
void Widget::clientInfoSlot()
{
//sender捕捉信号,获取信号的发出者
QTcpSocket *s = (QTcpSocket *)sender();
ui->mainLineEdit->setText(QString(s->readAll()));
}
void Widget::newClientHandler()中
//服务器收到客户端发送的信息,socket发出readyread信号
connect(socket, &QTcpSocket::readyRead, this, &Widget::clientInfoSlot);
五、多线程
1、创建文件——要继承Object类
在mythread.h中,myThread要继承Qobject类和QThread类
包含头文件:#include <QThread>
调用t->start()时,运行的是run,该实验要重写run
public:
explicit myThread(QTcpSocket *s);
void run(); //线程处理函数
2、widget.cpp——一旦建立连接,就要启动线程
//启动线程
myThread *t = new myThread(socket); //创建线程对象,要把对象传过去
t->start(); //开始线程
connect(t, &myThread::sendToWidget, this, &Widget::threadSlot);
3、mythread.cpp
myThread::myThread(QTcpSocket *s){
socket = s; }
void myThread::run(){
connect(socket, &QTcpSocket::readyRead, this, &myThread::clientInfoSlot);
}
//不能在其他类里面操作界面
void myThread::clientInfoSlot(){
//qDebug() << socket->readAll();
QByteArray ba = socket->readAll();//把所有数据读出来
emit sendToWidget(ba); //发送信号
}
五、自定义信号
服务器后台的线程收到的数据,然后线程把数据送到窗口上面
(1)mythread.cpp获取信息
QByteArray ba = socket->readAll();//把所有数据读出来
emit sendToWidget(ba); //发送信号,没有具体发哦是那个给谁,谁需要自己来拿
(2)widget.cpp中获取信号的信息
connect(t, &myThread::sendToWidget, this, &Widget::threadSlot);
void Widget::threadSlot(QByteArray b)
{
ui->mainLineEdit->setText(QString(b));
}
将发送的信息接收,并显示在文本框上