Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用select和recv通过套接字从web服务器获取文件_C_Sockets - Fatal编程技术网

使用select和recv通过套接字从web服务器获取文件

使用select和recv通过套接字从web服务器获取文件,c,sockets,C,Sockets,使用C套接字从web服务器接收大文件时遇到问题;也就是说,我怀疑这些文件大于我用来接收它们的缓冲区的大小。如果我试图通过GET请求请求一个不超过几个字节的简单index.html,我会得到很好的结果,但其他任何操作都会失败。我认为我缺乏select或recv方面的知识是我失败的原因。请看这里: fd_set read_fd_set; FD_ZERO(&read_fd_set); FD_SET((unsigned int)socketId, &read_fd_set); /* I

使用C套接字从web服务器接收大文件时遇到问题;也就是说,我怀疑这些文件大于我用来接收它们的缓冲区的大小。如果我试图通过GET请求请求一个不超过几个字节的简单index.html,我会得到很好的结果,但其他任何操作都会失败。我认为我缺乏select或recv方面的知识是我失败的原因。请看这里:

fd_set read_fd_set;
FD_ZERO(&read_fd_set);
FD_SET((unsigned int)socketId, &read_fd_set);

/* Initialize the timeout data structure. */
struct timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;

// Receives reply from the server
int headerReceived = 0;
do {
    select(socketId+1, &read_fd_set, NULL, NULL, &timeout);

    if (!(FD_ISSET(socketId, &read_fd_set))) {
       break;
    }

    byteSize = recv(socketId, buffer, sizeof buffer, 0);

    if (byteSize == 0 || (byteSize < BUFFER_SIZE && headerReceived)) {
       break;
    }

    headerReceived = 1;

} while(1);
没错,在将GET请求发送到web服务器之后(我很确定服务器运行得很好),从任何其他客户端(如任何web浏览器)获取请求都能正常工作


提前感谢,我们非常感谢您的帮助。

您没有说明您使用的是什么O/S,但根据:

成功完成后,选择功能可以修改 超时参数指向的对象

我相信Linux就是这样做的

因此,很有可能稍后对循环的调用将超时设置为零,这将导致select在没有准备好描述符的情况下立即返回


我建议在每次通过循环调用select之前立即重新初始化超时结构。

您没有说明您正在使用什么O/S,但根据:

if (byteSize == 0 || (byteSize < BUFFER_SIZE && headerReceived))
{
    break;
}
成功完成后,选择功能可以修改 超时参数指向的对象

我相信Linux就是这样做的

因此,很有可能稍后对循环的调用将超时设置为零,这将导致select在没有准备好描述符的情况下立即返回

我建议在每次通过循环调用select之前立即重新初始化超时结构

if (byteSize == 0 || (byteSize < BUFFER_SIZE && headerReceived))
{
    break;
}
首次读取后,headerReceived设置为true。这是完全可能的,并且后续RECV可能会小于缓冲区大小。此时,您已脱离读取循环。Recv将返回要读取的字节数,而不一定返回您请求的字节数

也可以使用缓冲区大小或sizeofbuffer。混合和匹配只是在路上的某个地方寻找一个bug

首次读取后,headerReceived设置为true。这是完全可能的,并且后续RECV可能会小于缓冲区大小。此时,您已脱离读取循环。Recv将返回要读取的字节数,而不一定返回您请求的字节数


也可以使用缓冲区大小或sizeofbuffer。混合和匹配只是在路上的某个地方询问一个bug。

我发现的一件事是,在循环过程中不重新初始化选择。这可能就是您成功获取小文件的原因;它们是一次性接收的,循环不必迭代

我建议您将以下内容:

FD_ZERO(&read_fd_set);
FD_SET((unsigned int)socketId, &read_fd_set);
timeout.tv_sec = 2;
timeout.tv_usec = 0;

在调用select之前,它可能会在循环内部工作。

我发现的一件事是,在循环期间,您不会重新初始化选择。这可能就是您成功获取小文件的原因;它们是一次性接收的,循环不必迭代

我建议您将以下内容:

FD_ZERO(&read_fd_set);
FD_SET((unsigned int)socketId, &read_fd_set);
timeout.tv_sec = 2;
timeout.tv_usec = 0;

在调用select之前在循环内部,它可能会正常工作。

它是Linux。谢谢你的建议,但不幸的是,这似乎并没有解决它。它是Linux。谢谢你的建议,但不幸的是,这似乎并没有解决它。好吧,这似乎是结合了这一点和鸭子的答案做的把戏,谢谢!好吧,看来这和Duck的回答结合在一起成功了,谢谢!这似乎改善了行为,谢谢!这和EitanT的改变相结合似乎起到了作用:这似乎改善了行为,谢谢!结合这一点和EitanT的改变似乎已经达到了目的:我认为假设byteSize