QT TCP服务器

avatar
作者
筋斗云
阅读量:2

客户端:

功能:

连接:获取ip地址和端口号,并连接   取消:关闭窗口

工程文件加上

QT=+=core gui network

相关类与函数

QTcpSocket类:(需要被包含)

connectToHost()  连接。参数:QHostAdress地址对象(可用QString初始化),端口号(16位短整型)(QString自带进制转换,如ip.toshort)

连接成功后会发出一个信号:&QTcpSocket::connected

连接异常也会发出一个信号:&QTcpSocket::disconnected

peerAddress();获取客户端地址

peerAddress的子函数toString():将其转化位字符串

peerPort():获取客户端端口号(并非服务器端口)

write():参数:QByteArray ,可用append拼接,发送后会出现&QTcpSocket::readyread信号

QHostAddress类:(需要被包含)

其他函数:

(QTcpSocket * )sender();获取信号的发送者并强制转为QTcpSocket指针

服务器:

相关类与函数:

QTcpServer类:

listen():监听网卡,参数QHostAdress::AnyIPv4,端口号

如果有信号,会发出QTcpServer::newConnection信号

nextPendingConnection() 建立TCP连接,返回QTcpSocket类型

实现服务器与客户端连接

在widget构造函数中监听网卡ip,等待请求,收到信号后与客户端建立连接

注意,必须使用127开头的地址

127.0.0.1 地址称为本地回环地址,是一种特殊的网络地址,用于让单独的计算机进行自我回路测试和通信。 这个地址在 IP 协议中被定义为环回地址。 在网络设备中,网络接口上的 127.0.0.1 地址本质上是本机对自己的网络地址。

通信

打开其他窗口:新建qt->设计师...,在客户端创建新的窗口类chat

this->hide()隐藏窗口

创建新窗口对象时要用堆空间创建,也即是指针形式,这样申请的内存不会被销毁,

widget在连接成功后隐藏当前窗口,并打开新窗口chat,与打开widget窗口类似

         chat *k=new chat(SOCKET);          k->show();

要将socket信息传到新窗口中,所以类chat中要有参数,并在chat构造函数中初始化

QTcpSocket *s

在新窗口中,使用socket中的write发送信息,参数是QByteArray类型

在服务器中连接后再connect一个新的信号与曹:

&QTcpSocket::readyRead &Widget::data_resslot

在槽函数中要注意变量的范围,如果QTcpSocket指针是内部变量,则需要使用

(QTcpSocket*)sender();

将其转化为QTcpSocket类型指针,再用readAll读取所有发送的数据。

服务器代码:

chat.h

#ifndef CHAT_H #define CHAT_H  #include <QWidget> #include <QTcpSocket>   namespace Ui { class chat; }  class chat : public QWidget {     Q_OBJECT  public:     explicit chat(QTcpSocket *s,QWidget *parent = nullptr);     ~chat();  private slots:     void on_clearButton_clicked();      void on_sendButton_2_clicked();  private:     Ui::chat *ui;     QTcpSocket *SOCKET; };  #endif // CHAT_H 

widget.h

#ifndef WIDGET_H #define WIDGET_H  #include <QWidget> #include <QTcpSocket> #include <QHostAddress> #include <QDebug> #include <QMessageBox> #include <chat.h>  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_cancelButton_2_clicked();      void on_connectButton_clicked();      void on_pushButton_clicked();  private:     Ui::Widget *ui;     QTcpSocket *SOCKET; }; #endif // WIDGET_H 

chat.cpp

#include "chat.h" #include "ui_chat.h"  chat::chat(QTcpSocket *s,QWidget *parent) :     QWidget(parent),     ui(new Ui::chat) {     ui->setupUi(this);     SOCKET=s; }  chat::~chat() {     delete ui; }  void chat::on_clearButton_clicked() {     ui->lineEdit->clear(); }  void chat::on_sendButton_2_clicked() {     QString text1=ui->lineEdit->text();     QByteArray ba;     ba.append(text1);     //write只能发送QByteArray类型数据     SOCKET->write(ba); } 

widget.cpp

#include "widget.h" #include "ui_widget.h"  Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget) {     ui->setupUi(this);     SOCKET=new QTcpSocket;     //成功/异常警告     connect(SOCKET,&QTcpSocket::connected,[this]()     {          QMessageBox::information(this,"提示","连接成功");          this->hide();          chat *k=new chat(SOCKET);          k->show();     });     connect(SOCKET,&QTcpSocket::disconnected,[this]()     {          QMessageBox::warning(this,"警告","连接异常");     });  }  Widget::~Widget() {     delete ui; }   void Widget::on_cancelButton_2_clicked() {     this->close(); }  void Widget::on_connectButton_clicked() {     //获取ip与端口号     QString com1=ui->COMlineEdit_2->text();     QString ip1=ui->IPlineEdit->text();     if(com1.isEmpty()||ip1.isEmpty())     {         QMessageBox::warning(this,"警告","请输入ip地址和端口号");     }     //开始连接     SOCKET->abort();     SOCKET->connectToHost(QHostAddress(ip1),com1.toShort()); }  void Widget::on_pushButton_clicked() {     qDebug()<<"disconnect";     SOCKET->disconnectFromHost(); } 

服务器代码:

widget.h

#ifndef WIDGET_H #define WIDGET_H  #include <QWidget> #include <QDebug> #include <QTcpServer> #include <QTcpSocket> #include <QHostAddress> #include <QMessageBox>   QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE #define TCPCOM 8000    class Widget : public QWidget {     Q_OBJECT  public:     Widget(QWidget *parent = nullptr);     ~Widget();  private slots:     void serverslot();     void on_check_clicked();     void data_resslot(); private:     Ui::Widget *ui;     QTcpServer *SERVER; }; #endif // WIDGET_H 

widget.cpp

#include "widget.h" #include "ui_widget.h"  Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget) {     ui->setupUi(this);     SERVER=new QTcpServer;     SERVER->listen(QHostAddress::Any,TCPCOM);     qDebug()<<TCPCOM;     connect(SERVER,&QTcpServer::newConnection,this,&Widget::serverslot); }  Widget::~Widget() {     delete ui; }  void Widget::serverslot() {     QTcpSocket *SOCKET1;     SOCKET1=SERVER->nextPendingConnection();     QHostAddress ip1=SOCKET1->peerAddress();     quint16 com1=SOCKET1->peerPort();     ui->comlineEdit->setText(QString::number(com1));     ui->iplineEdit_2->setText(ip1.toString());     QMessageBox::information(this,"提示","连接成功");     connect(SOCKET1,&QTcpSocket::readyRead,this,&Widget::data_resslot); }     void Widget::on_check_clicked() {     if(SERVER->isListening())     {             qDebug()<<"IS LISTENING";     }  } void Widget::data_resslot() {     QTcpSocket *Socket=(QTcpSocket*)sender();     ui->datalineEdit->setText(Socket->readAll());  } 

结果:

多线程

在服务器中启用多线程,即可接收多个客户端的连接。

相关类与函数

在文件中添加c++类,在继承中继承QThread,添加后多了.h和.cpp文件

QThread类,需要包含

start()打开线程

虚函数run():在run里连接信号与槽,线程处理函数

自定义信号

在类中定义,和private同级,在信号传递时可以附加参数

signals:  void sendtowidget(QByteArray ba);

在需要发出信号的地方加上即可,最后在widget中连接信号与槽

QByteArray ba=socket->readall(); emit sendtowidget(ba); 

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!