参考文章:qt socket通信
Socket通信
Qt中提供的所有的Socket类都是非阻塞的。
Qt中常用的用于socket通信的套接字类:
- QTcpServer
用于TCP/IP通信, 作为服务器端套接字使用
- QTcpSocket
用于TCP/IP通信,作为客户端套接字使用。
- QUdpSocket
用于UDP通信,服务器,客户端均使用此套接字。
TCP/IP
在Qt中实现TCP/IP服务器端通信的流程:
- 创建套接字
- 将套接字设置为监听模式
-
等待并接受客户端请求
可以通过QTcpServer提供的void newConnection()信号来检测是否有连接请求,如果有可以在对应的槽函数中调用nextPendingConnection函数获取到客户端的Socket信息(返回值为QTcpSocket*类型指针),通过此套接字与客户端之间进行通信。
-
接收或者向客户端发送数据
接收数据:使用read()或者readAll()函数
发送数据:使用write()函数
客户端通信流程:
-
创建套接字
-
连接服务器
可以使用QTcpSocket类的connectToHost()函数来连接服务器。
-
向服务器发送或者接受数据
关于“套接字”
server端:
#ifndef SERVERWIDGET_H #define SERVERWIDGET_H #include <QWidget> #include <QTcpServer> //监听套接字 #include <QTcpSocket> //通信套接字 namespace Ui { class serverWidget; } class serverWidget : public QWidget { Q_OBJECT public: explicit serverWidget(QWidget *parent = 0); ~serverWidget(); private slots: void on_buttonSend_clicked(); void on_buttonClose_clicked(); private: Ui::serverWidget *ui; QTcpServer *tcpServer; //监听套接字 QTcpSocket *tcpSocket; //通信套接字 }; #endif // SERVERWIDGET_H
#include "serverwidget.h" #include "ui_serverwidget.h" #pragma execution_character_set("utf-8") serverWidget::serverWidget(QWidget *parent) : QWidget(parent), ui(new Ui::serverWidget) { ui->setupUi(this); tcpServer = NULL; tcpSocket = NULL; //监听套接字,指定父对象,让其自动回收空间 tcpServer = new QTcpServer(this); //1.QTcpServer对象负责监听是否有客户端连接此服务器。它是通过这样一个函数监听的 //第一个参数表示服务器监听的地址,如果后面是Any表示监听本机的所有网口的,第二个参数表示监听的网络端口 tcpServer->listen(QHostAddress::Any, 8888); setWindowTitle("Sever"); //2.如果服务器监听到有客户端和它进行连接,服务器就会触发newConnection这个信号。同时客户端一旦和服务器连接成功, //客户端会触发connected这个信号,表示已经成功和服务器连接。 connect(tcpServer, &QTcpServer::newConnection, [=]() { //3.当服务器和客户端建立好连接之后,服务器需要返回一个QTcpSocket对象来和客户端进行通信,通常通过这个函数来返回一个建立好连接的套接字。 //客户端和服务器各有一个通信套接字,可以看出,每一方的套接字都可以获得对方的相关信息 //接着就可以通过两个的通信套接字来完成通信。 //取出建立好连接的套接字 tcpSocket = tcpServer->nextPendingConnection(); //获取对方的IP和端口 QString ip = tcpSocket->peerAddress().toString(); qint16 port = tcpSocket->peerPort(); QString temp = QString("[%1:%2]:成功连接").arg(ip).arg(port); ui->textEditRead->setText(temp); //4.当一端发送成功之后,"接收方"会触发这么一个信号,readyRead,这样我们就能够读取套接字当中的内容了。 connect(tcpSocket, &QTcpSocket::readyRead, [=]() { //从通信套接字中取出内容 QByteArray array = tcpSocket->readAll(); ui->textEditRead->append(array); } ); } ); } serverWidget::~serverWidget() { delete ui; } void serverWidget::on_buttonSend_clicked() { if(NULL == tcpSocket) { return; } //获取编辑区内容 QString str = ui->textEditWrite->toPlainText(); //给对方发送数据, 使用套接字是tcpSocket tcpSocket->write(str.toUtf8().data() ); } void serverWidget::on_buttonClose_clicked() { if(NULL == tcpSocket) { return; } //主动和客户端端口连接 tcpSocket->disconnectFromHost(); tcpSocket->close(); tcpSocket = NULL; }
客户端:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QTcpSocket>//通信套接字 namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_buttonConnect_clicked(); void on_buttonSend_clicked(); void on_buttonClose_clicked(); private: Ui::Widget *ui; QTcpSocket *tcpsocket; }; #endif // WIDGET_H
#include "widget.h" #include "ui_widget.h" #include <QHostAddress> #pragma execution_character_set("utf-8") Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); tcpsocket = NULL; //0.分配空间,指定父对象 tcpsocket = new QTcpSocket(this); setWindowTitle("客户端"); //3.连接成功之后客户端会触发这样一个信号 connected connect(tcpsocket,&QTcpSocket::connected, [=]() { ui->textEditRead->setText("成功和服务器建立好链接"); }); connect(tcpsocket,&QTcpSocket::readyRead, [=]() { //获取对方发送的内容 QByteArray array = tcpsocket->readAll(); //追加到编辑区中 ui->textEditRead->append(array); }); } Widget::~Widget() { delete ui; } void Widget::on_buttonConnect_clicked() { //1.获取服务器ip和端口 QString ip = ui->lineEditIP->text(); qint16 port = ui->lineEditPort->text().toInt(); //2.主动和服务器建立链接 tcpsocket->connectToHost(QHostAddress(ip),port); } void Widget::on_buttonSend_clicked() { //获取编框内容 QString str = ui->textEditWrite->toPlainText(); //发送数据 tcpsocket->write(str.toUtf8().data()); } void Widget::on_buttonClose_clicked() { //主动和对方断开连接 tcpsocket->disconnectFromHost(); tcpsocket->close(); }