heyho,
我正在尝试制作一个简单的 P2P 程序,它应该能够让至少 3 个对等体通过端口 50001-50010 交换存储在每个对等体 1 个文件中的音乐数据(作者/标题)。 坦率地说,这是家庭作业,我们从未真正谈论过P2P,也没有找到任何有用且简单的P2P示例,而无需特殊库等。 通过 Beej 的网络编程指南和其他一些资源,我已经走了一半工作程序,但我有一个大问题:
我的选择调用是针对整个循环的,每次 1 对于所有其他客户端/对等体,它只是 0,因此它们永远不会收到任何数据
我的P2P代码:
case 6:
{
if(!filename.empty())
{
time_t start, now;
time(&start);
double elapsedtime = 0;
char *recvbuf;
char *sendbuf;
recvbuf = new char[1024];
sendbuf = new char[1024];
int recvfd, sendfd,err, port;
int errormarker = 0;
if((recvfd = socket(AF_INET,SOCK_DGRAM,0)) == -1)
{
std::cout << "Error setting socketn";
errormarker =1;
}
if(errormarker ==1)
break;
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = INADDR_ANY;
server_address.sin_port = htons(50001);
for (int i =0; i<=9;i++)
{
port = 50001+i;
errormarker = bind(recvfd,(sockaddr*) &server_address, sizeof (server_address));
if(errormarker ==-1)
server_address.sin_port = htons(server_address.sin_port+1);
else
break;
}
if(errormarker == -1)
{
std::cout << "all ports are used, please wait a minute and try againn";
break;
}
std::cout << "Searching for other musicdata ownersn";
fd_set readset;
while (elapsedtime < 15)
{
if(errormarker != 0)
break;
memset(recvbuf, 0, sizeof(recvbuf));
memset(sendbuf, 0, sizeof(sendbuf));
struct timeval tv;
tv.tv_sec =0;
tv.tv_usec = rnd(10000,50000);
FD_ZERO(&readset);
FD_SET(recvfd, &readset);
int result = select(recvfd + 1, &readset, NULL, NULL, &tv);
std::cout << result << "n";
if (result >0)
{
result = recvfrom(recvfd, recvbuf, 1024, NULL,NULL,NULL);
if (result != -1)
{
buftofile(recvbuf,filename);
addnewdata(filename);
}
else
std::cout << "error receiving data n";
}
filetobuf(sendbuf,filename);
for(int i = 50001; i<=50010;i++)
{
struct addrinfo hints, *servinfo, *p;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype =SOCK_DGRAM;
std::string s_port = to_string(i);
err = getaddrinfo(NULL,s_port.c_str(),&hints,&servinfo);
for(p=servinfo;p!=NULL;p=p->ai_next)
{
if(i == port)
{
err = sendto(recvfd, sendbuf,strlen(sendbuf), 0, p->ai_addr,p->ai_addrlen);
continue;
}
if((sendfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1)
{
continue;
}
else
{
err=sendto(sendfd,sendbuf,strlen(sendbuf), 0, p->ai_addr,p->ai_addrlen);
close(sendfd);
}
}
freeaddrinfo(servinfo);
}
time(&now);
elapsedtime=difftime(now,start);
}
close(recvfd);
}
else
std::cout << "Error, please choose a file to save your data first!" << std::endl;
}
break;
这些功能都经过测试并正常工作。
(在网站上,我得到了一点不规则,让我有点吃惊:当我运行所有 3 个客户端并且第一个客户端每次都在同一行缺少正好 3 个字符时获得他获得的所有数据 --- 每次--- 我从一台 PC 运行程序并且无法完全理解,为什么每次都会发生这种情况(我想我应该添加一个开始和一个结束符号来解决问题, 但事实上,每次都出现同一条线让我着迷)。对这种现象有解释吗?
提前感谢您的帮助。
您不是检查读取集中的哪个套接字接收了数据,而是直接在 recvfd 描述符上调用 recvfrom。您需要循环检查所有这些。
这是我可以在快速回顾中收集的内容。
但这是我很久以前写的一个基于 tcp 的示例。您的是udp,但您应该能够轻松找到问题的根源。
附言代码中有一个错误,有人指出并在帖子的评论中修复了这个错误。