1

ノンブロッキング接続を実行し、選択を実行して、ソケットが書き込み可能か例外中かを確認することで、ネットワーク上のホストを確認しようとしています。ポート 80,139 経由でソケット接続を確立しようとしています。ホストソケットが接続後に書き込み可能である場合、またはホストが RST パケットを送信したときにソケットが例外になった場合に検出可能になります。

Windows ソケットを使用してコードを記述し、ロジックは正常に機能しましたが、Linux ソケットを使用すると、プログラムは目的の結果を与えません。選択関数は、その IP にホストがなくても、特定の IP アドレスに対して 1 を返します。 Winsock のケースでタイムアウトになり、0 が返されました。以下のコードを書きました。問題の正確な場所を教えてください。

#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

int port[]={80,139};

void Free(int Sock_Arr[])
{
    for(int i=0;i<2;i++)
    {
        close(Sock_Arr[i]);
    }
    return ;
}

int  main()
{
    int Socket[2],result=0; //Socket array
    struct sockaddr_in service;


    fd_set writefds;
    fd_set exceptfds;


    struct timeval timer;
    timer.tv_sec=5;

    timer.tv_usec=0;

    int flag=0;

    FD_ZERO(&writefds);
    FD_ZERO(&exceptfds);


    char Ip_Addr[20];
    for(int i=0;i<2;i++)
    {
        if((Socket[i]=socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0)
        {
             Free(Socket);
        }
        fcntl(Socket[i],F_SETFL,O_NONBLOCK);



    }

    bzero(&service, sizeof(sockaddr_in));

    printf("Enter the ip-address : ");
    scanf("%s",Ip_Addr);



    service.sin_family=AF_INET;
    service.sin_addr.s_addr=inet_addr(Ip_Addr);



    for(int i=0;i<2;i++)
    {


        FD_SET(Socket[i],&writefds);
        FD_SET(Socket[i],&exceptfds);
        service.sin_port=htons((unsigned short int )port[i]);
        connect(Socket[i],(struct sockaddr *)&service,sizeof(sockaddr_in));



        result= select(Socket[i]+1,NULL,&writefds,&exceptfds,&timer);

        if(result<0||result==0)
        {
                flag=0;
                printf("\n The machine could not be found on the port %d ",port[i]);
                printf("result : %d",result);
                perror("select");

        }
        else
        {

                printf("\n The machine could  be found on the port %d ",port[i]);
                flag=1;
                printf("result : %d",result);

                if(FD_ISSET(Socket[i],&writefds))
                {
                    printf("The socket triggered on write on port %d",port[i]);
                }

                else if(FD_ISSET(Socket[i],&exceptfds))
                {
                    printf("The socket triggered on except on port %d",port[i]);
                }
                else
                {
                    printf("No socket triggered on %d",port[i]);
                }

        }

        FD_ZERO(&writefds);
        FD_ZERO(&exceptfds);



    }

    Free(Socket);

    if(flag==1)
    {
        return 1;
    }
    else
    {
        return 0;
    }



}
4

1 に答える 1

1

ここ

result= select(Socket[i],NULL,&writefds,&exceptfds,&timer);

への最初の引数は、select必要な最大のファイル記述子select()+ 1 である必要があります。l だけなので、1 を追加していないため、問題が発生する可能性があります。試す

result= select(Socket[i]+1,NULL,&writefds,&exceptfds,&timer);

実際にはソケットにループを持たず、すべてのソケット ファイル記述子を fd_sets に追加し、最大のファイル記述子を計算し、すべての非ブロッキングconnect呼び出しを実行してから、select 呼び出しを 1 回だけ使用してソケット アクティビティを確認する方がよいでしょう。それらのいずれか (選択する最初の引数として最大のファイル記述子 +1 を使用)。次に、select()正の値が返された場合は、トリガーのFD_ISSET原因となったソケットを特定するために使用できます。このようにして、一度に多くのソケットのアクティビティを探すselect()ことができます。select()これは、複数のソケットでアクティビティをリッスンしているときに行う方法です。

少なくとも、呼び出しを実行する 2 番目のループを反復するたびに fd_set をクリアする必要があります。これはconnect()、前の反復で追加したソケット fds を削除していないため、他のソケットでのアクティビティを探している可能性があるためです。現在追加されているものへの追加。

また、これを行っている方法で行うと、select()呼び出しに送信するタイムアウト値がリセットされません。マニュアルページから、タイムアウト値を変更する可能性がselectあることが明確に述べられています。したがって、この場合、後続の反復呼び出しによってタイムアウトが短縮され、反復ごとにタイムアウトを 5 秒にリセットしようとする可能性があります。タイムアウトが大幅に短縮されてゼロになった場合、select() 呼び出しは即座に戻ります (ポーリング)。select select

于 2013-10-11T09:06:12.617 に答える