Lighttpd1.4.20 소스 분석 상태기(4) 오류 처리 및 연결 해제
15099 단어 lighttpd
http 프로토콜에 규정된 오류에 대해lighttpd는 해당하는 오류 알림 파일을 되돌려줍니다.사실lighttpd에 대해 말하자면, 이것은 잘못된 것이 아니다.오류 알림 파일을 되돌린 후 요청을 순조롭게 끝낸 셈이다. 클라이언트가 원하는 것과 결과가 다를 뿐이다.
서버 실행 중 오류의 경우 상태 기회가 CON_STATE_ERROR 상태.대부분의 경우, 이러한 오류는 클라이언트가 미리 연결을 끊어서 발생하는 것이다.예를 들어 페이지를 끊임없이 새로 고칩니다. 새로 고칠 때 이전의 연결이 완료되지 않았지만 브라우저에 의해 강제로 끊어지면 서버에 연결 오류가 발생합니다.서버의 경우 새로 고침 전후의 두 연결은 상관없다.따라서 서버는 다음 연결을 받을 때 이전 연결을 계속 처리합니다.이때 이전의 연결이 끊어져 연결 오류가 발생했습니다.CON_ 시작STATE_ERROR 상태 후에 이전 처리가 이미 결과를 얻었다면.http_status는 비어 있지 않습니다.그러면 플러그인_call_handle_request_done는 플러그인 요청 처리가 끝났다고 알려 줍니다.
/*
* even if the connection was drop we still have to write it to the
* access log
*/
if
(con
->
http_status)
{
plugins_call_handle_request_done(srv, con);
}
이어서 ssl을 사용하면 ssl 연결을 닫습니다.ssl 연결을 닫는 코드는 매우 길지만, 대부분은 오류 처리입니다.뒤로 가서 연결 모드가 DIRECT가 아니라면plugins_call_handle_connection_close는 플러그인 연결이 닫혔음을 알려 줍니다.여기, 연결이 설정되어 있지 않으면 keep_alive, 그러면 연결을 닫고 청소를 한 후에 상태기의 운행을 종료합니다.
keep_가 설정되어 있으면alive, 서버가 먼저 연결을 닫았을 수도 있습니다.shutdown을 호출하여 연결의 읽기와 쓰기를 닫습니다.끄기 오류가 없으면 상태 머신이 CON_ 로 들어갑니다.STATE_CLOSE 상태.
1
/*
2
* close the connection
3
*/
4
if
((con
->
keep_alive
==
1
)
&&
(
0
==
shutdown(con
->
fd, SHUT_WR)))
5
{
6
con
->
close_timeout_ts
=
srv
->
cur_ts;
7
connection_set_state(srv, con, CON_STATE_CLOSE);、
8
if
(srv
->
srvconf.log_state_handling)
9
{
10
log_error_write(srv, __FILE__, __LINE__,
"
sd
"
,
11
"
shutdown for fd
"
, con
->
fd);
12
}
13
}
위의 코드에는 다음과 같은 문장이 있습니다: con->close_timeout_ts = srv->cur_ts;close_timeout_ts의 값은 현재 시간으로 설정됩니다.이때 왜 썼어요?조급해하지 말고 계속 끝내고 가세요.
CON_ 시작STATE_ERROR 상태 이후 keep_alive, 그리고 버퍼에 데이터가 아직 읽지 않았으니, 이 데이터를 읽고 바로 버려라.읽을 데이터가 없으면 close_time_ts는 0입니다.다음 코드를 실행합니다.
1
if
(srv
->
cur_ts
-
con
->
close_timeout_ts
>
1
)
2
{
3
connection_close(srv, con);
4
if
(srv
->
srvconf.log_state_handling)
5
{
6
log_error_write(srv, __FILE__, __LINE__,
"
sd
"
,
"
connection closed for fd
"
, con
->
fd);
7
}
8
}
출력 로그를 제외하고 이 코드는connection_close.connection_close는 마지막 정리 작업을 합니다. close를 호출하여 대응하는connection을 버퍼에 다시 넣는 것을 포함합니다.앞에서 아까 말씀드렸듯이 CON_STATE_ERROR에 close_ 설정time_ts는cur_ts.CON_ 나왔습니다.STATE_ERROR 후 CON_STATE_CLOSE, 그동안cur_ts는 변하지 않았습니다.이전 코드에서 테스트 버퍼에 읽을 데이터가 없으면 const_time_ts는cur_와 같다ts.그러니까 상태기는 아직 CON_CLOSE_STATE 상태, 그리고 상태기의 큰 while 순환을 종료합니다.서버가 연결에 들어갔습니다_state_mechine 맨 뒤에 있는 switch 문장.이 switch에서 연결에 대응하는 fd가 fdevent 시스템에 추가되고 읽기 이벤트를 감청합니다.
이 시간에 연결이 꺼졌는데 읽을 게 뭐가 있겠어요?서두르지 마라!세심한 독자들은 이럴 때 서버가 연결에 대해shutdown 함수를 호출했을 뿐close 함수를 호출하지 않았다는 것을 알아차릴 것이다.우선 shutdown과close의 차이를 말씀드리겠습니다.close는 socket fd에 작용하고 다른 fd에 작용하는 효과가 많지 않습니다. 인용 계수를 줄이고 계수가 0일 때 자원을 방출하고 연결을 닫습니다.shutdown 함수는 socket fd를 위한 전문 함수입니다.shutdown은 socket 연결의 한 방향을 닫을 수 있습니다. 즉, 쓰기만 닫거나 읽기만 닫을 수 있습니다.또 다른 차이점은 연결이 여러 프로세스가 공유하는 경우 한 프로세스에서close를 호출하면 다른 프로세스가 연결을 사용하는 데 영향을 주지 않는다는 것이다. 인용 계수만 1이 줄어들기 때문이다.만약에 하나의 프로세스가 shutdown을 호출한다면 무작정 시스템이 이 연결을 없애고 다른 프로세스가 보는 것도 닫힌 연결이다.close의 socket fd,read,write 함수를 호출하면 이 fd에서 데이터를 읽거나 보낼 수 없습니다.shutdown의 socket fd를 호출했습니다. 버퍼에 읽을 수 있는 데이터가 있으면 프로세스에 socket fd가 닫히지 않았기 때문에read는 이 fd에서 데이터를 읽을 수 있습니다.shutdown은 연결을 닫았을 뿐이기 때문에 자원의 방출을 하지 않습니다. 연결이 차지하는 자원을 방출하려면close 함수를 호출해야 합니다.
keep_alive의 연결, 닫기는 서버가 자발적으로 시작합니다.TCP 프로토콜에 따라 자발적으로 종료를 시작한 쪽의 연결은 TIME_WAIT 상태입니다. 이 때 연결에 사용된 자원이 방출되지 않았습니다.더 비극적인 것은 이 상태에서 오랫동안 머물러야 한다는 것이다...(기본 4분) 병렬 서버의 경우 서버가 대량의 연결을 자발적으로 닫으면 서버의 자원이 곧 다 소모되고 (포트, 메모리 등) 새로운 연결을 만들 수 없습니다.이 TIME에 대해서_WAIT 상태, 독자 스스로 구글, 인터넷에 소개된 글과 처리 방법이 많습니다.비록 이 타임은_WAIT 상태는 우리에게 많은 번거로움을 가져다 줄 것 같지만, 이 상태가 없다면 우리는 더욱 번거로울 것이다...'UNIX Network Programming Volum1'이라는 신작에 대한 상세한 소개가 있으니, 관심 있는 독자들이 보실 수 있습니다.기왕 번거로움을 피할 수 없다면, 가능한 한 번거로움의 영향을 최소화해야 한다.연결이 차지하는 자원은 주로 포트와 메모리이다.포트는 어쩔 수 없어, 점용하면 점용해.하지만 메모리는 조금 절약할 수 있다.앞에서 말했듯이, shutdown 후에도 우리는 버퍼의 데이터를 읽을 수 있다.그러면 우리가 이 데이터를 읽은 후에 버퍼가 차지하는 메모리를 방출할 수 있다.메모리의 사용을 줄였다.
CON_에서STATE_CLOSE에서 다음 코드는 버퍼의 데이터를 읽습니다.
1
if
(ioctl(con
->
fd, FIONREAD,
&
b))
2
{
3
log_error_write(srv, __FILE__, __LINE__,
"
ss
"
,
"
ioctl() failed
"
, strerror(errno));
4
}
5
if
(b
>
0
)
6
{
7
char
buf[
1024
];
8
log_error_write(srv, __FILE__, __LINE__,
"
sdd
"
,
"
CLOSE-read()
"
, con
->
fd, b);
9
10
read(con
->
fd, buf,
sizeof
(buf));
11
}
12
else
13
{
14
/*
15
* nothing to read
16
*/
17
18
con
->
close_timeout_ts
=
0
;
19
}
읽을 데이터가 없으면 close_ 설정timeout_ts는 뒤에 연결된 코드를 닫습니다.읽을 수 있는 데이터가 있으면 데이터를 읽은 후에도 연결이 CON_STATE_CLOSE 상태에서 연결에 대응하는 fd가 fdevent 시스템에 추가되어 읽기 이벤트를 감청합니다.버퍼에 데이터가 있다면connection_handle_fdevent 함수에도 위의 코드가 있습니다. 다시 실행합니다.데이터가 다 읽히지 않으면 서버는 연결에서 중복됩니다_handle_fdevent 함수에서 데이터를 다 읽을 때까지 상기 코드를 실행합니다.close_에 따라timeout_ts는 0으로 설정되었습니다. 다음joblist 스케줄링에서 상태기는 연결을 닫고 모든 자원을 정리합니다.
이로써 연결이 정식으로 닫힙니다.이렇게 번거로운 이유는 연결이 서버가 자발적으로 닫혔기 때문에 TIME_WAIT 상태에 대한 질문입니다.이렇게 처리하는 것은 단지 메모리에 약간의 절약이 있을 뿐이다.그러나 구체적인 효과가 어떠한지 시스템 핵이 연결 버퍼를 어떻게 처리하는지에 달려 있다.만약 독자 여러분이 이 방면의 내용을 이해한다면, 아낌없이 가르침을 주십시오!
또한 shutdown 이후 커널의 버퍼가 어떻게 될지 필자는 확실하지 않다.위의 내용은 코드에 근거하여 추단할 뿐이다.아니면 그 말이 독자를 위해 어떤 고견을 주신다면 아낌없이 가르침을 주시겠어요.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Lighttpd1.4.20 소스 분석 상태기(4) 오류 처리 및 연결 해제close를 호출하여 대응하는connection을 버퍼에 다시 넣는 것을 포함합니다.앞에서 아까 말씀드렸듯이 CON_STATE_ERROR에 close_ 설정time_ts는cur_ts.CON_ 나왔습니다.STATE_E...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.