select의 writefds에 대해 제가 이해한 내용이 맞나요?

wjddndyd401의 이미지

select를 이용한 비동기 소켓 서버를 만들고 있습니다.

readfds의 경우엔 심플하게 패킷이 들어오면 fds에 변화가 생기지만

writefds의 경우엔 간단히 알아보니 '전송 가능한 시점에서 변화가 생긴다'라고 한 걸 봤습니다.

헌데 소켓의 경우엔 정상적인 연결 하에선 항상 전송 가능하지 않습니까?

실제로 콘솔 입출력에선 항상 fds의 변화가 생긴다고 했고...

그렇다면

-----------------------------

writefds에는 전송할 내용이 있는 소켓을 fd_set 시켜두면

그 소켓은 연결이 정상이라면 무조건 select에서 결과로 반환이 되니

그 결과를 검사해 전송 과정을 수행한다.

-----------------------------

라는 과정이 맞는건지요?

이론상 완벽하게 이해하는 게 아니라 코드와 결과를 통해 빠르게 이해하는 게 목적이다보니

중간중간 막히는 게 많네요...

추가로 select의 첫 번째 파라미터를 0으로 해두면 무슨 문제가 있는지도 알고 싶습니다.

검사할 FD의 개수라는데 그렇다면 0을 넣으면 안 될 것 같은데 실제론 이상이 없네요.

익명 사용자의 이미지

소켓이라고 항상 전송가능한 건 아닙니다. select 수행후에 readfds에 있으면 read 수행가능하고 writefds에 있으면 write 수행이 가능하다는 것만 염두에 두면 됩니다.
select 함수는 0 ~ (첫 파라미터-1) 까지의 fd만 검사합니다. 이 범위의 readfds, writefds 만 의미가 있습니다. 첫번째 파라미터를 0으로 두면 select는 아무것도 검사하지 않고 timeout을 지정하지 않는한 무한정 대기상태가 됩니다.

jick의 이미지

일반적으로 CPU는 네트웍보다 훨씬 빠릅니다. 그러니까 밖으로 나가는 소켓에 write를 끝없이 계속하면 write 버퍼가 점점 차서 어느 순간 커널이 더 이상 write를 받을 수 없는 지점이 오겠죠. (안 그런다면 무슨 일이 일어날지 생각해 보세요.)

그러므로 write가 항상 가능하다고 가정할 수는 없습니다.

wjddndyd401의 이미지

허면 그러한 상황에 놓인 fd는 select 실행 시 writefds에 들어가지 않게 되는 것인가요?

일단 버퍼가 가득 차는 상황을 대비해 전송 큐를 따로 구현하였고
그 전송 큐의 내용이 있을 경우 네트워크 관련 루틴에서 진짜 send를 하는 식으로 구현하고 있습니다.
말씀대로라면 전송 큐의 내용이 있을 경우에 writefds에 set시킨 후 select만 하면 될 듯한데...

jick의 이미지

select를 실행시킨 다음에 해당 fd가 writefds에 들어있는지 아닌지 검사를 하면 지금 blocking을 당하지 않고 write를 할 수 있는지 아닌지 알 수 있는 거죠.

전송 큐를 유저 레벨에서 구현하는 건 의미가 있을 수도 있지만, 그게 (네트웍이 느려서) 커널 단에서 버퍼링이 되는 걸 막아주진 않습니다. 유저레벨에서는 "버퍼링에 안 걸리고 얼마나 더 write를 할 수 있는가"라는 정보가 없으니 당연하죠.

wfellow의 이미지

그렇게 설정을 하지 않으면 block 처리가 되는데요, 이렇게 되면 select()를 사용하는 의미가 없겠지요.
man page 에서 select()를 보시던지 아님 리차드 스티븐스의 io multiplexing 부분 설명을 보시면
이해가 가실겁니다.

-----[꼬릿말 절취선 시작]-----
삽질전에 먼저 구글신께 기도하자.
-----[꼬릿말 절취선 끝]-----

wjddndyd401의 이미지

예제에서는 timeout을 마이크로초 단위로 하여 계속 루틴을 돌았기에
fd 자체에 nonblock 설정을 해야 하는 것은 몰랐습니다.

말씀하신 '지정'은 fcntl을 사용하는 것이 맞나요?
그리고 nonblock을 지정하지 않고 block인 상태로 사용한다면
select는 변화된 fd가 있을 때까지 대기하는 것이 맞는지..?

맞다면 아예 기본 개념을 잘못 이해하고 있었던건데...

jick의 이미지

> 예제에서는 timeout을 마이크로초 단위로 하여 계속 루틴을 돌았기에

...아니 그럴라면 select는 왜 한대요? select를 하는 이유가 "계속 루프를 돌며 확인하는 건 삽질이니, kernel이 내가 할 일이 있다고 알려줄 때까지 sleep해서 CPU를 아끼겠어!" 하는 건데...

그 예제 뭔가 수상한데요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.