2

このスレッドから得た回答に基づいて、私はこれを作成しました:

    //Server 

    sock_init(); //from SFL, see http://legacy.imatix.com/html/sfl/

    timeout = 50000;

    serv_sock_input[0] = TCP(1234); 
    serv_sock_input[1] = UDP(9876);

    input_protocols[0] = "tcp";
    input_protocols[1] = "udp";

    while (1)
    {
        FD_ZERO(&sock_set);
        for (x = 0; x<number_of_inputs; x++)
        {
            FD_SET(serv_sock_input[x], &sock_set);
        }

        select_timeout.tv_sec = timeout;
        select_timeout.tv_usec = 0;

        if (select(0, &sock_set, NULL, NULL, &select_timeout) == 0)
            printf("No requests");
        else
        {
            for (x = 0; x<number_of_inputs; x++)
            {
                if (FD_ISSET(serv_sock_input[x],&sock_set))
                {
                    printf("\nRequest on port %d: \n", x);
                    if ((strcmp(input_protocols[x],"tcp")) == 0) //in this case, 0 returned == TRUE
                    {
                        accept_socket(serv_sock_input[x]);
                        printf("Input TCP Port %d\n",x);
                        close_socket(serv_sock_input[x]);
                    }
                    else
                    {
                        printf("Input UDP Port %d\n",x);
                    }
                }
            }
        }
    }
    sock_term();
}

int TCP (unsigned short port)
{
    int sock;                        
    struct sockaddr_in servAddr; 

    if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        exit(1);

    memset(&servAddr, 0, sizeof(servAddr));
    servAddr.sin_family = AF_INET;         
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servAddr.sin_port = htons(port);            

    if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
        exit(1);

    if (listen(sock, 5) < 0)
        exit(1);

    return sock;
}

int UDP (unsigned short port)
{
    int sock;                        /* socket to create */
    struct sockaddr_in servAddr; /* Local address */

    /* Create socket for sending/receiving datagrams */
    if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
        exit(1);

    /* Construct local address structure */
    memset(&servAddr, 0, sizeof(servAddr));   /* Zero out structure */
    servAddr.sin_family = AF_INET;                /* Internet address family */
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
    servAddr.sin_port = htons(port);      /* Local port */

    /* Bind to the local address */
    if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
        exit(1);


    return sock;
}

//Client
sock_init();

    if ((client_sock_output = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        exit(1);

    memset(&client_addr, 0, sizeof(client_addr));
    client_addr.sin_family      = AF_INET;
    client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    client_addr.sin_port        = htons(1234);

    if (connect(client_sock_output, (struct sockaddr *) &client_addr, sizeof(client_addr)) < 0)
        exit(1);

    closesocket(client_sock_output);

    sock_term();

サーバーが起動すると、サーバーはif(select(...))ステートメントでブロックされます。

したがって、サーバーを実行してからクライアントを実行すると、クライアントはサーバーに接続します(クライアントが接続するまでに、クライアントの実行に数回かかる場合があります)。その後、if(select...))ステートメントは真ではなくなり、elseに進みます。

その後、クライアントは接続とプログラムを閉じます。しかし、これが私の問題が発生する場所であり、if(select(...))ステートメントは常に誤りです。私はこの出力を取得します:

Request on port 0:  
Input TCP Port 0  

Request on port 1:  
Input UDP Port 1

この出力は永久に繰り返されます。どうしてそれが行き詰まらないのif(select(...))ですか?

4

2 に答える 2

5

2つの問題があります。TCPでaccept()がどのように機能するかを理解していないことと、UDPで着信データを読み取る必要があることです。

select()は、リスニングソケットに受け入れる接続があるか、読み取りソケットに読み取るデータがあることを示します。

selectがこれを通知しないようにするには、実際にデータを読み取るか、接続を受け入れる必要があります。

UDPブランチでは、実際にデータを取得するためにreceivを呼び出す必要があります。そうでない場合、selectはデータがあることを通知し続けます。

TCPブランチで、accept_socketを呼び出します。実装が何であるかはわかりませんが、accept()を呼び出したばかりのソケットを閉じるのはおそらく間違っています。accept()は、新しいソケット(IOに使用する必要があるソケット)を返します。何かを閉じる必要がある場合、それはその新しいソケットです。

于 2010-07-30T15:03:09.727 に答える
1

サーバーにこれがある理由を確認してください。

if(select(0、&sock_set、NULL、NULL、&select_timeout)== 0)

に置き換えます

if(select(maxDescPlus1&sock_set、NULL、NULL、&select_timeout)== 0)

ここで、maxDescPlus1->は、選択する記述子の数に1を加えた値です。

于 2013-10-25T10:45:29.747 に答える