select()在一个简单的自制p2p程序中的问题,以交换" musicdata"用udp

时间:2015-01-07 21:26:21

标签: c++ c select udp p2p

heyho,

我正在尝试创建一个简单的p2p程序,它应该能够让至少3个对等体通过端口50001-50010交换每个对等体存储在1个文件中的musicdata(作者/标题)。直言不讳地说它是家庭作业,我们从来没有真正谈论过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 socket\n";
            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 again\n";
            break;
        }
        std::cout << "Searching for other musicdata owners\n";
        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;

这些功能都经过测试并按预期工作。

(在一个sitenote上,我有点不规则,让我有点吃惊: 当我运行所有3个客户端并且第一个获取他每次获得的所有数据同一行缺少正好3个字符---每次再次---我从一台PC运行程序并且无法完全理解,为什么这种情况每次都会发生(我想我应该添加一个开头和一个endign来消除这个问题,但事实上,同样的线路每次都会让我着迷)。那个现象有解释吗?)

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

不是检查读取集中的哪个套接字接收数据,而是直接在recvfd描述符上调用recvfrom。你需要循环检查所有这些。

这是我可以快速回顾的内容。

但是here是我很久以前写的基于tcp的例子。你的是udp,但你应该能够轻松找到问题的根源。

P.S。代码中有一个错误,有人在帖子的评论中指出并修复了这个错误。