【问题标题】:socket programming using timers使用定时器进行套接字编程
【发布时间】:2012-08-30 17:45:58
【问题描述】:

我需要 C 中的套接字编程方面的帮助。我需要用 C 编写一个服务器-客户端程序,其中两个 IP 在创建的套接字上相互通信。我成功地做到了这一点。但现在我想在套接字中添加计时器。我研究了一下,发现它可以通过 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”。我需要这方面的帮助。 提前致谢, 理查德。

【问题讨论】:

    标签: c sockets select


    【解决方案1】:
          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 返回的文件描述符。

    【讨论】:

      【解决方案2】:

      对于您的特定问题,您可以使用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);
      }
      

      来自manual page

      SO_RCVTIMEO
      设置超时值,该值指定输入函数在完成之前等待的最长时间。它接受一个 timeval 结构,其中包含秒数和微秒数,指定等待输入操作完成的时间限制。如果接收操作阻塞了这么长时间而没有接收到额外的数据,如果没有接收到数据,它将返回部分计数或设置为 [EAGAIN] 或 [EWOULDBLOCK] 的 errno。此选项的默认值为零,表示接收操作不会超时。此选项采用 timeval 结构。请注意,并非所有实现都允许设置此选项。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-21
        • 1970-01-01
        相关资源
        最近更新 更多