繁体   English   中英

C ++ Winsock P2P

[英]C++ Winsock P2P

脚本

有没有人在使用Winsock的C ++中有任何良好的点对点(p2p)网络示例? 对于特别需要使用这种技术的客户来说,这是一个要求(天知道为什么)。 我需要确定这是否可行。

任何帮助将不胜感激。

编辑

我想避免使用库,这样我就可以理解底层的源代码并进一步了解我的知识。

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

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

有了它,让我们开始:

注意事项:

阻止或非阻塞

首先,您需要确定是否需要阻止或非阻塞程序。 最大的区别是,如果你有一个GUI,你需要使用非阻塞或线程,以免冻结程序。 我做的方式,它是使用阻塞调用,但总是调用select调用(在某些后来更多),该闭锁功能之前。 这样我就可以避免使用线程和互斥锁等但仍然使用基本的acceptsendreceive调用。

您不能依赖于您的包裹将以您发送的方式到达!

你对此也没有影响。 这是我遇到的最大问题,主要是因为网卡可以决定发送什么信息以及何时发送它。 我解决它的方法是创建一个networkPackageStruct ,其中包含sizedata ,其中size是该包中数据的总量。 请注意,您发送的邮件可以拆分为2条或更多邮件,也可以与您发送的其他邮件合并。

请考虑以下事项:您发送两条消息

"Hello"
"World!"

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

"Hel"
"loWorld!"

也许

"HelloWorld!"

无论底层网络是什么感觉..

记录(几乎)一切!

调试网络程序很难,因为你没有完全控制它(因为它在两台计算机上)。 如果你遇到阻塞操作,你也看不到它。 这也可以称为“了解你的阻止代码”。当一方发送的东西你不知道它是否会到达另一方时,所以要跟踪发送的内容和收到的内容。

注意套接字错误

winsock函数返回很多信息。 知道你的WSAGetLastError()函数。 我将不会在下面的示例中保留它,但请注意它们往往会返回大量信息。 每次获得SOCKET_ERRORINVALID_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很棒 - 它实际上让你的套接字监听所有网络,而不只是一个ipaddress。

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

这是有趣的部分。 bindlisten不会阻止但accept意志。 诀窍是使用select来检查是否有传入连接。 所以上面的代码就是设置套接字。 在程序循环中,检查socket中的新数据。

交换数据

我解决它的方法是使用select alot。 基本上你可以看到你的套接字上是否有任何需要回应的东西。 这是通过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

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将使您的peer select触发器。 然而recv将不会收到任何数据,但会返回0.我没有注意到recv返回0的任何其他情况,因此(有些)可以安全地说这可以被视为关闭代码。 调用shutdown是最好的事情..
  • 在不调用关机的情况下关闭连接只是冷酷无情,但当然有效。 即使您使用shutdown ,仍然需要处理错误,因为它可能不是您的程序关闭连接。 要记住的好错误代码是10054,即WSAECONNRESET:由对等方重置连接。

如果您只想在Microsoft Windows上实现P2P应用程序,可以尝试使用Windows对等网络

如果您想实现自己的新P2P协议,可以学习eMule协议和eMule源代码 如果你查看Shareaza源代码 ,你可以做更多,它做eMule / Guntella / Gnutella / BitTorrent。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM