TCP和UDP
https://www.cnblogs.com/fundebug/p/differences-of-tcp-and-udp.html

一、TCP通信

1.linux下TCP通信

更加详细部分,百度socket通信
01_LinuxTCP通信流程.png

2.QT下的TCP通信

03_QtTCP通信过程.png

3.代码

效果图
image.png

3.1 服务器端口

serverwidget.h

  1. #ifndef SERVERWIDGET_H
  2. #define SERVERWIDGET_H
  3. #include <QWidget>
  4. #include <QTcpServer>
  5. #include <QTcpSocket>
  6. #include <QDebug>
  7. namespace Ui {
  8. class ServerWidget;
  9. }
  10. class ServerWidget : public QWidget
  11. {
  12. Q_OBJECT
  13. public:
  14. explicit ServerWidget(QWidget *parent = 0);
  15. ~ServerWidget();
  16. private slots:
  17. void on_btnSend_clicked();
  18. void on_btnColse_clicked();
  19. private:
  20. Ui::ServerWidget *ui;
  21. QTcpServer *myTcpserver;
  22. QTcpSocket *myTcpsocket;
  23. };
  24. #endif // SERVERWIDGET_H

serverwidget.cpp

  1. #include "serverwidget.h"
  2. #include "ui_serverwidget.h"
  3. ServerWidget::ServerWidget(QWidget *parent) :
  4. QWidget(parent),
  5. ui(new Ui::ServerWidget)
  6. {
  7. ui->setupUi(this);
  8. qDebug() << myTcpsocket;
  9. //指定父对象,让其自动回收
  10. myTcpserver = new QTcpServer(this);
  11. myTcpsocket = NULL;
  12. //监听
  13. myTcpserver->listen(QHostAddress::Any, 8888);
  14. setWindowTitle("服务器:8888");
  15. connect(myTcpserver, &QTcpServer::newConnection, [=](){
  16. //取出建立好连接的套接字
  17. myTcpsocket = myTcpserver->nextPendingConnection();
  18. //获取对方的ip和端口
  19. QString ip = myTcpsocket->peerAddress().toString();
  20. qint64 port = myTcpsocket->peerPort();
  21. QString temp = QString("[%1:%2]:成功连接").arg(ip).arg(port);
  22. ui->textEditRead->setText(temp);
  23. //注意这里有了才可以连接
  24. connect(myTcpsocket, &QTcpSocket::readyRead, [=](){
  25. //同通信套接字取出内容
  26. QByteArray array = myTcpsocket->readAll();
  27. ui->textEditRead->append(QString(array));
  28. });
  29. });
  30. }
  31. ServerWidget::~ServerWidget()
  32. {
  33. delete ui;
  34. }
  35. void ServerWidget::on_btnSend_clicked()
  36. {
  37. if (NULL == myTcpsocket) {
  38. ui->textEditRead->append("客户端未连接");
  39. return;
  40. }
  41. //获取编辑区内容
  42. QString str = ui->textEditSend->toPlainText();
  43. //给对方发送数据,使用套接字是tcpscoket
  44. myTcpsocket->write(str.toUtf8().data());
  45. }
  46. void ServerWidget::on_btnColse_clicked()
  47. {
  48. if (NULL == myTcpsocket) {
  49. ui->textEditRead->append("客户端未连接");
  50. return;
  51. }
  52. //主动和客户端断开连接
  53. myTcpsocket->disconnectFromHost();
  54. myTcpsocket->close();
  55. myTcpsocket = NULL;
  56. }

3.2 客户端端口

clientwidget.h

  1. #ifndef CLIENTWIDGET_H
  2. #define CLIENTWIDGET_H
  3. #include <QWidget>
  4. #include <QTcpSocket>
  5. namespace Ui {
  6. class clientWidget;
  7. }
  8. class clientWidget : public QWidget
  9. {
  10. Q_OBJECT
  11. public:
  12. explicit clientWidget(QWidget *parent = 0);
  13. ~clientWidget();
  14. private slots:
  15. void on_btnConnect_clicked();
  16. void on_btnSend_clicked();
  17. void on_btnColse_clicked();
  18. private:
  19. Ui::clientWidget *ui;
  20. QTcpSocket *myTcpScoket;
  21. bool connectwith;
  22. };
  23. #endif // CLIENTWIDGET_H

clientwidget.cpp

  1. #include "clientwidget.h"
  2. #include "ui_clientwidget.h"
  3. #include <QHostAddress>
  4. clientWidget::clientWidget(QWidget *parent) :
  5. QWidget(parent),
  6. ui(new Ui::clientWidget)
  7. {
  8. ui->setupUi(this);
  9. setWindowTitle("客户端");
  10. connectwith = false;
  11. //分配空间
  12. myTcpScoket = new QTcpSocket(this);
  13. connect(myTcpScoket, &QTcpSocket::connected, [=](){
  14. connectwith = true;
  15. ui->textEditRead->setText("成功和服务器建立连接");
  16. connect(myTcpScoket, &QTcpSocket::readyRead, [=](){
  17. //获取对方发送的内容
  18. QByteArray array = myTcpScoket->readAll();
  19. //追加到内容
  20. ui->textEditRead->append(QString(array));
  21. });
  22. });
  23. connect(myTcpScoket, &QTcpSocket::disconnected, [=](){
  24. connectwith = false;
  25. ui->textEditRead->append("已成功与服务器断开连接");
  26. });
  27. }
  28. clientWidget::~clientWidget()
  29. {
  30. delete ui;
  31. }
  32. void clientWidget::on_btnConnect_clicked()
  33. {
  34. //获取服务器IP和端口
  35. QString ip = ui->lineEditIP->text();
  36. qint16 port = ui->lineEditPort->text().toInt();
  37. //主动和服务器建立连接
  38. myTcpScoket->connectToHost(QHostAddress(ip), port);
  39. }
  40. void clientWidget::on_btnSend_clicked()
  41. {
  42. if (connectwith == false) {
  43. ui->textEditRead->append("还未与服务器建立连接");
  44. return;
  45. }
  46. //获取编辑框内容
  47. QString str = ui->textEditWrite->toPlainText();
  48. //发送数据
  49. myTcpScoket->write(str.toUtf8().data());
  50. }
  51. void clientWidget::on_btnColse_clicked()
  52. {
  53. if (connectwith == false) {
  54. ui->textEditRead->append("还未与服务器建立连接");
  55. return;
  56. }
  57. //主动和对方端断开
  58. myTcpScoket->disconnectFromHost();
  59. myTcpScoket->close();
  60. }

代码:
server.rar

二、UDP通信

image.png

1.linux下UDP通信

02_LinuxUDP通信过程.png

2.QT下的UDP通信

04_QtUDP通信过程.png

3.广播和组播

3.1广播

在使用QUdpSocket类的writeDatagram()函数发送数据的时候,其中第二个参数host应该指定为广播地址:QHostAddress::Broadcast此设置相当于QHostAddress(“255.255.255.255”)
使用UDP广播的的特点:

  • 使用UDP进行广播,局域网内的其他的UDP用户全部可以收到广播的消息
  • UDP广播只能在局域网范围内使用

    3.2组播

    我们再使用广播发送消息的时候会发送给所有用户,但是有些用户是不想接受消息的,这时候我们就应该使用组播,接收方只有先注册到组播地址中才能收到组播消息,否则则接受不到消息。另外组播是可以在Internet中使用的。
    在使用QUdpSocket类的writeDatagram()函数发送数据的时候,其中第二个参数host应该指定为组播地址,关于组播地址的分类:
    06_组播地址分类.png

    3.代码

    udpwidget.h ```cpp

    ifndef UDPWIDGET_H

    define UDPWIDGET_H

include

include //UDP套接字

include

namespace Ui { class UdpWidget; }

class UdpWidget : public QWidget { Q_OBJECT

public: explicit UdpWidget(QWidget *parent = 0); ~UdpWidget(); private slots: //创建处理信息的槽 void dealMsg();

  1. void on_ptnSend_clicked();

private: Ui::UdpWidget *ui;

  1. QUdpSocket *udpSocket; //UDP套接字

};

endif // UDPWIDGET_H

  1. udpwidget.cpp
  2. ```cpp
  3. #include "udpwidget.h"
  4. #include "ui_udpwidget.h"
  5. UdpWidget::UdpWidget(QWidget *parent) :
  6. QWidget(parent),
  7. ui(new Ui::UdpWidget)
  8. {
  9. ui->setupUi(this);
  10. //分配空间,指定父对象
  11. udpSocket = new QUdpSocket(this);
  12. //绑定一个端口
  13. // udpSocket->bind(9000);
  14. //要加入组播
  15. udpSocket->bind(QHostAddress::AnyIPv4, 9000);
  16. udpSocket->joinMulticastGroup( QHostAddress("224.0.0.2") );
  17. //udpSocket->leaveMulticastGroup(); //退出组播
  18. //更改窗体名称
  19. setWindowTitle("服务器端口为9000");
  20. //当对方成功发送数据过来
  21. //自动触发 readyRead()
  22. connect(udpSocket, &QUdpSocket::readyRead, this, &UdpWidget::dealMsg);
  23. }
  24. UdpWidget::~UdpWidget()
  25. {
  26. delete ui;
  27. }
  28. void UdpWidget::dealMsg()
  29. {
  30. //读取对方发送的内容
  31. char buf[1024] = {0};
  32. //对方地址
  33. QHostAddress cliAddr;
  34. //对方端口
  35. quint16 port;
  36. qint64 len = udpSocket->readDatagram(buf, sizeof(buf), &cliAddr, &port);
  37. if (len > 0) {
  38. QString str = QString("[%1:%2] %3")
  39. .arg(cliAddr.toString())
  40. .arg(port)
  41. .arg(buf);
  42. //给编辑区设置内容
  43. ui->textEdit->setText(str);
  44. }
  45. }
  46. void UdpWidget::on_ptnSend_clicked()
  47. {
  48. //先获取对方的IP和端口
  49. QString ip = ui->lineEditIP->text();
  50. qint16 port = ui->lineEditPort->text().toInt();
  51. //获取编辑区内容
  52. QString str = ui->textEdit->toPlainText();
  53. //给指定的IP发送数据
  54. udpSocket->writeDatagram(str.toUtf8(), QHostAddress(ip), port);
  55. }

三、webscoket

image.png

1.简单使用和添加

在工程文件夹中添加:

  1. QT += websockets

包含该类

  1. #include <QWebSocket>

使用步骤:
使用时先new一个QWebsocket,然后关联其connected(),disconnected(),error(),textFrameReceived()(或者textMessageReceived()信号,两个收到消息的信号都会触发),发送调用sendTextMessage()函数即可。

2.代码

先简单写了客户端的代码,通过别人写的sever来进行了测试

2.1客户端

socketwidget.h

  1. #ifndef SOCKETWIDGET_H
  2. #define SOCKETWIDGET_H
  3. #include <QWidget>
  4. #include <QObject>
  5. #include <QWebSocket>
  6. namespace Ui {
  7. class SocketWidget;
  8. }
  9. class SocketWidget : public QWidget
  10. {
  11. Q_OBJECT
  12. public:
  13. explicit SocketWidget(QWidget *parent = 0);
  14. ~SocketWidget();
  15. private slots:
  16. void on_btnSend_clicked();
  17. void on_btnClose_clicked();
  18. void on_btnConnect_clicked();
  19. private:
  20. Ui::SocketWidget *ui;
  21. bool _running;
  22. //创建一个websocket对象
  23. QWebSocket *mywebsocket;
  24. };
  25. #endif // SOCKETWIDGET_H

socketwidget.cpp

  1. #include "socketwidget.h"
  2. #include "ui_socketwidget.h"
  3. SocketWidget::SocketWidget(QWidget *parent) :
  4. QWidget(parent),
  5. ui(new Ui::SocketWidget),
  6. _running(false),
  7. mywebsocket(NULL)
  8. {
  9. ui->setupUi(this);
  10. }
  11. SocketWidget::~SocketWidget()
  12. {
  13. if (mywebsocket != NULL) {
  14. mywebsocket->deleteLater();
  15. mywebsocket = 0;
  16. }
  17. delete ui;
  18. }
  19. void SocketWidget::on_btnConnect_clicked()
  20. {
  21. if (_running == true) {
  22. qDebug() << "websocket正在工作";
  23. return;
  24. }
  25. if (NULL == mywebsocket) {
  26. mywebsocket = new QWebSocket;
  27. //获取URL
  28. QUrl url(ui->lineEdit->text());
  29. //连接到URL
  30. mywebsocket->open(url);
  31. //设置为正在运行
  32. connect(mywebsocket, &QWebSocket::connected, [=](){
  33. _running = true;
  34. ui->textEditRead->setText("服务器连接成功");
  35. });
  36. connect(mywebsocket, &QWebSocket::disconnected, [=](){
  37. ui->textEditRead->setText("服务器已断开连接");
  38. });
  39. connect(mywebsocket, &QWebSocket::textMessageReceived, [=](const QString &message){
  40. ui->textEditRead->append(message);
  41. });
  42. }
  43. }
  44. void SocketWidget::on_btnSend_clicked()
  45. {
  46. mywebsocket->sendTextMessage(ui->textEditWrite->toPlainText());
  47. }
  48. void SocketWidget::on_btnClose_clicked()
  49. {
  50. if (NULL == mywebsocket)
  51. return;
  52. //关闭websocket
  53. mywebsocket->close();
  54. mywebsocket = NULL;
  55. _running = false;
  56. }

代码下载:
上述代码和下载的代码去一些区别
websocket.rar
测试服务器:
qtwebsockets-dev.rar