【问题标题】:read() from socket hangs when run from thread从线程运行时,来自套接字的 read() 挂起
【发布时间】:2012-05-08 11:52:15
【问题描述】:

我正在尝试编写代理服务器,现在我想实现流水线。我遇到了一个问题,需要帮助。我检查了this 问题,但我认为它不适用,因为我确实有要从套接字读取的数据。

主要思想如下。对于每个连接,我创建一个处理它的线程,对于这个连接中的每个请求,我想创建一个处理该请求的线程。到目前为止,我已经设法编写了第一部分的代码并且它工作正常(线程还处理连接的所有请求)。

现在,当我尝试从请求处理线程中读取套接字时,它会挂起。我用来读取数据的功能和以前一样(在工作版本中)。

void copydata(int from, int to, int len)
{
    char tbuff[BSIZ];
    int n;
    while (len > 0)
    {
        if ((n = read(from, tbuff, BSIZ)) <= 0) break;
        if (write(to, tbuff, n) < n) break;
        len -= n;
    }
}

from、to 和 len 变量具有适当的值(我检查了它们)。有什么东西会导致这种行为吗?

PS:如果需要更多代码,请告诉我。

编辑

以下是获取 len 的方法:

int contentlength(char *header)
{
    int len = INT_MAX;
    char line[MAX_LINE];

    if (HTTPheadervalue_case(header, "Content-Length", line)) sscanf(line, "%d", &len);
    return len;
}

调用copydata(其中activesocket是一个打开socket的函数):

if ((srv = activesocket(host, portno)) < 0)
    {
        sprintf(reshead, "HTTP/1.1 503\r\nContent-Length: 12\r\nConnection: close\r\n\r\nNon-existent");
        write(cli, reshead, strlen(reshead));
    } else
    {
        sprintf(reqhead1, "%s %s HTTP/1.1\r\n", "GET", path);
        if (HTTPheadervalue_case(reqhead1, "Connection", result)) if (strcasecmp(result, "close") == 0) cli_terminate[cli] = TRUE;
        strcat(reqhead1, reqhead);
        write(srv, reqhead1, strlen(reqhead1));
        while (completed[cli] != id)
            ;
        copydata(cli, srv, contentlength(reqhead));
        parseResponse(&srv, cli);
        completed[cli] = (completed[cli] + 1) % ULONG_MAX;
    }

编辑

一个示例请求标头如下:

Host: www.google.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.1.16) Gecko/20120421 Iceweasel/3.5.16 (like Firefox/3.5.16)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Cookie: cookie content

我也尝试去掉 keep-alive 标志,但还是一样。

【问题讨论】:

  • 是非阻塞套接字吗?此外,需要围绕write() 进行循环,因为它可能会进行部分写入。
  • 是的,它是一个非阻塞套接字。
  • 请添加一些调用copydata的上下文。 len 是从什么得到的?
  • 它是否挂在copydata函数中?
  • 是的。正如我所说,当调用read() 时它会挂起。但它只发生在我正在尝试处理请求时。老实说,即使我只有一个请求,它也会挂起。

标签: c sockets pthreads


【解决方案1】:

我猜这是你的问题(来自accept(2)):

在 Linux 上,accept() 返回的新套接字从侦听套接字继承文件状态标志,例如 <b>O_NONBLOCK</b><b>O_ASYNC</b>。 1234565>

即您需要明确地使每个新接受的套接字非阻塞。

【讨论】:

  • accept() 更改为accept4() 并使用SOCK_NONBLOCK 标志就可以了。感谢您提供信息。
猜你喜欢
  • 2019-10-14
  • 1970-01-01
  • 2012-06-15
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多