Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.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
select()之后的FD_ISSET()未检测到接收到的数据_C_Linux_Sockets - Fatal编程技术网

select()之后的FD_ISSET()未检测到接收到的数据

select()之后的FD_ISSET()未检测到接收到的数据,c,linux,sockets,C,Linux,Sockets,我有一个程序,我设计在一堆不同的节点上运行,根据它们从主节点上运行的进程中得到的指令在它们之间传输文件。每个进程同时充当发送方和接收方 我的策略是: //Setup a listener socket on port 63000(say) to listen to commands from the master //socket. This listener will only listen for commands and read these commands /* 1) Set

我有一个程序,我设计在一堆不同的节点上运行,根据它们从主节点上运行的进程中得到的指令在它们之间传输文件。每个进程同时充当发送方和接收方

我的策略是:

//Setup a listener socket on port 63000(say) to listen to commands from the master    
//socket. This listener will only listen for commands and read these commands

/* 1) Setup a listener socket on port 63001(say) to listen to connection requests from 
   (NUMNODES-1) other processes on the rest of the nodes
   2) Accept each of the connections from the rest of the (NUMNODES-1) nodes and fill  
   these conneced descriptors into an array of integers  */

for(i=1;i<NUMNODES;i++){
   connfd=accept(...,&node_addr,...);
   index=findNodeIndex(node_addr); //To find the node number, corresp to this address
   connections[index]=connfd; 
}

/* Skipping all details aside, assuming i have a process running on node number 4 (out  
   of a total of 10 nodes, say) connections[4] will be -1, and connections[1..3, 5..10] 
   will hold connection descriptors to each of the other nodes, ready to read any file 
   that they decide to transfer */

fd_set read_set;
for(i=1;i<=NUMNODES;i++){
    if(i==thisNodeNum())   //For nodenum 4, the connections[4] will be -1
        continue;          //So we don't want to put it into the read fd_set

     FD_SET(connections[i],&read_set);
}

fd_set temp_rset;

//A select() call ready to listen to any data that comes in from any of the nodes
for(;;){
    temp_rset=read_set;
    select(maxfdp1,&temp_rset,NULL,NULL,NULL);

    //Listening for commands from master goes here
    if(FD_ISSET(commandListener,&temp_rset){
        ... listen to command and send file to a particular node...
        ... File will be sent to port 63001 on that node...
        ... commandLIstener listens for commands on port 63000(just a reminder)...
    }

    //Listening for data that has come in from the other nodes
    for(i=1;i<=NUMNODES;i++){
        if(FD_ISSET(connections[i],&temp_rset){
            ... write file to the local hard disk, byte by byte...
        }
    }//End of connections[1..NUMNODES] testing for data to read

}//End of infinite for loop
我的问题是,我的主机在端口号63001上向它喜欢的任何节点发送命令,然后接收并执行该命令。文件被逐字节发送到相应的节点,例如,主节点命令节点5将文件发送到节点9。。节点5上的进程将利用连接[9]将文件发送到节点9上的进程。。。节点9上的进程将接收连接[5]上的数据。。。至少这是我想要的

将文件发送到正确节点9@port 63001上的相应端口, 但是节点9上的FD_ISSETconnections[i]、&temp_rset条件从未检测到任何发送的数据。我已经使用tshark和tcpdump进行了检查,数据确实会被发送到节点9,但是select调用从未接收到任何内容


我做错了什么

您的代码应该如下所示:

fd_set read_set; // set of file descriptors (in this case sockets)
int result;

for(;;)
{
    FD_ZERO(&read_set); // you need to clear the set first!
    FD_SET(commandListener, &read_set); // add command socket to the set 
    for(i=1; i<=NUMNODES; i++) // add node sockets to the set
    {
        if(i==thisNodeNum()) continue;
        FD_SET(connections[i], &read_set);
    }

    // check status of all sockets from the set
    result = select(maxfdp1, &read_set, NULL, NULL, NULL); // instead of tracking maxfdp1 you can use FD_SETSIZE (maximum allowed size of set)

    if(result == -1) // error
    {
        perror("select() error");
    }
    else if(result > 0) // there is new data
    {
        if(FD_ISSET(commandListener, &read_set) // there is new command data
        {
            // (...) handling your tasks here
        }

        for(i=1; i<=NUMNODES; i++) 
        {
            if(FD_ISSET(connections[i], &read_set) // there is new data on i-th node 
            {
                // (...) handling your tasks here
            }
        }
    }

}//End of infinite for loop
注:

您忘记了清除和重建代码中的文件描述符套接字集。select修改了它-请注意,稍后您将使用FD_ISSET检查它

您可以将所有套接字放在一个集合中,并使用select一次检查所有套接字,然后确定哪些套接字具有新数据(如果有的话)

我不确定如何索引表连接,因为代码中的循环是1..NUMNODES,而不是0..NUMNODES-1的自然C/C++表索引


您的accept循环接受来自NUMNODES-1其他节点的连接。因此,如果所有节点都运行此代码,这意味着所有节点都必须连接到其他节点。这意味着您将在每对节点之间建立两个连接,从每个方向启动一个连接


现在,当您为select循环设置read_set时,看起来您只查看已接受的连接,而不是调用connect的连接。如果您同时在已接受的连接而不是已连接的连接上发送数据,则另一端的进程不会注意到它,因为它正在等待其已接受的连接而不是已连接的连接。

您必须在每次调用之前重新设置fd_集,以便在循环中进行选择-请参阅@ChrisStratton:OP的代码就是这样做的。参见:临时设置=读取设置;对不起,我错过了。如果能弄清楚select是否返回,如果是的话,找出它在没有提供超时的情况下返回的原因,也许会有帮助。返回值是多少?是否表示应检查errno?对于i=1;i> fori=0;i