Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
了解用于接收UDP消息和打开TCP套接字的Select循环_C_Sockets_Networking_Tcp_Udp - Fatal编程技术网

了解用于接收UDP消息和打开TCP套接字的Select循环

了解用于接收UDP消息和打开TCP套接字的Select循环,c,sockets,networking,tcp,udp,C,Sockets,Networking,Tcp,Udp,嗨,我在为一个网络类做一个项目,我们在网络中创建节点,通过udp接收来自控制应用程序的消息,然后创建与其他节点的tcp连接。基本顺序如下:1)控制管理器向节点A发送udp消息,告知其连接到节点B 2)节点A接收udp消息并将udp消息转发到节点B 3)节点B接收udp消息,随机选择端口号,在该端口上打开侦听tcp套接字,并将udp消息发送回a,端口号为4)节点a接收udp消息并在该tcp端口上打开与节点B的连接 基本上,我想循环接收到的udp消息并跳转到我的消息解析函数,同时循环tcp连接。这一

嗨,我在为一个网络类做一个项目,我们在网络中创建节点,通过udp接收来自控制应用程序的消息,然后创建与其他节点的tcp连接。基本顺序如下:1)控制管理器向节点A发送udp消息,告知其连接到节点B 2)节点A接收udp消息并将udp消息转发到节点B 3)节点B接收udp消息,随机选择端口号,在该端口上打开侦听tcp套接字,并将udp消息发送回a,端口号为4)节点a接收udp消息并在该tcp端口上打开与节点B的连接

基本上,我想循环接收到的udp消息并跳转到我的消息解析函数,同时循环tcp连接。这一部分看起来很简单,但我不太明白如何将侦听套接字添加到文件描述符列表中。下面的代码是我编写的,我想知道基本结构是否正确?我真的不明白如何创建侦听tcp套接字并将其添加到fd列表

SOCKET udpsock;
udpsock = initudp(port); //setup udp socket
SOCKET tcpsock;
FD_ZERO(&rdsocks);

max = udpsock + 1;
while(1)
{
    SOCKET temp;

    FD_SET(udpsock,&rdsocks);//setup udp macros
    FD_SET(tcpsock,&rdsocks);

    if( select(max,&rdsocks,NULL,NULL,NULL) == SOCKET_ERROR )
    {
        perror("Select error");
        WSACleanup();
        return 1;
    }
    for(temp = 0; temp<=max;temp++) // loop on TCP sockets
    {
        if(FD_ISSET(temp,&rdsocks))
        {
            printf("Socket %d is ready \n",temp);
            // process tcp messages
        }

    }
    if(FD_ISSET(udpsock,&rdsocks)) // udp connection, parse control message
    {
        int ret = 0;
        res = recvfrom(udpsock, buff,sizeof(buff),0,(struct sockaddr*)&udpclient,lenaddr);
        //process udp message, setup tcp connection here if requested and add to file descriptor list?
    }

}
SOCKET-udpsock;
udpsock=initudp(端口)//设置udp套接字
插座;
FD_零(&rdsocks);
max=udpsock+1;
而(1)
{
插座温度;
FD_SET(udpsock,&rdsocks);//设置udp宏
FD_套件(tcpsock和rdsocks);
if(选择(max,&rdsocks,NULL,NULL)=SOCKET\u错误)
{
perror(“选择错误”);
WSACleanup();
返回1;
}

对于(temp=0;temp,创建侦听TCP套接字(,)后,将其标记为非阻塞,并将其添加到的读取集

当它变为“可读”时,意味着您的客户端连接处于挂起状态,请调用。将新连接的套接字也添加到读取集

您可能希望保留这些客户机套接字的列表/哈希/任何内容,因为在每次调用和计算其第一个参数(max fd)之前,必须重新初始化读取集

注0:我在这里参考Linux手册页面,但逻辑基本上是跨平台的。您可以在上找到Windows参考。
注1:Windows忽略其第一个参数。

在调用
FD\u SET()
select()之前,需要在每次循环迭代中调用
FD\u ZERO()
。此外,在尝试首先连接TCP套接字之前,不要将其添加到
fd\u集。
请保留您创建的TCP套接字列表,以便在每次循环迭代时将其重新添加到
fd\u集

试着这样做:

udpsock = initudp(port); //setup udp socket

std::vector<SOCKET> tcpsocks;
SOCKET tcpsock;

while(1)
{
    FD_ZERO(&rdsocks);
    FD_SET(udpsock, &rdsocks);
    max = udpsock;

    for(size_t i = 0; i < tcpsocks.size(); ++i)
    {
        tcpsock = tcpsocks[i];
        FD_SET(tcpsock, &rdsocks);

        if( tcpsock > udpsock )
            max = tcpsock;
    }

    if( select(max+1, &rdsocks, NULL, NULL, NULL) == SOCKET_ERROR )
    {
        perror("Select error");
        WSACleanup();
        return 1;
    }

    for(size_t i = 0; i < tcpsocks.size(); ++i) // loop on TCP sockets
    {
        tcpsock = tcpsocks[i];            
        if( FD_ISSET(tcpsock, &rdsocks) )
        {
            printf("Socket %d is ready \n", tcpsock);
            // process tcp message
        }
    }

    if( FD_ISSET(udpsock, &rdsocks) )
    {
        int ret = 0;
        res = recvfrom(udpsock, buff, sizeof(buff), 0, (struct sockaddr*)&udpclient, lenaddr);
        // process udp message...
        if( setup tcp connection is requested )
        {
            tcpsock = ...;
            if( tcpsock != INVALID_SOCKET )
                tcpsocks.push_back(tcpsock);
        }
    }
}
udpsock=initudp(端口);//设置udp套接字
std::向量tcpsocks;
插座;
而(1)
{
FD_零(&rdsocks);
FD_套件(udpsock和rdsocks);
max=udpsock;
对于(size_t i=0;iudpsock)
max=tcpsock;
}
if(选择(max+1,&rdsocks,NULL,NULL)=SOCKET\u错误)
{
perror(“选择错误”);
WSACleanup();
返回1;
}
对于TCP套接字上的(size_t i=0;i