首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >资源临时不可否认- MSG_DONTWAIT标志

资源临时不可否认- MSG_DONTWAIT标志
EN

Stack Overflow用户
提问于 2016-10-10 13:11:36
回答 2查看 920关注 0票数 1

我在c中使用tcp套接字服务器和客户端,使用AF_INET、SOCK_STREAM和IPPROTO_TCP。

我在客户端中的发送功能

代码语言:javascript
运行
复制
sent_now = send(sockId, buffer + sent_total, len - sent_total, MSG_DONTWAIT);

当我发送到20K-40 It大小的MSG时,它工作得很好。当我将MSG发送到365 K大小(我需要的东西)时,我在服务器端收到以下错误:资源暂时不可用!

在服务器端我的接收功能

totalRecvMsgSize =接收( clntSocket,Buffer,RCVBUFSIZE,MSG_DONTWAIT);

我发送int数据类型。

如何在一次发送和接收操作中接收所有数组?

老岗位

有一篇关于What can cause a “Resource temporarily unavailable” on sock send() command的文章,大卫·贝拉说

这是因为您使用的是非阻塞套接字,并且输出缓冲区已满。 从send()手册页 当消息不适合套接字的发送缓冲区时,send()通常会阻塞,除非套接字已处于非阻塞I/O模式。在非阻塞模式下,在这种情况下它将返回EAGAIN。EAGAIN是与“资源暂时不可用”相关联的错误代码 考虑使用select()来更好地控制这种行为

我的问题是:

*1)如何在一次发送和接收操作中接收所有数组?*

2) select()是否帮助我实现这个数组大小?

3)我可以更改缓冲区大小以及如何更改吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-10 16:26:23

因为这是流套接字,所以在send()上使用循环,在recv()上使用MSG_WAITALL

考虑以下帮助函数:

代码语言:javascript
运行
复制
/* Receive the entire buffer.
 * Returns 0 if success, nonzero errno otherwise.
*/
static int recv_all(const int sockfd, void *buffer, const size_t len)
{
    ssize_t n;

    n = recv(sockfd, buffer, len, MSG_WAITALL);
    if (n == 0)
        return errno = EPIPE; /* Other end will not send more data */
    else
    if (n == -1)
        return errno;
    else
    if (n < -1)
        return errno = EIO;   /* Should never occur */
    else
    if (n != (ssize_t)len)
        return errno = EINTR; /* Interrupted, or sender goofed */
    else
        return 0;
}

/* Send the entire buffer.
 * Returns 0 if success, nonzero errno otherwise.
*/
static int send_all(const int sockfd, const void *buffer, const size_t len)
{
    const char       *pos = (const char *)buffer;
    const char *const end = (const char *)buffer + len;
    ssize_t           n;

    while (pos < end) {

        n = send(sockfd, pos, (size_t)(end - pos), 0);
        if (n > 0)
            pos += n; 
        else
        if (n != -1)
            return errno = EIO;
        else
            return errno;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2016-10-10 16:24:19

  1. 你不能可靠地做到这一点。您始终可以编写自己的sendallrecvall函数,这些函数将套接字设置为阻塞,然后反复调用send (/recv),直到发送/接收所有数据。(通常,带有阻塞套接字的单个send调用将导致在一次操作中发送所有数据,但在某些数据传输后会出现情况信号,例如,这将导致早期返回,因此不应依赖于此。)
  2. 您可以使用select来实现与非阻塞套接字相同的功能,但它使缓冲区管理更加复杂。您需要跟踪您在每个缓冲区中的位置/保留了多少数据,并且当select报告一个套接字是“可读的”或“可写的”时,请重新尝试在相应缓冲区的适当位置发送/接收。
  3. 是的,您可以任意设置缓冲区大小,但是如果您的意思是“我可以以某种方式设置系统缓冲区大小来避免这种情况吗?”如果没有额外的代码,就无法将系统配置成100%可靠地工作。TCP不维护消息边界。您的协议必须在TCP提供的逻辑流之上强制设置边界。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39959115

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档