C++ Winsock P2P

2023-12-02

Scenario

有没有人有任何使用 Winsock 在 C++ 中进行点对点 (p2p) 网络的好例子? 这是我对特别需要使用这项技术的客户的要求(天知道为什么)。 我需要确定这是否可行。

任何帮助将不胜感激。

EDIT

我想避免使用库,以便我可以理解底层源代码并进一步加深我的知识。


由于我不知道您在寻找什么信息,因此我将尝试描述如何设置套接字程序以及我遇到的陷阱。

首先,*阅读Winsock教程在 MSDN。这是一个用于连接、发送消息和断开连接的基本程序。这对于了解套接字编程非常有用。

接下来,我们开始:

注意事项:

  • 阻塞或非阻塞

    首先,您需要决定是否需要阻塞程序或非阻塞程序。如果您有 GUI,则需要使用非阻塞或线程以避免冻结程序。我这样做的方法是使用阻塞调用,但总是调用select在调用阻塞函数之前(稍后将详细介绍 select)。这样我就避免了线程和互斥体之类的东西,但仍然使用基本的accept, send and receive calls.

  • 您不能相信您的包裹会按照您发送的方式到达!

    你也无法控制这一点。这是我遇到的最大问题,基本上是因为网卡可以决定发送哪些信息以及何时发送。我解决这个问题的方法是制作一个networkPackageStruct,包含一个size and data,其中 size 是该数据包中的数据总量。请注意,您发送的消息可以分为 2 个或更多数据包,也可以与您发送的另一条消息合并。

    考虑以下:

    您发送两条消息

      "Hello"
      "World!"
    

    当您发送这两条消息时send发挥你的recv函数可能不会像这样得到它们。它可能看起来像这样:

      "Hel"
      "loWorld!"
    

    也许

      "HelloWorld!"
    

    无论底层网络感觉如何。

  • 记录(几乎)所有内容!

    调试网络程序很困难,因为您无法完全控制它(因为它位于两台计算机上)。如果您遇到阻塞操作,您也看不到它。这也可以称为“了解您的阻止代码”。当一侧发送某些内容时,您不知道它是否会到达另一侧,因此请跟踪发送的内容和接收的内容。

  • 注意socket错误

    Winsock 函数返回大量信息。了解你的WSAGetLastError()功能。我不会将其保留在下面的示例中,但请注意它们往往会返回大量信息。每次你得到一个SOCKET_ERROR or INVALID_SOCKET检查Winsock 错误消息查找它。

设置连接:

  • 由于您不需要服务器,因此所有客户端都需要一个侦听套接字来接受新连接。最简单的是:

      SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
      sockaddr_in localAddress;
      localAddress.sinfamily = AF_INET;
      localAddress.sin_port = htons(10000);  // or whatever port you'd like to listen to
      localAddress.sin_addr.s_addr = INADDR_ANY;
    

    INADDR_ANY 很棒 - 它使您的套接字侦听所有 IP 地址,而不仅仅是一个 IP 地址。

      bind(s, (SOCKADDR*)&localAddress, sizeof(localAddress));
      listen(s, SOMAXCONN);
    

    有趣的部分来了。bind and listen不会阻止但是accept将要。诀窍是使用select检查是否有传入连接。所以上面的代码只是设置socket。在程序循环中,您检查套接字中的新数据。

交换数据

  • 我解决这个问题的方法是使用select很多。基本上,您可以查看任何套接字上是否有任何需要响应的内容。这是通过FD_xxx功能。

      // receiving data
      fd_set mySet;
      FD_ZERO(&mySet);
      FD_SET(s, &mySet);
      // loop all your sockets and add to the mySet like the call above
      timeval zero = { 0, 0 };
      int sel = select(0, &mySet, NULL, NULL, &zero);
      if (FD_ISSET(s, &mySet)){
          // you have a new caller
          sockaddr_in remote;
          SOCKET newSocket = accept(s, (SOCKADDR*)&remote, sizeof(remote));
      }
      // loop through your sockets and check if they have the FD_ISSET() set
    

In the newSocket你现在有了一个新的同伴。这是为了接收数据。但请注意! send还堵!我遇到的令人头疼的错误之一是send阻止了我。然而,这也解决了select.

 // sending data
 // in: SOCKET sender
 fd_set mySet;
 FD_ZERO(&mySet);
 FD_SET(sender, &mySet);
 timeval zero = { 0, 0 };
 int sel = select(0, NULL, mySet, NULL, &zero);
 if (FD_ISSET(sender, &mySet)){
      // ok to send data
 }

正在关闭

最后,有两种方法可以关闭。您要么通过关闭程序来断开连接,要么调用shutdown功能。

  • 调用 shutdown 将使你的同伴select扳机。recv但是不会收到任何数据,而是返回 0。我没有注意到任何其他情况recv返回 0,因此可以(在某种程度上)安全地说这可以被视为关闭代码。呼叫shutdown是最好的事情。
  • 不调用就关闭连接shutdown只是冷酷无情,但当然有效。即使您使用,您仍然需要处理错误shutdown,因为关闭连接的可能不是您的程序。一个值得记住的错误代码是 10054,它是WSAECONNRESET: Connection reset by peer.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ Winsock P2P 的相关文章

随机推荐

  • 带有对象的 Javascript 纯函数示例

    我有下面一个不纯函数的例子 注意变量a超出了正在更改的函数范围 为了解决这个问题 人们可以克隆函数内的对象并返回一个副本 但这是正确的方法吗 实现该功能有哪些选项transformObject pure var a a 1 b 2 func
  • 给定大小为 n 的矩阵,计算距中心的距离矩阵

    假设我有一个大小为 n 非 1 的奇数 的矩阵 我想计算每个条目距中心的距离 例如 如果 n 2 则矩阵为 5 x 5 要找到矩阵的中心 您需要执行以下操作 import numpy as np import math center mat
  • 在 EF4 中控制 ArithAbort

    我们的 EF4 MVC 解决方案存在一些性能问题 我们已经能够追踪到 ArithAbort 在所有与数据库的连接之前被设置为关闭 现在我们正在尝试强制它保持 打开 状态 我们研究过 如何控制 Linq to SQL 发出的 SET 语句 但
  • 在命令行工具上使用 Swift URLSession 示例代码

    我想弄清楚simplest在 Swift 4 中从命令行发出 HTTP 请求的方法 我从以下位置复制了这段代码URLSession 编程指南 并添加了一些打印语句 我不明白为什么 dataTask没有执行 print Testing URL
  • 使用 Javascript 进行 Web 应用程序的 iOS 3D Touch API

    iPhone 6s 具有用于本机应用程序的 3D 触摸 API 我想知道 Apple 是否为 Web 应用程序启用了从 Javascript 进行 3D 触摸访问 就像我们使用标准触摸事件一样 element addEventListene
  • 如何根据json中的属性编写jackson反序列化器

    我想在类 Type 上编写 json 反序列化器 以便当基于名称从给定的 json 反序列化 Type 时 它 会将值 类型接口 Being 映射到基于某些工厂方法的当前实现 该工厂方法根据名称返回正确的类名称 并填充剩余的类没有任何显式的
  • 填充 numpy 数组的对角线失败

    我正在尝试填充矩阵的偏移对角线 loss matrix np zeros 125 125 np diagonal loss matrix 3 fill 4 ValueError assignment destination is read
  • 获取android中卸载应用程序的意图

    我只是想知道卸载应用程序的意图 因为 在我的应用程序中 当用户打开第一个屏幕时 设备 ID 将使用 php ini 保存在服务器端 当用户卸载此应用程序时 该设备将自动在服务器端删除 为此 我准备了用于删除设备 ID 的 php 代码 那么
  • Openpyxl 在保存时损坏 xlsx。即使没有做出任何改变

    TL DR 使用 Openpyxl 保存对大型 Excel 文件的更改会导致 xlsx 文件损坏 Excel 文件由多个带有图形 公式 图像和表格的选项卡组成 Powershell 脚本可以毫无问题地将编辑保存到 xlsx 文件 我可以使用
  • 用于 C# 的 Google 地图 API

    我对使用 API 非常陌生 所以在查看 Google Maps API 页面后 我不确定是否有设计用于 C 的 API 我不需要在我的应用程序上显示 Google 地图 我需要知道的是我是否可以在 C 上使用 Google Maps API
  • 当提供空列表时,是否有一个标志可以使 docker 静音

    当在一个遵循以下模式的命令中运行多个 docker 命令时 这一功能非常有用 docker do smth docker query smth 例如 docker stop docker ps q or docker rm docker p
  • Visual Studio 托管流程的目的是什么?

    使用 Visual Studio 调试程序时 您可以选择Enable the Visual Studio hosting process 这个选项的目的是什么 有什么作用 MSDN 库没有提供有关 托管进程 的很好的信息 Eric 链接中列
  • jquery 中的 .load() 方法给我 404 - 未找到错误

    我有一个简单的页面 我需要将 html 文件加载到 DIV 中 但我总是遇到 404 NOT FOUND 我的 JSP 文件的同一文件夹中有一个名为 demo test txt 的文件 我需要将此文件加载到 ID div1 的 div 这是
  • MongoDB:$elemMatch

    我正在尝试使用 elemMatch在数组中查找对象 我将以下数据导入到名为的集合中trails Copper name Spaulding Bowl level Extreme Terain location East Side name
  • 在python中将IP地址转换为字节

    假设我在 python 中有一个IP地址 addr 164 107 113 18 如何将IP地址转换为4字节 Use socket inet aton gt gt gt import socket gt gt gt socket inet
  • 如何在jsp中获取上传文件的完整路径?

    在我的jsp页面中 使用文件上传并将字符串文件传递到java页面以复制到特定文件夹 我想要复制文件的完整路径 但我只得到一个带有扩展名的文件名 扫描文件 ABC pdf 它仅显示 ABC pdf 我想显示 c abc pdf JSP确实是一
  • mongodb子元素查询

    这是例子 gt db test insert name test values check true check false gt db find values check true 0 所以我既得到了真也得到了假check id Obje
  • (公共)网关和服务之间的 Istio 503:s

    我一直在尝试我的 Istio 集群配置 但最终陷入了无法调试的状态 我有配置了公共 IP 的 SDS 网关 我已经在端口 5000 上部署了 Istio HelloWorld 应用程序 我可以 执行到istio proxy on the h
  • 包装函数的内联汇编器由于某种原因不起作用

    我正在尝试为 read 系统调用编写一个包装函数 使用 asm 易失性 但它不会工作 因为 res 不会改变它的值 这是代码 ssize t my read int fd void buf size t count ssize t res
  • C++ Winsock P2P

    Scenario 有没有人有任何使用 Winsock 在 C 中进行点对点 p2p 网络的好例子 这是我对特别需要使用这项技术的客户的要求 天知道为什么 我需要确定这是否可行 任何帮助将不胜感激 EDIT 我想避免使用库 以便我可以理解底层