ssr:

ssr:

八月底,我在家工作。 后来,有人让我向办公室发送一个 VMWare 映像。 虚拟机的大小为 +17 GB,因此无法使用 Slack。 由于我不在办公室,使用 USB 驱动器也不是办法。

我有一些空闲时间,于是就想:"好吧,用它来编写一个小程序。UDT's 交会模式应该很简单"(这种模式基本上可以让你建立真正的 P2P 连接)... 顺便说一下,我本可以用更好的东西,比如 ,但是......嘿,我只是想做一些编码工作 :-)

ssr:

ssr:

我是几天后才发现上面这个笑话的。 xkcd 的人描述了如何文件传输问题尚未解决.

ssr:

此外bar.io后来我还发现一些JavaScript WebRTC 代码与我试图通过命令行实现的功能完全相同.

我试图为 C# 找一个 WebRTC 实现,结果发现了来自 Frozen Mountain 的 IceLink ()。 我还没有尝试,但它看起来很棒。

ssr:

简单说明一下:我所说的 P2P 是指在两个不同的防火墙后连接两台电脑。

如果计算机在同一个本地网络上,或者可以直接从互联网访问,我就不会在这篇博文中将其视为 P2P(理论上可以是,但要让它们连接起来,传统的套接字操作就足够了)。

ssr:

ssr:

其实应该是 "看,妈,没有服务器!"。

要在两台位于不同防火墙后的计算机之间建立 P2P 连接,首先需要获取并交换它们的公共 IP 和端口。

然后,每台计算机都会尝试连接到另一个 IP:端口,如果幸运的话,它们会穿越 NAT 并连接上(你知道,防火墙/NAT 允许你在使用公网 IP 的同时使用私网 IP)。

但你需要一个中央服务器来协调这一过程。 每台客户端计算机都要连接一台服务器,用来获取和交换它们的 IP 地址。

ssr:

我们自己的管道服务器可以扮演这个角色(它已经在为我们自己的伪 P2P 操作充当中继服务器--所有流量都通过中央服务器,这是我想避免的真正的 P2P 操作)。

ssr:

#@#But I wanted to write a small console application so simple that it didn't need to "trust" any intermediate server, so I didn't want to use a central server to do the initial negotiation (or signaling).#@#

我想要一个无服务器的 P2P 设置...

因此,我们的目标是让 p2pcopy 启动,显示公共 IP(这需要一个服务器),并询问对方的公共 IP。 然后,p2pcopy 的用户将通过 Slack 或任何其他消息系统交换他们的公共 IP:端口,然后开始数据传输...... 无需服务器。

ssr:

到目前为止,我一直认为 UDT 是理所当然的。 UDT 是在 UDP 基础上编写的一个巧妙协议,在高延迟/高带宽网络上的性能优于 TCP。

这意味着什么? 嗯,如果你的 ping 需要 100 毫秒,但你的带宽很高,那么 UDT 将绕着 TCP 跑一圈。

nonenone.

none

ssr:

UDT 编码交会模式none

none

如果两个对等体执行相同的代码,它们就会真正连接起来!

#@#Yes, they both "connect()" instead of a connect/accept pair, and it works, that's the magic of NAT traversal.#@#

#@#I tested this with 2 laptops, manually, one on the Codice'ssr: and the other just on my LAN (Wi-Fi) and... it worked! Although I had to run the two peers concurrently for it to work... which is something I initially sub estimated when I though "I will code it in 5 minutes".#@#

ssr:

运行 p2pcopy 的每个节点都必须获取其外部 IP 和端口,以便与另一个对等节点交换。 为了做到这一点,我使用了(并清理了)我在CodeProject:用 C# 实现 STUN 客户端。

ssr:

到目前为止,整个编码过程都非常迅速,只需几分钟就能启动和运行。

none

于是,我决定向办公室的一位同事求助。

我们都启动了自己的应用程序,交换了 IP,点击 ENTER,然后......什么都没有! 没成功 哎哟

然后,我们开始使用 Slack 手动同步,以便能够同时 HIT 运行连接代码(在同一张桌子上的两台笔记本电脑上按 ENTER 键时,这并不难)。 结果还是不行。

最糟糕的是,当你的同事开始取笑你时,你知道,"是啊,你这是多么伟大的发明啊!" :-D

none

如果是这样的话,我的 p2pcopy 就没什么用了

ssr:

与真实用户的首次测试完全失败。 我花了 10 分钟编写 p2pcopy 的代码",结果还是要多花一点时间。

#@#Initially I thought: "ok, it can't be done without a central server, that's all". But, well, I kept relaunching manually on my two laptops and it sort of worked most of the time. I was worried because of the low data transfer speed (1 to 1.5MB/s seemed to be the upper limit, with many transfer under 700KB/s).#@#

none

如果双方都查看时间,并等到给定的一秒到来呢? 那么它们实际上会在同一时间开始... 但如果它们的时钟不同步呢?

解决办法是从互联网时钟中获取准确时间。 谷歌提供了大量 C# 实现,我只用了一个来自 StackOverflow.

用户输入对方的对等 IP:端口对后,程序会检索互联网时间,并等待一分钟中的某一秒到来。 比如等待 0、10、20、30、40、50 秒后再开始同步连接。

它成功了! 我在局域网/VPN 设置上进行了测试,还测试了通过远程桌面访问 VPN 上的远程机器,结果正常!

#@#Later I ran tests with two different "real users" and while it wasn't perfect, most of the time you could enter the other peer and hit enter without having to "Slack-synchronize" and it worked fine.#@#

ssr:

一旦我成功了,我就创建了一个 GitHub repo 来共享代码,包括我开发它的全部历史、办理登机手续(不用说,我其实是用 Plastic 开发的,只是推送到了 GitHub :P)。

但我最担心的是数据传输速度。

我向办公室发送了著名的 17GB VmWare 映像,数据传输速度始终保持在 800KB/s 左右,只是偶尔会达到 1MB/s。

速度很慢。

然后,我开始重新阅读和研究 UDT 选项,但没有成功。 任何组合似乎都无法加快数据传输。

因此,我想我必须找到一种更好的方法来发送数据,我决定测试并行数据传输:如果我将文件分成两部分(或更多部分),并尝试通过并行发送片段来更好地利用可用带宽,会怎么样?

我在分支上做了一些测试主控多线程none

ssr:

然后,我编写了一个使用纯 TCP 发送/接收数据的选项,以便在局域网上进行测试。 这与 P2P 无关,只是为了测量和比较数据传输。

none

ssr:

然后,我在局域网上测试了真正的 UDT 会合(毕竟是 NAT 打洞),以比较普通 TCP 和 UDT 的结果:

tcp

#@#p2pcopy.exe sender --tcp --tcpremotepeer 192.168.1.39:7070 --file C:\Users\pablo\Downloads183u.tif Connected to 192.168.1.39:7070 -[###################################] 181.64 MB / 181.64 MB. 2.3 MB/s#@#

udt

#@#p2pcopy.exe sender --localport 4300 --file C:\Users\pablo\Downloads183u.tif Using local port: 4300 Your firewall is FullCone Tell this to your peer: 88.41.37.87:4300 Enter the ip:port of your peer: 192.168.1.39:21300 Your firewall is FullCone [18:35:52] - Waiting 8 sec to sync with other peer Your firewall is FullCone 0 - Trying to connect to 192.168.1.39:21300. Connected successfully to 192.168.1.39:21300 -[#################################] 181.64 MB / 181.64 MB. 1.75 MB/s#@#

UDT: 1.75MB/s 与技术合作计划(TCP:2.3MB/s(我必须打开端口进行 TCP 测试)。 有差别,但不是很大!

请注意,在 UDT 模式下(不带 --tcp 标志),我输入的是本地 IP 地址,而忽略了公共 IP 地址。

有趣的发现您可以使用 NAT 打洞穿越局域网上的每台计算机的防火墙。 这一点非常有趣,因为在局域网上,你受到自己防火墙的保护,但在这里,NAT 打洞也能起作用。 因此,更好的基于 P2P 的 Plastic Tube 可以检测两个对等设备是否有相同的公网 IP(它们在同一个局域网上),而不是向公网 IP 打洞(这确实行不通),只需使用专用地址即可。

none

事实上,Wi-Fi 问题让我开始研究 PeerFinder,因为我分享了这里.

ssr:

在看到包括多线程数据传输在内的 perf 结果后,我认为 UDT 可能存在问题,而普通 TCP 可能会做得更好。

于是,我试着让 TCP 打孔机工作。

理论上说,你必须做到以下几点:

  • 每个同行启动 2 个线程。
  • 一个线程尝试连接另一个对等节点。
  • 另一条线聆听。
  • 两个线程都创建了套接字,但它们利用地址重用功能绑定到同一个本地端口。

后来我读到,其实根本不需要 "accept 部分",事实上,在我的所有测试中,我从未看到过 accept 起作用。

我开始在局域网上进行测试,结果成功了:除非禁用笔记本电脑上的防火墙,否则简单的 tcp 无法正常工作(连接/接受,无打孔,原始代码),而我的 tcp 打孔代码却能正常工作! 连接立即建立并发送了数据。

使用 --tcpholepunch 的示例会话如下:

p2pcopy\bin\Debug\p2pcopy.exe sender --tcpholepunch --localport 7070 --tcpremotepeer 192.168.3.35:7070 --file PeerFinder.exe Running tcp hole punch Trying to connect Connector correctly connected \[############################################################] 10.5 KB / 10.5 KB.

在这个测试中,每个对等程序都会事先设置其本地端口和远程 IP:端口,我从未执行过交换部分,因为我没有使用 STUN 来处理 TCP(事实上,代码只是针对 UDP)。

在最初的局域网成功后,我在 VPN 上进行了测试。 没有成功。 我看到其中一个对等体正在连接,但另一个总是失败。

后来,我用我的一位同事从他家连接进行了测试......结果也不行。 我又用办公室的另一个同事进行了测试,结果也一样。

我可能弄错了,但在本地网络之外,tcp 打孔不够可靠。

有趣的发现none.

ssr:

与 TCP 相比,UDP 打孔似乎更有可能奏效,这一点我已经亲眼目睹了。 可以找到一些很好的解释,其中提到 SYN 数据包和 TCP 是如何建立的等等。

但从根本上说,这意味着在互联网上,你最好坚持使用 UDP,这意味着你需要在上面建立一些可靠性层,比如 UDT。

nonenonenone

ssr:

ssr:

由于 P2P 是现代网络应用程序的优势,我开始阅读一些资料,了解它们是如何做到这一点的。

WebRTC 就是他们都在使用的技术。 它能在大多数现代浏览器上用 JavaScript 轻松实现视频会议和音频。

nonenone用于双向点对点任意数据传输。

我曾尝试用 C# 来实现 WebRTC,但没有找到。 使用 WebRTC,以真正的 P2P 方式实现 Tube 将非常简单,因为该库可以处理打孔、决定是否需要通过中继、解决两个节点是否在同一局域网上的问题等等。

我一直在搜索,但除了 XSockets(一种用于实时通信的商业产品)之外,我没有找到任何适用于 C# 的东西,但我不清楚它们是否能完成整个 RTC 的工作。

后来,我发现可以通过在表单上嵌入浏览器或其他东西来实现 WebRTC,并实现自动化,但这看起来像是矫枉过正。

ssr:

更多的阅读让我找到了 libjingle(同样,因为我觉得我以前已经读过关于它的文章)。 这是一个由 Google 开发的库,用于简化 P2P 应用程序的开发。

而且,WebRTC 似乎完全是在 libjingle 的基础上构建的(我的意思是,你可以找到这样的包含 #include"webrtc/p2p/base/pseudotcp.h";代码上.

它使用 ICE、TURN、STUN、XMPP-or-something 等协议以可靠的方式创建连接。 似乎 92% 的时间可以直接实现 P2P,只有 8% 的时间需要中继。 这似乎是他们用于 Google Hangouts 的协议(不确定他们是否还在使用)。

none

ssr:

我的问题是:这些人是如何实现 TCP 点对点连接的?

我以为是这样,因为我试过 从家里连接到办公室,速度达到 2MB/s,而 p2pcopy 只有 1.2MB/s 左右。 不知为什么,它们的速度更快,我想知道为什么。

我一直在阅读,但没有找到很好的答案,直到浏览代码时我发现了一些关于 pseudotcp 的内容。 起初我以为这只是一个选项,但后来我发现了这个:none

none可以通过防火墙发送类似 TCP 的数据包。 通常,通过 NAT 建立 UDP 连接比建立 TCP 连接更容易。 因此,我们提供了 PseudoTcpChannel,使 UDP 数据包具有类似 TCP 的功能。 建立连接时,每个 FileShareSession 对象都会创建自己的 PseudoTcpChannel 对象。 FileShareSession 对象在建立连接时会创建自己的 PseudoTcpChannel 对象,它通过调用传入其构造函数的会话对象上的 Session::CreateChannel 来创建 TransportChannel,从而提供外部数据连接。 它暴露了一个 StreamInterface,供内部组件读/写数据到远程计算机。 在文件共享应用程序中,PseudoTcpChannel 充当通道与 HttpServer 或 HttpClient 之间的中介,通过伪 TCP 层封装或拆封数据。 当 FileShareSession 的关联会话对象接收到带有 QN_SHARE_CHANNEL 成员的 XML 信息节时,FileShareSession 就会创建 PseudoTcpChannel。

那么,归根结底,他们是在像我一样进行 UDP 打洞,只不过他们把 pseudotcp 放在了 UDT 的上面,而不是 UDT。 所以,也许 pseudotcp 比 UDT 更有效率!

none可在此阅读.

none

我发现了一个关于 libjingle 的有趣主题,甚至还有一个可能的 C# 移植.

ssr:

我开始寻找有关 pseudotcp 的信息,结果发现了 libnice。 这是另一个 P2P 库,他们似乎从 Google 复制了 pseudotcp 代码,并在最近进行了改进。 我找到了一篇关于它的文章:

最后,在 libnice' 的伪 TCP 实现中添加了 FIN/ACK 支持。 该代码最初基于 Google 的 libjingle 伪 TCP,通过在 UDP 中封装类似 TCP 的数据包,在 UDP 上建立可靠的连接。 它实现了 TCP 的基本功能,但像关闭 FIN/ACK 握手这样的功能则留给了更高级别的协议。 这对 Google 来说没问题,但对我们的用例却不合适,因此我们增加了这方面的支持。 此外,我们还需要使用 GTlsConnection 在伪 TCP 连接上分层 TLS,这就需要实现半双工关闭支持,并修复 GTlsConnection 中一些令人讨厌的漏洞。

libnice 在 C# 中也没有封装或任何东西,不过我读到曾经有一个 GTK# 应用程序在 C# 中使用 DBus 来使用它。这里他们提到了 Chatter、Telephathy GUI 和 Telephathy 是另一种 P2P 技术。 我还在一个讨论区但没有找到任何代码。

libnice pseudotcp 代码采用 C 语言而非 C++,可在此处找到:

ssr:

您可以从 GitHub 获取源代码还有一个提供二进制版本以备不时之需 :-P

ssr:

我想试试这个想法,看看使用 pseudotcp 代替 UDT 如何提高数据传输速度。

ssr:

我承认我喜欢所有与网络编程相关的东西。 虽然我不是什么专家,但我确实乐在其中。

#@#My motivation with all this P2P thing, though, is to add real peer-to-peer connectivity to our Plastic Tube feature. Right now, as I mentioned, all traffic goes through a relay. We don't cache any data at all, but obviously it would be more effective both in cost and transfer speed if it used true P2P. Unlike p2pcopy, the Tube uses a server to negotiate the connection and to serve as "directory service" so you can easily reach remote repositories by email like this:#@#your_repo@tube:robin@batman.com这非常方便。

ssr:

  1. ssr:
  2. ssr:

    下面是几个可以与 c# 一起使用的 webrtc 栈



    回复删除
  3. ssr:

    我注意到 Github 已经 3 个月没有更新了。 成功率为 50%,最大速度约为 1 MB/秒,发送大文件时会中途崩溃。

    回复删除
    答复
    1. ssr:

      谢谢您的分享!

      是的,我们的速度比 1MB/s 多一点,但也不是太多。 我不得不说,Reep.io 的传输速率并不高。

      我的目标是在我们的主要产品 Plastic SCM 中使用这些代码进行 P2P 操作。

      为了改进 perf,我们应该试试伪 tcp,看看效果如何。

      关于 50%的成功率:嗯......是的,在路由器上开孔有时需要不止一次尝试。 您可以做的一件事是,在一次成功后的下一次数据传输中指定端口。

      真正的改进方法是使用中央服务器作为会合点,但这样就失去了这一想法的部分美感。

      关于崩溃:没有发现任何崩溃。 你是指发送大文件时连接中断吗? 如果能实现重试就太好了。

      关于项目活动: I'm open to receive contributions? 加入重试怎么样?) 想做吗?

      谢谢!

      巴勃罗

      删除
  4. ssr:

    有趣的阅读! 你有没有试过在对称 NAT 后面的任一或两个对等网络中使用你的代码? 考虑到整个端口地址转换问题,这似乎行不通。

    回复删除
    答复
    1. ssr:

      既然您交换的是外部端口,它就应该能正常工作。 我经常用它与队友交换大文件,大多数时候似乎都能正常工作 :-)

      删除

shadowsock 节点购买登录国外网站的加速器手机外网梯子现在国内上instagram加速软件蚂蚁免费外网加速器
好用的免费游戏加速器蚂蚁官网加速器安卓版下载坚果加速器app下载蘑菇加速器appsurf加速器安卓下载游戏加快倍数的加速器腾讯迅游手游加速器xbox免费加速器英雄联盟手游国际服加速器灵能加速器pubglite加速器帆游加速器手机版奇妙加速器为什么加速失败传奇通用加速器手机加速器推荐海外永久免费加速器plex加速器ios798加速器官网手机版SUB加速器华硕路由器ssr插件ssr:小火箭ssrssr搭建服务器教程ssr节点订阅心阶ssr中文官网小小机场ssr官网ssr推荐yunssr稳定下载ssr免费机场免费ssr节点获取ssr原理ssr使用日本ssrssr安卓客户端下载ssr节点长期免费更新比较好的付费ssr节点最新ssr免费节点ssr小火箭