λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

TIL (Today I Learned)/Network

[TCP/IP] select()

728x90

μ†ŒμΌ“ λ©€ν‹°ν”Œλ ‰μ‹± ν•¨μˆ˜ select()

μ„œλ²„κ°€ μ—¬λŸ¬ ν΄λΌμ΄μ–ΈνŠΈλ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ 방법 쀑 μž…μΆœλ ₯ 닀쀑화λ₯Ό μ‚¬μš©ν•˜λŠ” 방법
μž…μΆœλ ₯ λ‹€μ€‘ν™”λž€ μ—¬λŸ¬ μž…μΆœλ ₯ λŒ€μƒμ΄ μžˆμ„ λ•Œ κ·Έ λŒ€μƒλ“€μ„ κ²€μ‚¬ν•˜λ©° μž…μΆœλ ₯이 ν•„μš”ν•  λ•Œλ§ˆλ‹€ μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” 것을 λ§ν•œλ‹€. 이 방법은 λ©€ν‹° ν”„λ‘œμ„Έμ‹±, λ©€ν‹° μŠ€λ ˆλ”© 방법과 λ‹€λ₯΄κ²Œ μ‹±κΈ€ ν”„λ‘œμ„ΈμŠ€, μ‹±κΈ€ μŠ€λ ˆλ“œμ—μ„œλ„ λ™μž‘
μ™„μ „νžˆ λ™μ‹œμ— μ²˜λ¦¬ν•˜μ§€ λͺ»ν•˜λŠ” 단점이 μžˆλ‹€.

select() ν•¨μˆ˜

λ¦¬λˆ…μŠ€λŠ” select() ν•©μˆ˜λ‘œ μž…μΆœλ ₯ 닀쀑화λ₯Ό κ΅¬ν˜„ν•  수 μžˆλ‹€. select()λŠ” μ§€μ •ν•œ λ²”μœ„μ˜ file discripter 쀑 FD_SET으둜 1둜 set λ˜μ–΄ μžˆλŠ” νŒŒμΌμ„ μˆœνšŒν•˜λ©΄μ„œ λ³€ν™”κ°€ μžˆλŠ” file discripterλ₯Ό λ°˜ν™˜
νŒŒμΌμ— λ³€ν™”κ°€ μžˆλ‹€λ©΄ 1, μ—†λ‹€λ©΄ 0 set

file discripter

  • select()λ₯Ό μ΄ν•΄ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ¦¬λˆ…μŠ€μ—μ„œ νŒŒμΌμ„ κ΄€λ¦¬ν•˜λŠ” 방법을 μ•Œμ•„μ•Ό ν•œλ‹€. λ¦¬λˆ…μŠ€λŠ” νŒŒμΌμ„ file discripter둜 κ΄€λ¦¬ν•˜λ©°, λ¦¬λˆ…μŠ€ μ‹œμŠ€ν…œμ—μ„œ νŒŒμΌμ„ μ—΄λ©΄ ν•΄λ‹Ή νŒŒμΌμ— λŒ€ν•œ 정보λ₯Ό 담은 ꡬ쑰체λ₯Ό κ°€λ¦¬ν‚€λŠ” 포인터듀이 table ν˜•νƒœλ‘œ μ €μž₯λ˜λŠ”λ° 이 table의 색인 λ²ˆν˜Έκ°€ λ°”λ‘œ file discripterλ‹€.
  • λ¦¬λˆ…μŠ€λŠ” μ†ŒμΌ“λ„ 파일둜 닀루기 λ•Œλ¬Έμ— νŽΈλ¦¬ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€.
  • λ¦¬λˆ…μŠ€μ—μ„œ 0, 1, 2번 νŒŒμΌμ€ κΈ°λ³Έμ„€μ •μœΌλ‘œ μ§€μ •λ˜μ–΄μžˆμœΌλ©° μž„μ˜μ˜ νŒŒμΌλ“€μ€ 3λΆ€ν„° fdλ₯Ό λΆ€μ—¬λ°›λŠ”λ‹€. μ†ŒμΌ“λ„ 파일둜 닀루기 λ•Œλ¬Έμ— μ†ŒμΌ“μ„ μƒμ„±ν•˜λ©΄ 3 μ΄μƒμ˜ fd(file discripter)λ₯Ό λΆ€μ—¬ λ°›λŠ”λ‹€.

fd set

  • 크기가 1024인 λΉ„νŠΈν•„λ“œ 이며 0κ³Ό 1의 값을 κ°€μ§„λ‹€.
int select(int n,    // 검사할 파일 λ””μŠ€ν¬λ¦½ν„° 번호 쀑 κ°€μž₯ 큰 κ°’+1 (λ°°μ—΄μΈμžλ‘œ μ ‘κ·Όν•˜κΈ° λ•Œλ¬Έμ—)
  fd_set* readfds,    // 읽기λ₯Ό 검사할 fd_set
  fd_set* writefds,    // μ“°κΈ°λ₯Ό 검사할 fd_set
  fd_set* exceptfds,    // μ˜ˆμ™Έλ₯Ό 검사할 fd_set
  const struct timeval* timeout);    // κ²€μ‚¬ν•˜λŠ” μ‹œκ°„μ— μ œν•œμ„ λ‘”λ‹€. NULL이면 λ¬΄ν•œμ • λŒ€κΈ°ν•œλ‹€.
  // returnκ°’ : 0 <= 변경이 생긴 파일의 수, -1 = μ‹€νŒ¨

select()의 핡심은 fd_set을 μ œμ–΄ν•˜λŠ” 것이닀. fd_set은 파일 λ””μŠ€ν¬λ¦½ν„° 번호λ₯Ό λ°°μ—΄λ‘œ κ°€μ§€λŠ” 'λΉ„νŠΈ ν•„λ“œ'ꡬ쑰체이닀. select()λŠ” fd_set을 μˆœνšŒν•˜λ©°, fd_set값이 1인 νŒŒμΌμ— λŒ€ν•΄ 읽기 λ˜λŠ” μ“°κΈ°λ₯Ό κ²€μ‚¬ν•˜κ³  λ³€ν™”κ°€ 생긴 fd_set을 1둜 ν•œλ‹€. ( μ—†λ‹€λ©΄ λ‹Ήμ—°νžˆ 0으둜 ν•œλ‹€. )

fd_set을 μ œμ–΄ν•˜λŠ” 맀크둜 ν•¨μˆ˜λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

ν•¨μˆ˜ μ„€λͺ…
FD_ZERO(*fds) fd_set을 μ΄ˆκΈ°ν™”ν•œλ‹€. λͺ¨λ“  값을 0으둜 ν•œλ‹€.
FD_SET(fdnum, *fds) fdnum(파일 번호)을 fd_setμ—μ„œ 1둜 ν•œλ‹€. select()λŠ” 이 νŒŒμΌμ„ κ²€μ‚¬ν•œλ‹€.
FD_ISSET(fdnum, *fds) fdnum이 fd_setμ—μ„œ 1인지 κ²€μ‚¬ν•œλ‹€.
FD_CLR(fdnum, *fds)) fd_setμ—μ„œ fdnum을 μ œκ±°ν•œλ‹€. 더이상 관리할 ν•„μš”κ°€ 없을 λ•Œ μ‚¬μš©ν•œλ‹€.

이제 select()둜 μ†ŒμΌ“λ“€μ˜ μž…μΆœλ ₯을 κ΄€λ¦¬ν•˜λŠ” 방법을 μ•Œμ•„λ³΄μž.
λ¨Όμ € 7개의 μ†ŒμΌ“μ„ λ§Œλ“€μ—ˆκ³ , 각 μ†ŒμΌ“μ€ 3~9κΉŒμ§€ fdnum을 λΆ€μ—¬λ°›μ•˜λ‹€κ³  κ°€μ •ν•˜μž. 그럼 fd_set의 λͺ¨μŠ΅μ€ λ‹€μŒκ³Ό 같을 것이닀.

fd_set* readfds

fdnum 0 1 2 3 4 5 6 7 8 9
bit 0 0 0 0 0 0 0 0 0 0

이제 3,5,8 μ†ŒμΌ“μ— λŒ€ν•΄ 읽기λ₯Ό κ²€μ‚¬ν•˜κΈ° μœ„ν•΄ 3, 5, 8λ²ˆμ„ λ“±λ‘ν•œλ‹€.

FD_SET(3, &readfds);
FD_SET(5, &readfds);
FD_SET(8, &readfds);

fd_set* readfds

fdnum 0 1 2 3 4 5 6 7 8 9
bit 0 0 0 1 0 1 0 0 1 0

select()둜 fd_set을 κ²€μ‚¬ν•œλ‹€.

nfdsκ°€ 9인 μ΄μœ λŠ” 검사할 λΉ„νŠΈκ°€ λ°°μ—΄ λ²ˆν˜Έμƒ 9λ²ˆλΉ„νŠΈ κΉŒμ§€μ΄κΈ° λŒ€λ¬Έμ΄λ‹€.
select(9, &readfds, (fd_set_)0, (fd_set_)0, NULL);
예λ₯Όλ“€μ–΄ 3번과 5λ²ˆμ—μ„œ λ³€ν™”κ°€ 생겼닀면 fd_set의 λͺ¨μŠ΅μ€ λ‹€μŒμ²˜λŸΌ λ³€ν•œλ‹€

fd_set* readfds

fdnum 0 1 2 3 4 5 6 7 8 9
bit 0 0 0 1 0 1 0 0 0 0
  • fd_set은 이전 μƒνƒœλ₯Ό μœ μ§€ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ λ‹€μ‹œ 또 3, 5, 8번 μ†ŒμΌ“μ„ κ²€μ‚¬ν•˜κ³  μ‹Άλ‹€λ©΄ λ‹€μ‹œ FD_SET으둜 λ“±λ‘μ‹œν‚€κ³  μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.

select둜 λͺ¨λ“  μ†ŒμΌ“ 쀑에 λ­”κ°€ λ³€ν™”κ°€ μžˆλŠ” μ†ŒμΌ“μ΄ μžˆλŠ”μ§€ μ•Œμ•„λƒˆμœΌλ‹ˆ 이제 FD_ISSET으둜 μ–΄λ–€ μ†ŒμΌ“μ— λ³€ν™”κ°€ μžˆλŠ”μ§€ 검사λ₯Ό ν•  수 μžˆλ‹€

FD_SET(int fd, fd_set* fdset) // fdset의 fd번째 인자λ₯Ό 1둜 set (fd번 μ†ŒμΌ“μ„ 1둜 μ˜¬λ¦°λ‹€λŠ” μ†Œλ¦¬)
FD_ISSET(int fd, fd_set* fdset) // fdset의 fd번째 인자 값을 return

μœ„ μ˜ˆμ—μ„œ 3번과 5번 μ†ŒμΌ“μ— λ³€ν™”κ°€ μžˆμ—ˆμœΌλ‹ˆ

read_fds의 fd_arryaλŠ” [0][0][0][1][0][1][0] ...

FD_ISSET(3, &read_fds) 와 FD_ISSET(5, &read_fds)의 값은 1이 될 것이고
λ°˜λ³΅λ¬Έμ„ λŒλ©΄μ„œ μ†ŒμΌ“ 0λ²ˆλΆ€ν„° μ΅œλŒ€ μ†ŒμΌ“λ²ˆν˜Έ n κΉŒμ§€ μˆœνšŒν•˜λ©° read_fdsλ₯Ό κ²€μ‚¬ν•˜λ©΄ μ–΄λ–€ μ†ŒμΌ“μ΄ 데이터λ₯Ό μˆ˜μ‹  λ°›μ•˜λŠ”μ§€ μ•Œ 수 μžˆλ‹€.

좜처

[글그리 λΈ”λ‘œκ·Έ]