【问题标题】:How to add delay to sento and recvfrom in UDP client/server in C如何在 C 中的 UDP 客户端/服务器中为 sento 和 recvfrom 添加延迟
【发布时间】:2012-10-03 17:10:21
【问题描述】:

对于学校的一个编程项目,我们必须使用 tcp 协议和 udp 协议设计一个基本的客户端/服务器设置。我已经使用 C Socket 库中的 read() 和 write() 让 TCP 工作了。我现在需要创建一个“可靠的 UDP”系统。例如:

“当服务器接收到长度消息时,它将等待最多 500 毫秒以发送该字节数。如果它接收到正确的字节数,它将以包含字符“ACK”的字符串进行响应(a确认的常用缩写)。如果在超时期限结束时没有收到正确的字节数,服务器将放弃并静默退出。”

我已经设置了 sendto() 和 recvfrom() 函数,但我不确定如何执行超时功能,以便它只等待 500 毫秒来发送第二个 msg。如果它没有收到“ACK”并重新发送长度 msg + msg 几次,我也必须稍后在客户端执行此操作。超时怎么办?

【问题讨论】:

    标签: c sockets


    【解决方案1】:

    在你的程序中添加以下函数并使用它而不是直接使用recvfrom函数。

    下面的functiong与recvfrom函数的输入参数相同+最后一个超时输入参数

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <unistd.h>
    
    int timeout_recvfrom (int sock, char *buf, int *length, struct sockaddr_in *connection, int timeoutinseconds)
    {
        fd_set socks;
        struct timeval t;
        FD_ZERO(&socks);
        FD_SET(sock, &socks);
        t.tv_sec = timeoutinseconds;
        if (select(sock + 1, &socks, NULL, NULL, &t) &&
            recvfrom(sock, buf, *length, 0, (struct sockaddr *)connection, length)!=-1)
            {
            return 1;
            }
        else
            return 0;
    }
    

    【讨论】:

    • 你能解释一下为什么我们需要向套接字添加一个吗?我在几个地方看到过这种情况,这让我很困惑。
    • 那么与 sendto() 类似的函数是什么?或者我会正常使用 sendto(),因为我只等待 recvfrom() 的
    • 如果您想设置发送超时,请正常调用sendto(),然后仅在sendto() 失败并出现EAGAINEWOULDBLOCK 错误时调用select(),然后调用@ 987654328@ 第二次,如果select() 报告套接字再次变为可写。
    • @MasterGberry 我也发布了一个替代答案,但没有使用 select,因为超时是作为标准 Linux 套接字选项提供的。
    • @MasterGberry select() 允许程序监控多个文件/套接字描述符,等待一个或多个文件/套接字描述符“准备好”用于某种类型的 I/O 操作(例如,可以输入)。如果可以在不阻塞的情况下执行相应的 I/O 操作,则认为文件/套接字描述符已准备就绪。 select() 使用的超时是一个 struct timeval(秒和微秒):有关更多详细信息,请参阅 select 手册页 manpagez.com/man/2/select
    【解决方案2】:

    不使用 select 或 poll 的替代方法是使用套接字选项 SO_RCVTIMEO 和 SO_SNDTIMEO

    tv.tv_sec = 10; /* seconds */
    tv.tv_usec = 0;
    
    if(setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)
            printf("Cannot Set SO_SNDTIMEO for socket\n");
    
    if(setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
            printf("Cannot Set SO_RCVTIMEO for socket\n");
    

    SO_RCVTIMEO and SO_SNDTIMEO socket options

    如果您有一个单独的套接字可以读取或写入/写入,那么这是一个更好的选择。如果您正在使用多个套接字并希望继续使用一个完全发送/接收数据的套接字,那么也许 select 会更合适。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-17
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-20
      相关资源
      最近更新 更多