lighttpd1.4.18程式碼分析(八)--狀態機(2)CON_STATE_READ狀態
阿新 • • 發佈:2018-12-27
// -1:出錯 -2:對方關閉連線 0:成功staticint connection_handle_read(server *srv, connection *con) {
int len;
buffer *b;
int toread;
if (con->conf.is_ssl) {
return connection_handle_read_ssl(srv, con);
}
#if defined(__WIN32)
b = chunkqueue_get_append_buffer(con->read_queue);
buffer_prepare_copy(b, 4*1024);
len = recv(con->fd, b->ptr, b->size -1, 0);
#else// 獲取有多少資料可讀if (ioctl(con->fd, FIONREAD, &toread)) {
log_error_write(srv, __FILE__, __LINE__, "sd",
"unexpected end-of-file:",
con->fd);
return-1;
}
// 根據資料量準備緩衝區 b = chunkqueue_get_append_buffer(con ->read_queue);
buffer_prepare_copy(b, toread +1);
// 讀資料 len = read(con->fd, b->ptr, b->size -1);
#endifif (len <0) {
con->is_readable =0;
// Non-blocking I/O has been selected using O_NONBLOCK and no data
// was immediately available for reading.if (errno == EAGAIN)
return0;
if (errno == EINTR) {
/* we have been interrupted before we could read */
con->is_readable =1;
return0;
}
if (errno != ECONNRESET) {
/* expected for keep-alive */
log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
}
connection_set_state(srv, con, CON_STATE_ERROR);
return-1;
} elseif (len ==0) {
// 當讀入資料 = 0時 表示對端關閉了連線 con->is_readable =0;
/* the other end close the connection -> KEEP-ALIVE *//* pipelining */return-2;
} elseif ((size_t)len < b->size -1) {
/* we got less then expected, wait for the next fd-event */
con->is_readable =0;
}
// 記錄讀入的資料量 未使用的資料第一個位元組為0 b->used = len;
b->ptr[b->used++] ='\0';
con->bytes_read += len;
#if 0
dump_packet(b->ptr, len);
#endifreturn0;
}
簡單的說, 該函式首先呼叫ioctl獲取fd對應的緩衝區中有多少可讀的資料, 然後呼叫chunkqueue_get_append_buffer和buffer_prepare_copy函式準備好所需的緩衝區, 準備好緩衝區之後, 呼叫read函式讀取緩衝區中的資料.對read函式的呼叫結果進行區分, 小於0表示出錯, 返回-1;等於0表示關閉了連線, 返回-2;假如讀取的資料長度比預期的小, 那麼就等待下一次繼續讀資料, 最後將已經讀入的資料緩衝區最後一個位元組置'\0',返回0.
int len;
buffer *b;
int toread;
if (con->conf.is_ssl) {
return connection_handle_read_ssl(srv, con);
}
#if defined(__WIN32)
b = chunkqueue_get_append_buffer(con->read_queue);
buffer_prepare_copy(b,
len = recv(con->fd, b->ptr, b->size -1, 0);
#else// 獲取有多少資料可讀if (ioctl(con->fd, FIONREAD, &toread)) {
log_error_write(srv, __FILE__, __LINE__, "sd",
"unexpected end-of-file:",
con->fd);
return-1;
}
// 根據資料量準備緩衝區 b = chunkqueue_get_append_buffer(con
buffer_prepare_copy(b, toread +1);
// 讀資料 len = read(con->fd, b->ptr, b->size -1);
#endifif (len <0) {
con->is_readable =0;
// Non-blocking I/O has been selected using O_NONBLOCK and no data
// was immediately available for reading.if (errno == EAGAIN)
if (errno == EINTR) {
/* we have been interrupted before we could read */
con->is_readable =1;
return0;
}
if (errno != ECONNRESET) {
/* expected for keep-alive */
log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
}
connection_set_state(srv, con, CON_STATE_ERROR);
return-1;
} elseif (len ==0) {
// 當讀入資料 = 0時 表示對端關閉了連線 con->is_readable =0;
/* the other end close the connection -> KEEP-ALIVE *//* pipelining */return-2;
} elseif ((size_t)len < b->size -1) {
/* we got less then expected, wait for the next fd-event */
con->is_readable =0;
}
// 記錄讀入的資料量 未使用的資料第一個位元組為0 b->used = len;
b->ptr[b->used++] ='\0';
con->bytes_read += len;
#if 0
dump_packet(b->ptr, len);
#endifreturn0;
}
簡單的說, 該函式首先呼叫ioctl獲取fd對應的緩衝區中有多少可讀的資料, 然後呼叫chunkqueue_get_append_buffer和buffer_prepare_copy函式準備好所需的緩衝區, 準備好緩衝區之後, 呼叫read函式讀取緩衝區中的資料.對read函式的呼叫結果進行區分, 小於0表示出錯, 返回-1;等於0表示關閉了連線, 返回-2;假如讀取的資料長度比預期的小, 那麼就等待下一次繼續讀資料, 最後將已經讀入的資料緩衝區最後一個位元組置'\0',返回0.