封装了一个类,可以进行在局域网进行P2P通讯(仅局域网可用)

也就是说,假设局域网中有10台电脑,那么从本机发出的数据,将依次派发到这10台电脑(目前的设计中包括自己这台)

在使用方面,构造的时候给端口和一些参数,然后只需要管send槽和accepted信号就可以了

特性/原理介绍:

1.UDP搜索

2.TCP通讯(短连接)

3.自带心跳包,自动维护可用ip

4.TCP工作线程为单独的线程,稳定

5.完全P2P,无需服务器

注意:

1.一台电脑只能使用单开,多开无法监听端口,就无法使用

2.用到了C++11语法,所以请务必开启11模式,不然会编译报错

3.使用前请在pro文件中加入

QT += network concurrent

CONFIG += c++11

上源码:

Jason_LanSocket.h

  1. #ifndef __JasonQt_LanSocket_h__
  2. #define __JasonQt_LanSocket_h__
  3. // Qt lib import
  4. #include <QMap>
  5. #include <QTcpSocket>
  6. #include <QTcpServer>
  7. #include <QUdpSocket>
  8. #include <QNetworkAddressEntry>
  9. #include <QtConcurrent>
  10. class JasonQt_LanSocket_TcpListen: public QTcpServer
  11. {
  12. Q_OBJECT
  13. public:
  14. void incomingConnection(qintptr socketDescriptor);
  15. signals:
  16. void newConnect(const qintptr socketDescriptor);
  17. };
  18. class JasonQt_LanSocket: public QObject
  19. {
  20. Q_OBJECT
  21. private:
  22. quint16 m_udpPort;
  23. quint16 m_tcpPort;
  24. quint16 m_pingInterval;
  25. quint16 m_pingTimeout;
  26. QTimer m_timerPing;
  27. QUdpSocket m_udpListen;
  28. JasonQt_LanSocket_TcpListen m_tcpListen;
  29. QThreadPool m_threadPool;
  30. QNetworkAddressEntry m_NetworkAddressEntry;
  31. QMap<quint32, qint64> m_availableIp;
  32. public:
  33. JasonQt_LanSocket(const quint16 &udpPort, const quint16 &tcpPort,
  34. const int &pingInterval = 1000, const int &pingTimeout = 10000,
  35. const quint8 &threadPoolCount = 20);
  36. bool begin(void);
  37. static QNetworkAddressEntry getNetworkAddressEntry(void);
  38. public slots:
  39. void send(const QByteArray &data);
  40. void ping(void);
  41. private slots:
  42. void udpNewConnect(void);
  43. void tcpNewConnect(const qintptr &socketDescriptor);
  44. signals:
  45. void accepted(const QHostAddress address, const QByteArray data);
  46. void newConnect(const QHostAddress address);
  47. void disConnect(const QHostAddress address);
  48. void sendSucceed(const QHostAddress address);
  49. };
  50. #endif//__JasonQt_LanSocket_h__

Jason_LanSocket.cpp

  1. #include "JasonQt_LanSocket.h"
  2. // JasonQt_LanSocket_TcpListen
  3. void JasonQt_LanSocket_TcpListen::incomingConnection(qintptr socketDescriptor)
  4. {
  5. emit newConnect(socketDescriptor);
  6. }
  7. // JasonQt_LanSocket
  8. JasonQt_LanSocket::JasonQt_LanSocket(const quint16 &udpPort, const quint16 &tcpPort,
  9. const int &pingInterval, const int &pingTimeout,
  10. const quint8 &threadPoolCount):
  11. m_udpPort(udpPort),
  12. m_tcpPort(tcpPort),
  13. m_pingInterval(pingInterval),
  14. m_pingTimeout(pingTimeout)
  15. {
  16. connect(&m_timerPing, SIGNAL(timeout()), this, SLOT(ping()));
  17. connect(&m_udpListen, SIGNAL(readyRead()), this, SLOT(udpNewConnect()));
  18. connect(&m_tcpListen, SIGNAL(newConnect(qintptr)), this, SLOT(tcpNewConnect(qintptr)));
  19. m_threadPool.setMaxThreadCount(threadPoolCount);
  20. }
  21. bool JasonQt_LanSocket::begin(void)
  22. {
  23. m_NetworkAddressEntry = getNetworkAddressEntry();
  24. if(!m_NetworkAddressEntry.ip().toIPv4Address() || !m_udpListen.bind(QHostAddress::Any, m_udpPort) || !m_tcpListen.listen(QHostAddress::Any, m_tcpPort))
  25. {
  26. m_timerPing.stop();
  27. return false;
  28. }
  29. m_timerPing.start(m_pingInterval);
  30. return true;
  31. }
  32. QNetworkAddressEntry JasonQt_LanSocket::getNetworkAddressEntry(void)
  33. {
  34. auto allInterfaces = QNetworkInterface::allInterfaces();
  35. // Scan en0
  36. for(const auto &interface: allInterfaces)
  37. {
  38. if(interface.name().indexOf("en0") != -1)
  39. {
  40. for(const auto &entry: interface.addressEntries())
  41. {
  42. if(entry.ip().toIPv4Address())
  43. {
  44. return entry;
  45. }
  46. }
  47. }
  48. }
  49. // Scan other
  50. for(const auto &interface: allInterfaces)
  51. {
  52. for(const auto &entry: interface.addressEntries())
  53. {
  54. if(entry.ip().toIPv4Address())
  55. {
  56. if(entry.ip().toString().indexOf("10.0.") == 0)
  57. {
  58. return entry;
  59. }
  60. else if(entry.ip().toString().indexOf("192.168.") == 0)
  61. {
  62. return entry;
  63. }
  64. }
  65. }
  66. }
  67. return QNetworkAddressEntry();
  68. }
  69. void JasonQt_LanSocket::send(const QByteArray &data)
  70. {
  71. for(auto it = m_availableIp.begin(); it != m_availableIp.end(); it++)
  72. {
  73. QtConcurrent::run(&m_threadPool, [=](const QHostAddress &address, const QByteArray &data)
  74. {
  75. auto socket = new QTcpSocket;
  76. socket->connectToHost(address, m_tcpPort);
  77. if(!socket->waitForConnected(5000))     { socket->deleteLater(); return; }
  78. socket->write(QString::number(data.size()).toLatin1());
  79. if(!socket->waitForBytesWritten(5000))  { socket->deleteLater(); return; }
  80. if(!socket->waitForReadyRead(5000))     { socket->deleteLater(); return; }
  81. if(socket->readAll() != "OK")           { socket->deleteLater(); return; }
  82. socket->write(data);
  83. if(!socket->waitForBytesWritten(5000))  { socket->deleteLater(); return; }
  84. socket->waitForReadyRead(5000);
  85. emit sendSucceed(address);
  86. QTimer::singleShot(5000, socket, SLOT(deleteLater()));
  87. }, QHostAddress(it.key()), data);
  88. }
  89. }
  90. void JasonQt_LanSocket::ping(void)
  91. {
  92. auto &¤tTime = QDateTime::currentDateTime().toMSecsSinceEpoch();
  93. for(auto it = m_availableIp.begin(); it != m_availableIp.end(); it++)
  94. {
  95. if((currentTime - it.value()) > m_pingTimeout)
  96. {
  97. emit disConnect(QHostAddress(it.key()));
  98. m_availableIp.erase(it);
  99. it = m_availableIp.begin();
  100. }
  101. }
  102. QJsonObject data;
  103. data.insert("Type", "Ping");
  104. data.insert("Ip", QString::number(m_NetworkAddressEntry.ip().toIPv4Address()));
  105. auto socket = new QUdpSocket;
  106. socket->writeDatagram(QJsonDocument(data).toJson(), m_NetworkAddressEntry.broadcast(), m_udpPort);
  107. QTimer::singleShot(1000, socket, SLOT(deleteLater()));
  108. }
  109. void JasonQt_LanSocket::udpNewConnect(void)
  110. {
  111. while(m_udpListen.hasPendingDatagrams())
  112. {
  113. QByteArray datagram;
  114. datagram.resize(m_udpListen.pendingDatagramSize());
  115. m_udpListen.readDatagram(datagram.data(), datagram.size());
  116. QJsonObject data = QJsonDocument::fromJson(datagram).object();
  117. if(data.contains("Type") && (data.value("Type").toString() == "Ping") && data.contains("Ip"))
  118. {
  119. if(m_availableIp.find(data.value("Ip").toString().toUInt()) == m_availableIp.end())
  120. {
  121. emit newConnect(QHostAddress(data.value("Ip").toString().toUInt()));
  122. }
  123. m_availableIp[data.value("Ip").toString().toUInt()] = QDateTime::currentDateTime().toMSecsSinceEpoch();
  124. }
  125. }
  126. }
  127. void JasonQt_LanSocket::tcpNewConnect(const qintptr &socketDescriptor)
  128. {
  129. QtConcurrent::run(&m_threadPool, [=](const qintptr &socketDescriptor)
  130. {
  131. auto socket = new QTcpSocket;
  132. int psckageSize = -1;
  133. QByteArray buf;
  134. if(!socket->setSocketDescriptor(socketDescriptor)) { socket->deleteLater(); return; }
  135. if(!socket->waitForConnected(5000)) { socket->deleteLater(); return; }
  136. if(!socket->waitForReadyRead(5000)) { socket->deleteLater(); return; }
  137. psckageSize = socket->readAll().toInt();
  138. socket->write("OK");
  139. socket->waitForBytesWritten(5000);
  140. while(socket->waitForReadyRead(5000))
  141. {
  142. buf.append(socket->readAll());
  143. }
  144. if(buf.size() != psckageSize) { socket->deleteLater(); return; }
  145. socket->write("OK");
  146. socket->waitForBytesWritten(5000);
  147. emit accepted(socket->peerAddress(), buf);
  148. QTimer::singleShot(1000, socket, SLOT(deleteLater()));
  149. }, socketDescriptor);
  150. }

我也写了一个示例工程,可以到下方链接中下载

http://download.csdn.net/detail/wsj18808050/8369201

http://blog.csdn.net/wsj18808050/article/details/42778751

Qt:基于TCP和UDP的局域网P2P(局域网)通讯封装的更多相关文章

  1. Java Socket实现基于TCP和UDP多线程通信

    一.通过Socket实现TCP编程 1.1 TCP编程 TCP协议是面向连接,可靠的,有序的,以字节流的方式发送数据.基于TCP协议实现网络通信的类有客户端的Socket类和服务器端的ServerSo ...

  2. Qt基于tcp协议网络编程

    基于Qt网络编程: 基于tcp协议 c/s模式编程 所需要的类:QTcpServer QTcpSocket 利用qt基于tcp协议编写c/s模式程序: 两个类中的信号: QTcpServer : ne ...

  3. 基于TCP和UDP的socket

    为什么学习socket 你自己现在完全可以写一些小程序了,但是前面的学习和练习,我们写的代码都是在自己的电脑上运行的,虽然我们学过了模块引入,文件引入import等等,我可以在程序中获取到另一个文件的 ...

  4. 基于TCP与UDP协议的socket通信

    基于TCP与UDP协议的socket通信 C/S架构与初识socket 在开始socket介绍之前,得先知道一个Client端/服务端架构,也就是 C/S 架构,互联网中处处充满了 C/S 架构(Cl ...

  5. Python网络编程02 /基于TCP、UDP协议的socket简单的通信、字符串转bytes类型

    Python网络编程02 /基于TCP.UDP协议的socket简单的通信.字符串转bytes类型 目录 Python网络编程02 /基于TCP.UDP协议的socket简单的通信.字符串转bytes ...

  6. 轨迹系列——Socket总结及实现基于TCP或UDP的809协议方法

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在上一篇博客中我详细介绍了809协议的内容.809协议规范了通 ...

  7. 轨迹系列7——Socket总结及实现基于TCP或UDP的809协议方法

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在上一篇博客中我详细介绍了809协议的内容.809协议规范了通 ...

  8. Node.js权威指南 (7) - 实现基于TCP与UDP的数据通信

    7.1 使用net模块实现基于TCP的数据通信 / 136 7.1.1 创建TCP服务器 / 136 7.1.2 socket端口对象 / 142 7.1.3 创建TCP客户端 / 151 7.1.4 ...

  9. 基于tcp和udp协议的套接字

    socket:是在应用层和传输层之间的一个抽象层,它把TCP/IP层的复杂的操作封装抽象,并提供一些接口供应用层调用 套接字:被设计用于同一台主机上多个应用程序之间的通信,被称为进程之间通信或IPC ...

  10. 初识Socket通信:基于TCP和UDP协议学习网络编程

    学习笔记: 1.基于TCP协议的Socket网络编程: (1)Socket类构造方法:在客户端和服务器端建立连接 Socket s = new Socket(hostName,port);以主机名和端 ...

随机推荐

  1. EditPlus 快速去重

  2. Almost Prime

    Description Almost Prime time limit per test: 2 seconds memory limit per test: 256 megabytes input: ...

  3. CSS左中右布局,规范案例

    html部分 <body> <form id="form1" runat="server"> <div id="wrap ...

  4. 迎接 Windows Azure 和 DNN 挑战,几分钟内快速构建网站!

    编辑人员注释:本文章由高级商务策划师兼开发平台推广者 Neeti Gupta 撰写. 曾几何时,构建一个简单的网站需要耗费好几个月的时间.在过去,.NET 开发人员和设计社区的一些成员使用 DNN(以 ...

  5. [技巧]使用Xcode集成的HeaderDoc自动生成注释和开发文档

    [技巧]使用Xcode集成的HeaderDoc自动生成注释和开发文档     Doxygen本来是一个很好的工具,可是我感觉在mac系统下,如果用doxygen最后生成的CHM文件感觉就不是那么恰当, ...

  6. vs2008 + OpenCV-2.1.0-win32-vs2008安装

    vs2008 + OpenCV-2.1.0-win32-vs2008安装 1. 安装vs2008+sp12. 安装opencv-2.1.0-win32-vs2008,假设安装目录为c:/opencv2 ...

  7. 收敛 p75

    三种收敛.中心极限定理.大数定理.delta方法

  8. 使用after伪类清除浮动

    使用after伪类清除浮动 .department li:after{ content:"."; height:0; visibility:hidden; display:bloc ...

  9. Reward(拓扑结构+邻接表+队列)

    Reward Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submis ...

  10. 关于在用Swift开发iOS时如何隐藏NavigationBar和TabBar

    举个例子:如果我有一个页面需要进入时同时隐藏NavigationBar和TabBar,那么我就在那个页面的ViewController的代码里加上下面的代码.就可以实现了.接下来告诉大家每一块要注意的 ...