套接字 fd 的 write() 是否有大小限制?
Is there a size limit of write() for a socket fd?
我正在编写一个涉及 epoll 和多线程的小型 Web 服务器。对于小而短的 http/1.1 请求和响应,它按预期工作。但是在处理大文件下载时,它总是被我设计的计时器打断。我用固定的超时值使计时器过期,但我也有一个 if 语句来检查响应是否已成功发送。
static void
_expire_timers(list_t *timers, long timeout)
{
httpconn_t *conn;
int sockfd;
node_t *timer;
long cur_time;
long stamp;
timer = list_first(timers);
if (timer) {
cur_time = mstime();
do {
stamp = list_node_stamp(timer);
conn = (httpconn_t *)list_node_data(timer);
if ((cur_time - stamp >= timeout) && httpconn_close(conn)) {
sockfd = httpconn_sockfd(conn);
DEBSI("[CONN] socket closed, server disconnected", sockfd);
close(sockfd);
list_del(timers, stamp);
}
timer = list_next(timers);
} while (timer);
}
}
我意识到在非阻塞环境中,write() 函数可能会在请求-响应通信期间被中断。我想知道 write() 可以保存多长时间或者 write() 可以发送多少数据,所以我可以调整我代码中的超时设置。
这是涉及write()的代码,
void
http_rep_get(int clifd, void *cache, char *path, void *req)
{
httpmsg_t *rep;
int len_msg;
char *bytes;
rep = _get_rep_msg((list_t *)cache, path, req);
bytes = msg_create_rep(rep, &len_msg);
/* send msg */
DEBSI("[REP] Sending reply msg...", clifd);
write(clifd, bytes, len_msg);
/* send body */
DEBSI("[REP] Sending body...", clifd);
write(clifd, msg_body_start(rep), msg_body_len(rep));
free(bytes);
msg_destroy(rep, 0);
}
下面是我用来处理传入请求的epoll循环,
do {
nevents = epoll_wait(epfd, events, MAXEVENTS, HTTP_KEEPALIVE_TIME);
if (nevents == -1) perror("epoll_wait()");
/* expire the timers */
_expire_timers(timers, HTTP_KEEPALIVE_TIME);
/* loop through events */
for (i = 0; i < nevents; i++) {
conn = (httpconn_t *)events[i].data.ptr;
sockfd = httpconn_sockfd(conn);
/* error case */
if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) ||
(!(events[i].events & EPOLLIN))) {
perror("EPOLL ERR|HUP");
list_update(timers, conn, mstime());
break;
}
else if (sockfd == srvfd) {
_receive_conn(srvfd, epfd, cache, timers);
}
else {
/* client socket; read client data and process it */
thpool_add_task(taskpool, httpconn_task, conn);
}
}
} while (svc_running);
http_rep_get() 由线程池处理程序 httpconn_task() 执行,HTTP_KEEPALIVE_TIME 是固定超时。一旦请求到达,处理程序 httpconn_task() 将向计时器添加一个计时器。由于write()是在http_rep_get()中执行的,我认为它可能被定时器中断了。我想我可以改变写给客户的方式,但我需要确定 write() 能做多少。
如果你有兴趣,你可以浏览我的项目来帮助我。
https://github.com/grassroot72/Maestro
干杯,
爱德华
Is there a size limit of write() for a socket fd?
这取决于你所说的限制是什么意思。
如评论所述,write
调用写入的字节数可能少于您要求的字节数。此外,如果您对套接字执行大量写入,这是预期的行为。但是,没有可靠的方法来确定(或预测)在调用 write
.
之前将写入多少字节
正确的处理方法是检查每次实际写入了多少字节,并使用循环确保所有字节都已写入(或直到失败)。
我正在编写一个涉及 epoll 和多线程的小型 Web 服务器。对于小而短的 http/1.1 请求和响应,它按预期工作。但是在处理大文件下载时,它总是被我设计的计时器打断。我用固定的超时值使计时器过期,但我也有一个 if 语句来检查响应是否已成功发送。
static void
_expire_timers(list_t *timers, long timeout)
{
httpconn_t *conn;
int sockfd;
node_t *timer;
long cur_time;
long stamp;
timer = list_first(timers);
if (timer) {
cur_time = mstime();
do {
stamp = list_node_stamp(timer);
conn = (httpconn_t *)list_node_data(timer);
if ((cur_time - stamp >= timeout) && httpconn_close(conn)) {
sockfd = httpconn_sockfd(conn);
DEBSI("[CONN] socket closed, server disconnected", sockfd);
close(sockfd);
list_del(timers, stamp);
}
timer = list_next(timers);
} while (timer);
}
}
我意识到在非阻塞环境中,write() 函数可能会在请求-响应通信期间被中断。我想知道 write() 可以保存多长时间或者 write() 可以发送多少数据,所以我可以调整我代码中的超时设置。
这是涉及write()的代码,
void
http_rep_get(int clifd, void *cache, char *path, void *req)
{
httpmsg_t *rep;
int len_msg;
char *bytes;
rep = _get_rep_msg((list_t *)cache, path, req);
bytes = msg_create_rep(rep, &len_msg);
/* send msg */
DEBSI("[REP] Sending reply msg...", clifd);
write(clifd, bytes, len_msg);
/* send body */
DEBSI("[REP] Sending body...", clifd);
write(clifd, msg_body_start(rep), msg_body_len(rep));
free(bytes);
msg_destroy(rep, 0);
}
下面是我用来处理传入请求的epoll循环,
do {
nevents = epoll_wait(epfd, events, MAXEVENTS, HTTP_KEEPALIVE_TIME);
if (nevents == -1) perror("epoll_wait()");
/* expire the timers */
_expire_timers(timers, HTTP_KEEPALIVE_TIME);
/* loop through events */
for (i = 0; i < nevents; i++) {
conn = (httpconn_t *)events[i].data.ptr;
sockfd = httpconn_sockfd(conn);
/* error case */
if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) ||
(!(events[i].events & EPOLLIN))) {
perror("EPOLL ERR|HUP");
list_update(timers, conn, mstime());
break;
}
else if (sockfd == srvfd) {
_receive_conn(srvfd, epfd, cache, timers);
}
else {
/* client socket; read client data and process it */
thpool_add_task(taskpool, httpconn_task, conn);
}
}
} while (svc_running);
http_rep_get() 由线程池处理程序 httpconn_task() 执行,HTTP_KEEPALIVE_TIME 是固定超时。一旦请求到达,处理程序 httpconn_task() 将向计时器添加一个计时器。由于write()是在http_rep_get()中执行的,我认为它可能被定时器中断了。我想我可以改变写给客户的方式,但我需要确定 write() 能做多少。
如果你有兴趣,你可以浏览我的项目来帮助我。 https://github.com/grassroot72/Maestro
干杯, 爱德华
Is there a size limit of write() for a socket fd?
这取决于你所说的限制是什么意思。
如评论所述,write
调用写入的字节数可能少于您要求的字节数。此外,如果您对套接字执行大量写入,这是预期的行为。但是,没有可靠的方法来确定(或预测)在调用 write
.
正确的处理方法是检查每次实际写入了多少字节,并使用循环确保所有字节都已写入(或直到失败)。