[정정] select함수에서...

zipsinworm의 이미지

select함수에 대해 궁금한것이 있어 글 올립니다.

소스를 대략 보면..

int sock;
fd_set readset;

sock=socket(PF_INET,SOCK_STREAM,0);

FD_ZERO(&readset)

while(1){
FD_SET(sock,&readset);

select(sock+1,&readset,0,0,NULL);
if(FD_ISSET(sock,&readset))
puts("OOPS");
}

return 0;

아주 간단한 소스 인데요. 결과는 무한 루프를 돈다는 겁니다. socket을 생성하고 fd_set에 등록한다음 sock에 아무런 변화를 주지 않았으니
select에서 기다리고 있어야 한다고 생각하는데 무한 루프에 빠져버리니... 왜 그런건지 이해가 가지 않습니다.

윗 소스대로라면 select는 소켓에 변화를 보는것이 아니라 읽기가 봉쇄당하지 않는것을 검사하지 않을까요?

만약 저 상태에서 select가 블록킹 하게 하려고 한다면 어떻게 해야하나요?

wariua의 이미지

socket 생성 후 connect()나 accept() 등을 호출하지 않은 상태로 (즉, 연결을 수립하지 않은 상태로) select()를 호출하는 경우 select()가 그 소켓을 어떻게 처리하느냐가 문제로군요. man page에는 뭐라고 나와 있을까요?

man select(2) 대강 번역 wrote:
select()와 pselect()는 프로그램이 복수의 파일 디스크립터를 모니터링 할 수 있도록 해주는데, 하나 혹은 그 이상의 파일 디스크립터가 어떤 유형의 I/O 연산에 대해 "준비 상태"(가령, 입력이 가능)가 될 때까지 대기합니다. 해당하는 I/O 연산(가령, read(2))을 블록킹 없이 수행하는 게 가능하면 파일 디스크립터가 준비 상태라고 간주합니다.

그렇다면 올려주신 코드의 select() 바로 앞에서 read()를 호출하면 어떻게 될까요? 네, read()는 즉시 -1을 반환하고 errno가 ENOTCONN 정도로 설정되겠죠. 네, '즉시' 반환됩니다. man page에서 명시한 조건에 부합하는 거죠. :-) 따라서 select()는 readset에 sock을 표시하고서 즉시 반환하게 됩니다.

최근에 올리신 몇 개의 글을 봐서는 "클라이언트가 connect()를 완료하고서, select()를 호출하기 전에 서버로부터 데이터 패킷을 수신한 경우 select()로 그 데이터의 수신을 감지할 수 있는가"라는 문제로 고민하고 계신 것 같습니다. 이 글타래도 그것과 관련된 것 같구요. 간단하게 코드 짜서 해보니까 잘 감지하는 것 같던데, 혹시 아직 그 문제가 미결 상태인가요?
----
$PWD `date`

$PWD `date`

답금의 이미지

각함수의 리턴값들 체크해보세요.

zipsinworm의 이미지

wariua님이 말씀해준신대로 select는

"해당하는 I/O 연산(가령, read(2))을 블록킹 없이 수행하는 게 가능하면 파일 디스크립터가 준비 상태라고 간주합니다."

connect()나 accept()등을 호출하지 않는 비동기일때 항상 준비상태가 되어서 무한 루프를 도는것 같습니다.

epoll은 비동기 일때도 소켓의 변화를 잘 감지 하더라고요.(무한 루프는 안돕니다.)

메시지가 들어온 상태에서 epoll을 호출해도 감지를 하고 select을 호출해도 감지가 됩니다.

단, 차이점이 있다면 비동기일때 select는 무한 루프에 빠진다는 겁니다. 그외에는 실험결과가 같았습니다.

실험은
서버를 하나 두고 클라이언트에서 쓰레드 하나를 생성하여 서버 메세지만 받게 합니다. 클라이언트에서는 여러개의 소켓을 생성해 소켓 테이블(전역 변수로 설정)을 만들어 쓰레드가 사용할수 있게 합니다.(소켓 테이블이 만들어질때 까지 쓰레드는 sem_wait를 사용해 기다리게 했습니다. 소켓 테이블이 다 만들어지면 sem_post를 사용해 쓰레드를 재 작동 시킵니다.) 쓰레드는 그 소켓 테이블을 받아서 fd_set과 struct epoll_event에 등록합니다. 마지막으로 select와 epoll을 호출 하는 방식입니다.(만약을 위해 따로따로 실험)

상당히 까다롭더라고요. select 때문에 2틀을 보낸듯..

약간 찝찝 하지만 어느정도 해소가 된 기분입니다. 나중에 내공이 많이 쌓이면 더 알 수 있겠죠~

답글 달아주신분들 정말 감사합니다. 많은 도움이 됐습니다.

zipsinworm의 이미지

서버 세팅이 잘못 됐다는걸 알고 다시 실험을 해봤습니다.

결론은 epoll도 비동기일때 select와 마찬가지로 무한루프를 돈다는 겁니다.

그외에는 같은 실험 결과가 나왔습니다.

몇번이고 재차 확인하고 올렸는데 잘못된 결과를 알려드려서 대단히 죄송합니다. (T T)(_ _)

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.