2

C でのソケット プログラミングについて助けが必要です。作成されたソケットで 2 つの IP が相互に通信するサーバー クライアント プログラムを C で作成する必要があります。私はこれで成功しました。しかし今、ソケットにタイマーを追加したいと思います。少し調べたところ、タイムアウト値を指定する select() で実現できることがわかりました。やってみましたがだめでした。以下に示すコードでは、クライアントに接続して、作成された新しいソケットを 10 秒間読み取ろうとしています。クライアントがこれらの 10 秒以内に何らかのメッセージを送信した場合、サーバーはそのメッセージを受け取り、確認応答を返す必要があります。そうでない場合は、タイムアウトになったことを示すエラー メッセージを表示する必要があります。

私のサーバーコードは次のとおりです。

    #include<stdio.h>
    #include<unistd.h>
    #include<sys/time.h>
    #include<sys/types.h>
    #include<sys/socket.h>
    #include<netinet/in.h>
    #include<stdlib.h>
    void error(char *msg)
    {
        perror(msg);
        exit(1);
    }

    int main(int argc, char *argv[])
    {
        int a=1;
        fd_set readfds,writefds;
        int ready_for_reading,reading;
        struct timeval time_out;
        FD_ZERO(&readfds);
  //    FD_ZERO(&writefds);
        FD_SET(a,&readfds);

        time_out.tv_sec = 10;    // 10 seconds
        time_out.tv_usec = 0;    // 0 milliseconds

  //    ready_for_reading=select(1,&readfds,NULL,NULL,&time_out);


        int sockfd, newsockfd, portno,n,clilen;;
        struct sockaddr_in serv_addr,cli_addr;
        char buffer[256];
        portno=atoi(argv[1]);
        sockfd=socket(AF_INET,SOCK_STREAM,0);
        if(sockfd==-1)
            error("\nError creating socket");
        serv_addr.sin_family=AF_INET;
        serv_addr.sin_port=htons(portno);
        serv_addr.sin_addr.s_addr=INADDR_ANY;

        n=bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
        if(n<0)
            error("\nError binding socket");
        listen(sockfd,5);
        clilen=sizeof(cli_addr);
        printf("\nAccept call reached");
        newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen);
        printf("\nnewSockfd=%d",newsockfd);
        printf("\ntesting value:%d",sizeof(readfds));
        if(newsockfd==-1)
            error("\nError on accept");
    //  FD_SET(a,&readfds);
        ready_for_reading=select(sizeof(readfds)*8,&readfds,NULL,NULL,&time_out);
        printf("\nready_for_reading=%d",ready_for_reading);
        if (ready_for_reading == -1) 
        {
            /* Some error has occured in input */
             printf("Unable to read your input\n");
             return -1;
        }
         else 
        {
                  if (ready_for_reading) 
              {
                     reading = read(newsockfd, buffer, 255);
                     printf("Read, %d bytes from input : %s \n", reading,buffer);
                  } 
              else 
              {
                     printf(" 10 Seconds are over - no data input \n");
             return 0;
                  }
            }

    /*  n=read(newsockfd,buffer,255);
        if(n<0)
            error("\nError in reading client's msg");
    */
        printf("\nClient's msg is:%s\n",buffer);
        n=write(newsockfd,"I got your message",25);
        if(n<0)
            error("\nError on writing");

        return 0;
    }

select() 関数は常に「0」を返します。これについて助けが必要です。前もってありがとう、リチャード。

4

2 に答える 2

4
      int a=1;
      fd_set readfds,writefds;
      int ready_for_reading,reading;
      struct timeval time_out;
      FD_ZERO(&readfds);
//    FD_ZERO(&writefds);
      FD_SET(a,&readfds); // a?!

ファイル記述子1、stdoutを選択しています。から取得したファイル記述子を選択する必要がありますaccept

于 2012-09-05T23:23:23.903 に答える
0

特定の問題については、SO_RCVTIMEOソケットオプションを使用できます。

#include <assert.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv_with_timeout (int s, void *buf, size_t len, int flags,
                           struct timeval *timeout)
{
    if (timeout) {
        ssize_t bytes;
        int r;
        struct timeval last;
        socklen_t lastlen = sizeof(last);
        r = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &last, &lastlen);
        if (r < 0) return r;
        r = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, timeout, sizeof(*timeout));
        if (r < 0) return r;
        bytes = recv(s, buf, len, flags);
        r = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &last, lastlen);
        assert(r == 0);
        return bytes;
    }
    return recv(s, buf, len, flags);
}

マニュアルページから:

SO_RCVTIMEO
入力関数が完了するまで待機する最大時間を指定するタイムアウト値を設定します。入力操作が完了するまで待機する時間の制限を指定する秒数とマイクロ秒数を持つ timeval 構造体を受け入れます。追加のデータを受信せずに受信操作がこの時間ブロックされた場合、データが受信されない場合、部分的なカウントまたは errno が [EAGAIN] または [EWOULDBLOCK] に設定されて返されます。このオプションのデフォルトはゼロで、受信操作がタイムアウトしないことを示します。このオプションは timeval 構造を取ります。すべての実装でこのオプションを設定できるわけではないことに注意してください。

于 2012-09-06T02:39:43.283 に答える