[ํ’€์Šคํƒ] TCP ๋น„๋™๊ธฐ์‹ socket server programming

2023. 4. 16. 03:47ใ†ComputerScience/FullStackProgramming

 

 

 

socketserver์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๋น„๋™๊ธฐ์‹ 1:N programming

  • [์ ‘๊ทผ1] Socket API ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ
    • Socket API๋Š” ๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ ์œ ์‚ฌํ•จ
    • Socket API๋งŒ์œผ๋กœ 1:N ์„œ๋ฒ„๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๋„ ๋‹น์—ฐํžˆ ๊ฐ€๋Šฅํ•จ
    • 40๋…„ ์ „ํ†ต์˜ ์›์กฐ ๋ง›์ง‘ ํ”„๋กœ๊ทธ๋ž˜๋ฐ
  •  [์ ‘๊ทผ2] ์–ธ์–ด๋ณ„ ์ฐจ๋ณ„ํ™” ๋œ Socket ๊ธฐ๋Šฅ์œผ๋กœ ๊ฐœ๋ฐœ
    • ์ตœ์‹  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋Š” ๋ณด๋‹ค ํ–ฅ์ƒ๋œ Socket ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•จ
    • ์ตœ์‹  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ Socket ๊ธฐ๋Šฅ์œผ๋กœ ๋น ๋ฅธ ๊ฐœ๋ฐœ๊ณผ ์•ˆ์ •์ ์ธ ์„ฑ๋Šฅ ์ œ๊ณต์ด ์šฉ์ดํ•จ
    • ์ด๊ฑด ์–ธ์–ด์— ๋”ฐ๋ผ ์žˆ์„ ์ˆ˜๋„ ์žˆ๊ณ , ์—†์„ ์ˆ˜๋„ ์žˆ๋‹ค. ex) cpp ์ด๋Ÿฐ๊ฑฐ ๋ชปํ•  ์ˆ˜ ์žˆ๋‹ค. 
  • [๋ณธ ๊ฐ•์˜์˜ ์˜ˆ์ œ] Python์— ๋Œ€ํ•œ [์ ‘๊ทผ2]๋กœ ๊ตฌํ˜„
    • socketserver๋ฅผ ํ†ตํ•ด ์‰ฝ๊ฒŒ Socket ์„œ๋ฒ„ ๊ฐœ๋ฐœ์ด ๊ฐ€๋Šฅ
    • Multi-threading/process ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์‰ฝ๊ฒŒ ๋น„๋™๊ธฐ์‹ Socket ์„œ๋ฒ„ ๊ฐœ๋ฐœ์ด ๊ฐ€๋Šฅ

 

 

 

 

socketserver ๊ธฐ๋ฐ˜ TCP Echo Server ๊ฐœ๋ฐœ

Python์˜ socketserver๋ž€? 

  • ์ด๋ฏธ ์„œ๋ฒ„ class๊ฐ€ ์กด์žฌํ•œ๋‹ค! 
  • Socket ๊ธฐ๋ฐ˜ ๋„คํŠธ์›Œํฌ ์„œ๋ฒ„ ๊ฐœ๋ฐœ์„ ์ง€์›ํ•˜๋Š” Python ๋ชจ๋“ˆ -> ์›ฌ๋งŒํ•˜๋ฉด ์•Œ์•„์„œ ๋Œ์•„๊ฐ€๊ฒŒ ํ•จ
  • 4๊ฐ€์ง€ ์œ ํ˜•์˜ ์„œ๋ฒ„ ํด๋ž˜์Šค๋ฅผ ์ œ๊ณต

class socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)

optional : IP, Port number 

์–ด๋–ป๊ฒŒ ๊ฐœ๋ฐœ์ž๋“ค์ด ํŽธํ•˜๊ฒŒ ์งค ์ˆ˜ ์žˆ์„๊นŒ?
์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ์ด ํ•ด์•ผํ•  ์ผ์€ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค
์–ด๋–ค ๋ฐ์ดํ„ฐ๋“ , ํ”„๋กœ๊ทธ๋žจ์ด๋“  ์„œ๋ฒ„๊ฐ€ ํ•  ์ผ๋ฐ˜์ ์ธ ์ผ
-> server ๊ฐ์ฒด๋กœ ๋„์›€ (๊ฐ€์žฅ ์ตœ์†Œํ•œ์˜ ์ •๋ณด)

๊ฐœ๋ฐœ์ž๊ฐ€ ๊ด€์‹ฌ์žˆ๋Š” ๊ฒƒ : ํŠน์ • ๊ฐ’, ์ •๋ณด, ๋ช…๋ น์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ 
ํ†ต์ƒ requestHandler ์— ๊ตฌํ˜„ํ•œ๋‹ค. (custom)
๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋กœ์ง์„ ํ•ธ๋“ค๋Ÿฌ์— ๋„ฃ์–ด ๋‘”๋‹ค.
๊ทธ๋Ÿผ ์„œ๋ฒ„ํ•œํ…Œ, ๋‹ˆ๊ฐ€ ๋ฐ›์œผ๋ฉด ํ•ธ๋“ค๋Ÿฌ์—๊ฒŒ ๋„ฃ์–ด์ค˜!

 

 

 

 

socketserver.TCPServer ๊ธฐ๋ฐ˜์˜ TCP ์„œ๋ฒ„ ๋งŒ๋“œ๋Š” ์ ˆ์ฐจ

1. You must create a request handler class by subclassing the BaseRequestHandler class and overriding its handle() method

- this method will process incoming requests. -> ๋ฆฌํ€˜์ŠคํŠธ ์š”์ฒญ๋“ค์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์†Œ๋“œ
- ์ด๋ฏธ ๋ฒ ์ด์Šค ๋ฆฌํ€˜์ŠคํŠธ ํ•ธ๋“ค๋Ÿฌ์˜ ํ…œํ”Œ๋ฆฟ์ด ์žˆ๋‹ค. 
- ์šฐ๋ฆฌ๋Š” handle (๋ฏธ๋‹ˆ๋ฉˆ) ๋ฉ”์†Œ๋“œ์—๋งŒ ์†์„ ๋Œˆ ๊ฒƒ์ด๋‹ค. 

2. You must instantiate one of the server classespassing it the server’s address and the request handler class. 

- It is recommended to use the server in a with statement.

3. Call the handle_request() or serve_forever() method of the server object to process one or many requests.

- ์šฐ๋ฆฌ๊ฐ€ ์‹คํ–‰ํ•˜๋ฉด, ๋‚ด๋ถ€์ ์œผ๋กœ ์˜์›ํžˆ ์„œ๋ฒ„๋ฅผ ์‚ด๋ ค๋‘”๋‹ค. 

4. Call server_close()to close the socket (unless you used a with statement).

 

 

 

[ ์žฅ์  ]

- ์ด์ œ ํ•˜๋‚˜์˜ ํด๋ผ์ด์–ธํŠธ ์‘๋‹ต ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ์˜ ์‘๋‹ต์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. 

- 1:1 -> import socket 

- 1:N -> import socketserver

- socket, bind ๋“ฑ์˜ ํ•จ์ˆ˜๊ฐ€ ๋ชจ๋‘ ์‚ฌ๋ผ์ง 

- handle() ํ•จ์ˆ˜ ๋‚ด๋ถ€์—, ํ•ธ๋“ค๋Ÿฌ ๋™์ž‘์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋

 

[ ๋‹จ์  ]

- ๋™์‹œ ์ง€์› ๊ฐ€๋Šฅํ•œ client๋Š” 1๊ฐœ ๋ฟ์ด๋‹ค. 

- ๋‹ค๋ฅธ ํด๋ผ์ด์–ธํŠธ๋“ค์€ ์„œ๋น„์Šค ์ค‘์ธ ํด๋ผ์ด์–ธํŠธ ์ข…๋ฃŒ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•œ๋‹ค. 

- ์ฆ‰, ๋™๊ธฐ์‹์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. (๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ X)

 

 

 

socketserver.TCPServer ๊ธฐ๋ฐ˜ Echo-Server ๋ฌธ์ œ์ 

  • Each request must be completed before the next request can be started.
  • This isn’t suitable if each request takes a long time to complete, because it requires a lot of computation, or because it returns a lot of data which the client is slow to process.
  • The solution is to create a separate process or thread to handle each request;
    the 
    ForkingMixIn and ThreadingMixIn mix-in classes can be used to support asynchronous behaviour.
    -> fork: ๋ฉ€ํ‹ฐ ํ”„๋กœ์„ธ์Šค, threading: ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ 

 

 

 

๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ

๋™๊ธฐ์‹ ๋™์ž‘๊ณผ ๋น„๋™๊ธฐ์‹ ๋™์ž‘์€ ๋ฌด์—‡์ธ๊ฐ€?

  • ๋™๊ธฐ์‹ ์ฒ˜๋ฆฌ
    • ์ง„ํ–‰์ค‘์ธ ์ž‘์—…์ด ์žˆ์œผ๋ฉด, ๋‹ค์Œ ์ž‘์—…์€ ํ˜„์žฌ ์ง„ํ–‰ ์ž‘์—… ์ข…๋ฃŒ ํ›„ ์ฒ˜๋ฆฌ
    • ํ†ต์ƒ blocking ์ฒ˜๋ฆฌ๋ผ๊ณ  ํ•จ
    • ํ˜„์žฌ ์‹คํ–‰ ๋ง๊ณ ๋Š” ๋‹ค ์•ˆ ๋ฐ›์•„์ฃผ๊ฒ ๋‹ค - blocking
  • ๋น„๋™๊ธฐ์‹ ์ฒ˜๋ฆฌ
    • ์ง„ํ–‰์ค‘์ธ ์ž‘์—…์ด ์žˆ์–ด๋„, ๋‹ค์Œ ์ž‘์—…์ด ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์‹คํ–‰
    • ํ†ต์ƒ non-blocking ์ฒ˜๋ฆฌํ•˜๊ณ  ํ•จ
    • ํด๋ผ์ด์–ธํŠธ ์ž…์žฅ, ์„œ๋ฒ„ํ•œํ…Œ ๋ฐ์ดํ„ฐ ์š”์ฒญ ๋ณด๋‚ด๋†“๊ณ , ๋ณธ์ธ์€ ๋‚จ์€ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ํ•˜๋Š” ๋“ฑ ๋น„๋™๊ธฐ์ ์ธ ๋™์ž‘
    • ์„œ๋ฒ„ ์ž…์žฅ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋™์‹œ์— ๋ฐ›์•„์ฃผ๋Š” ๊ฒƒ

 

 

 

Multi-Thread/Process๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

  • “์ผ๊พผ์ด ๋˜๋Š” ํ”„๋กœ๊ทธ๋žจ ๊ฐœ์ˆ˜๋ฅผ ์ฆ๊ฐ€"
  • Multi-Process์™€ Multi-Thread๊ฐ€ ์ผ๋ฐ˜์ ์ž„

1) Multi-Process
๋…๋ฆฝ์ ์ธ ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰
์ฃผ๋กœ 
fork()๋กœ ์‹คํ–‰

์‹คํ–‰ ํŒŒ์ผ์„ ์‹คํ–‰ํ•œ ํ›„ 
์ปดํ“จํ„ฐ ๋ฉ”๋ชจ๋ฆฌ ์œ„์— ์˜ฌ๋ผ์˜จ ์ƒํ™ฉ
ํ•˜๋‚˜ ๋” ์‹คํ–‰ํ•˜๋ฉด -> ๋ณ„๋„์˜ ์ฝ”๋“œ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ๋…๋ฆฝ์ ์œผ๋กœ ์˜ฌ๋ผ๊ฐ (multi process)

์ฆ‰, ๋‘ ๊ฐœ ์ด์ƒ์˜ ์‹คํ–‰ ํŒŒ์ผ์„ ๋™์‹œ์— ์‹คํ–‰์‹œํ‚จ ๊ฒƒ 

 

2) Multi-Thread (๋ณธ ๊ฐ•์˜ ์‚ฌ๋ก€)

๋ฐ์ดํ„ฐ๋ฅผ ๊ณต์œ ํ•˜๋Š” ์ผ๊พผ

์ถ”๊ฐ€ ์ผ๊พผ์„ Thread ๋ผ๊ณ  ์นญํ•จ

Process ๋ณด๋‹ค ์ž์› ์š”๊ตฌ ์ ์Œ

 

ํ”„๋กœ์„ธ์Šค ๊ฐ„ ๊ณต์œ ํ•˜๊ฒŒ ๋˜๋ฉด, ๋” ๊ฐ€๋ณ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ž–์•„?
๋…๋ฆฝ์ ์œผ๋กœ ์Šค๋ ˆ๋“œ๋ฅผ ๋„์›Œ๋ดค์ž, ๋„ˆ๋ฌด ๋ฌด๊ฑฐ์›€
๊ณต์œ ํ•  ๊ฑด ๊ณต์œ ํ•˜๊ณ , ๊ทธ ์•ˆ์—์„œ ์ผ๊พผ๋“ค์„ (๊ธฐ๋Šฅ, ์ž‘์—…์„) ๋ถ„๋‹ดํ•ด์„œ ์ฒ˜๋ฆฌํ•˜์ž -> ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ


ํ”„๋กœ๊ทธ๋žจ์ด ํ•˜๋‚˜๋งŒ ์‹คํ–‰๋œ๋‹ค.
๊ณต์œ ํ•  ๋ฐ์ดํ„ฐ๋Š” ๊ณต์œ ํ•˜๋ฉฐ, ํ•จ์ˆ˜ ํ•˜๋‚˜, ํด๋ž˜์Šค ํ•˜๋‚˜ ๊ฐ๊ฐ์„ ์—ฌ๋Ÿฌ ๊ฐœ ๋„์šด๋‹ค
์‹คํ–‰ ํŒŒ์ผ ํ•˜๋‚˜ ์‹คํ–‰์‹œ์ผฐ์œผ๋‚˜, ๊ทธ ์•ˆ์—์„œ ํ•จ์ˆ˜ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋น„๋™๊ธฐ ์ž‘์—…์„ ํ•˜๊ฑฐ๋‚˜ ๋“ฑ๋“ฑ

 

[ ์žฅ์  ]

- ์ž์› ์š”๊ตฌ์‚ฌํ•ญ์ด ์ž‘๋‹ค

- ์Šค๋ ˆ๋“œ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ๋งŒ๋“ค๋ฉด, ์šด์˜์ฒด์ œ๊ฐ€ ์ฝ”์–ด๋งˆ๋‹ค ๋‚˜๋ˆ ์ค€๋‹ค -> ํ”„๋กœ๊ทธ๋žจ ์„ฑ๋Šฅ ํ–ฅ์ƒ ok

 

 

 

๋น„๋™๊ธฐ์‹ TCP socketserver ๊ฐœ๋ฐœ

ํŒŒ์ด์ฌ, ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๋Š” 1:N ์„œ๋ฒ„ -> ์•„์ฃผ ์‰ฝ๊ฒŒ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ฅผ ๊ตฌํ˜„

 

[๋‹จ๊ณ„1] socketserver์˜ multi-thread ๋ฒ„์ „ ์ƒ์„ฑ

  • Forking and threading versions of each type of server can be created using these mix-in classes.
  • ์•„๋ฌด ๋™์ž‘๋„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๋ฉด -> ๊ทธ ์™ธ์—๋Š” ํ•  ๊ฒŒ ์—†๋‹ค. 
  • The mix-in class comes first, since it overrides a method defined in socketserver. 
    Setting the various attributes also changes the behavior of the underlying server mechanism.

 

  • Threadingmixin ๋จผ์ €, ์ดํ›„ tcp server ์‹คํ–‰ ๋จ
  • ๋‘ ๊ฐœ์˜ ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ, threaded TCP ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์–ด๋‚ธ ๊ฒƒ
  • Threadingmixin - ๊ธฐ์กด tcp ์„œ๋ฒ„์— ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋”ฉ์„ ๊ตฌํ˜„ํ•˜๊ธฐ์œ„ํ•œ ์ด๊ฑธ ์ถ”๊ฐ€ํ•˜๋ฉด, ๊ทธ๋ƒฅ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ๋จ
  • Threadingmixin class
    -> 
    ๋ณธ์ธ ์Šค์Šค๋กœ๋ถ€ํ„ฐ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์—ˆ์„ ๋•Œ ๋ณ„ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค 
    ๋‹ค๋ฅธ ํด๋ž˜์Šค์— ํฌํ•จ์ด ๋˜์—ˆ์„ ๋•Œ ์œ ์˜๋ฏธ
  • ex) ์ด ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฐ์ฒด์˜ ์ˆ˜๋Š” ๋ช‡ ๊ฐœ์ด๋ƒ? 
    ์ผ์ข…์˜ ํˆด ์ฒ˜๋Ÿผ ์“ฐ์ด๋Š” ํด๋ž˜์Šค๋“ค -> mixIn์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค
    ํ•„์š”ํ•  ๋•Œ ์ด๋Ÿฐ ์• ๋“ค์„ ๋ณธ์ธ ํด๋ž˜์Šค์— ์ง‘์–ด๋„ฃ๋Š”๋‹ค. ex) objective-C

 

 

[๋‹จ๊ณ„2] socketserver์˜ Request Handler๋ฅผ ์ˆ˜์ •

  • To implement a service, you must derive a class from BaseRequestHandler and redefine its handle() method.
    ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€ - echo ๋Œ๋ ค๋ณด๋‚ด๋Š” ๋™์ž‘ ๋ฟ 
    ์ด์ œ๋Š” ์ด๊ฒŒ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์ฒ˜๋ฆฌ๊ฐ€ ๋˜์–ด, ์Šค๋ ˆ๋“œ 1, 2, 3 ๋กœ ๋„์šด๋‹ค
  • You can then run various versions of the service by combining one of the server classes with your request handler class.
  • The request handler class must be different for datagram or stream services. This can be hidden by using the handler subclasses StreamRequestHandler or DatagramRequestHandler.
  • ์–ด๋Š ์Šค๋ ˆ๋“œ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋Š”์ง€ ๋ณด์—ฌ์ฃผ๊ณ ์ž cur_thread.name์„ ๋„์› ์ง€๋งŒ, ์ด๊ฑฐ ์ง€์šฐ๋ฉด ์•ž์˜ 1:1์ด๋ž‘ ์ฝ”๋“œ ๋˜‘๊ฐ™๋‹ค
    ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š”, ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œํ™” ํ•  ๋•Œ, ํ•ธ๋“ค๋Ÿฌ ๋‚ด๋ถ€์— ๋” ํ•ด์ค„ ์ž‘์—… ์—†์Œ 

 

 

[๋‹จ๊ณ„3] Main Thread ์„ค์ • ๋ฐ ์‹คํ–‰

  • When inheriting from ThreadingMixIn for threaded connection behavior, you should explicitly declare how you want your threads to behave on an abrupt shutdown.
  • ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ์˜ ์ฒ ํ•™
    ์Šค๋ ˆ๋“œ๋ฅผ ๋„์šฐ๊ณ  ๋‚˜๋ฉด - ์šด์˜์ฒด์ œ๋Š” ๊ฐ๊ฐ ๋…๋ฆฝ์ ์œผ๋กœ ๋ฐ”๋ผ๋ณธ๋‹ค. 
    ๊ฐ™์ด ์ฃฝ์„๊ฑฐ๋ƒ? ๋ชจ๋‘ ๋…๋ฆฝ์ ์œผ๋กœ ์ฃฝ์„ ๊ฒƒ์ด๋ƒ?
    1) ํ”„๋กœ๊ทธ๋žจ์ด ์ฃฝ์œผ๋ฉฐ, ํ˜„์žฌ ๋„์šด ์Šค๋ ˆ๋“œ๋ฅผ ๋‹ค ์ข…๋ฃŒ์‹œํ‚ค๊ณ  ์‹ถ์„ ๋•Œ
    -> ํ”„๋กœ๊ทธ๋žจ์˜ ์ข…๋ฃŒ๋Š” ๋งˆ์ง€๋ง‰ ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋˜์ง€?
    or 2) ํ”„๋กœ๊ทธ๋žจ์€ ์ฃฝ๊ณ , ์Šค๋ ˆ๋“œ๋“ค์€ ๋…๋ฆฝ์ ์œผ๋กœ ์ฃฝ๋Š”๋‹ค 
  • The ThreadingMixIn class defines an attribute daemon_threads, which indicates whether or not the server should wait for thread termination.
    daemon ๊ฐ’์œผ๋กœ ๊ธฐ๋‹ค๋ฆด๊ฑฐ๋ƒ ๋ง๊ฑฐ๋ƒ๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. 
  • You should set the flag explicitly if you would like threads to behave autonomously; 
    the default is False, meaning that Python will not exit until all threads created by ThreadingMixIn have exited.
  • ์„œ๋ฒ„๊ฐ€ ์ฃฝ์„ ๋•Œ ํ•  ์ผ์ด ๋งŽ๋‹ค. (DB ๋‹ซ๊ณ  ๋“ฑ๋“ฑ) -> ์˜ˆ์˜๊ฒŒ ์ฃฝ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

 

 

  • threading.Thread(target=server.serve_forever)
    • This constructor should always be called with keyword arguments.
    • target is the callable object to be invoked by the run() method.
    • ์„œ๋ฒ„๋ฅผ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋กœ ๋„์›€ -> server.serve_forever ์–˜๋กœ๋ถ€ํ„ฐ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ๋œจ๋Š” ์”จ๋“œ๊ฐ€ ๋จ
  • server_thread.start()
    • Start the thread’s activity.
    • ์†์„ ์•ˆ ๋Œ€๊ณ , ๊ทธ๋ƒฅ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ ์‹คํ–‰
  • threading.active_count()
    • Return the number of Thread objects currently alive.
    • ์‚ด์•„์žˆ๋Š” ์Šค๋ ˆ๋“œ์˜ ์ˆ˜ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด
  • server_thread.run()
    • Method representing the thread’s activity.
    • You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument.
    • ๋ฉ”์ธ ๋„์šฐ๋ฉด์„œ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ญ”๊ฐ€ ํ•˜๊ณ ์‹ถ๋‹ค? -> ๋Ÿฐ ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ
  • Threadingmixin์œผ๋กœ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋”ฉ์„ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค! 

 

 

 

Socket Programming (N:M) 
๋น„๋™๊ธฐ์‹ TCP Chatting ์„œ๋น„์Šค ๊ฐœ๋ฐœ 

  • ๋น„๋™๊ธฐ์‹ TCP socketserver๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ 1:N ์ฑ„ํŒ…์„ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ ํ˜•ํƒœ์˜ server์™€ client๋ฅผ ๊ฐœ๋ฐœ
  • ํด๋ผ์ด์–ธํŠธ ํ•˜๋‚˜๊ฐ€ ๋ณด๋‚ธ ์ •๋ณด๋ฅผ ๋‹ค๋ฅธ ์• ๋“คํ•œํ…Œ๋„ ๋ฟŒ๋ฆผ -> ๋ฉ€ํ‹ฐ ์บ์ŠคํŠธ -> ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์ด ํ•„์š”ํ•จ 

 

  • Server ๋ณ€๊ฒฝ ๋‚ด์šฉ
    • (์†Œ์Šค์ฝ”๋“œ์˜ {CHAT๋ถ€๋ถ„) -> CHAT์ด ๋ฐ”๋€ ๋ถ€๋ถ„ 
    • ๋ชจ๋“  client์˜ socket ์—ฐ๊ฒฐ ์ •๋ณด๋ฅผ ์ €์žฅํ•ด๋‘”๋‹ค (๋“ฑ๋ก ๋ฐ ์‚ญ์ œ)
      N๊ฐœ์˜ ์œ ์ €๋ฅผ ํ•˜๋‚˜์˜ ์ฑ„ํŒ…๋ฐฉ์œผ๋กœ ๋„ฃ๋Š” ๊ฒƒ
    • ํŠน์ • client๊ฐ€ ์ „์†กํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ชจ๋“  client๋“ค์— ์ „๋‹ฌํ•จ 
    • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ
      ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ๋Š” ๋ณด๋‚ด๊ณ , ๊ธฐ๋‹ค๋ ธ๋‹ค.
      new ํด๋ผ์ด์–ธํŠธ -> ๋ณธ์ธ์ด ๋ณด๋‚ด๋ฉด์„œ, ์„œ๋ฒ„๋ฅผ ํ†ตํ•ด ๋ฉ”์„ธ์ง€๋ฅผ ๋ฐ›์„ ์ˆ˜ ์žˆ๋„๋ก
      ์ฆ‰, ์–‘๋ฐฉํ–ฅ ์ฑ„ํŒ…์ด ๊ฐ€๋Šฅํ•˜๋„๋ก, ํด๋ผ์ด์–ธํŠธ๋ฅผ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œํ™” ํ•  ๊ฒƒ
  • Client ๋ณ€๊ฒฝ ๋‚ด์šฉ
    • Thread๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, ์ „์†ก๊ณผ ์ˆ˜์‹ ์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋ถ„๋ฆฌํ•จ
    • ์ˆ˜์‹  Thread๋ฅผ ํ†ตํ•ด์„œ, ์„œ๋ฒ„๋กœ ๋ถ€ํ„ฐ์˜ ์ „์†ก์— ํ•ญ์ƒ ์ค€๋น„ํ•จ
    • ํด๋ผ์ด์–ธํŠธ ๊ตฌํ˜„
      ์ˆ˜์‹ ์€ ์Šค๋ ˆ๋“œํ™” -> ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋กœ ๋Œ๋ฆผ
      ์‚ฌ์šฉ์ž์™€์˜ ๋Œ€ํ™” -> ๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„

 

  • Client
  • ๋„ค์ž„๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ธฐ๋ฒ•
    • ํฌ์ง€์…”๋„ํ•˜๋‹ค = ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฑ ๋•Œ๋ ค๋„ฃ๋Š” ํ˜ธ์ถœ
    • ๋ณ€์ˆ˜๋“ค์˜ ์ด๋ฆ„์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค
    • ํ˜ธ์ถœ์„ ํ•  ๋•Œ, ํฌ์ง€์…”๋„ํ•˜์ง€ ์•Š๊ณ , ์ž…๋ ฅ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ด๋ฆ„์„ ์ฃผ๋Š” ๊ฒƒ 
    • ์ˆœ์„œ ์—†์ด ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ˆœ์„œ ๋’ค์ง‘์–ด์ง„ ์ฑ„ ์ „๋‹ฌํ•ด๋„ ๊ดœ์ฐฎ๋‹ค. 
    • ์™œ ์ด๋Ÿฐ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉ? 
    • ์ž…๋ ฅ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ 10๊ฐœ์•ผ -> ์ „๋ถ€ ๋‹ค ์ค„ ์ˆ˜ ์—†๋‹ค 
    • ๋”ฐ๋ผ์„œ ๋Œ€๋ถ€๋ถ„ ๋””ํดํŠธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ (๋‚˜์ค‘์— ํ˜ธ์ถœํ•  ๋•Œ๋Š”, ํ•œ ๋‘๊ฐœ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ’๋งŒ ์ง€์ •ํ•˜๊ณ  ์‹ถ์„ ๋•Œ)

 

  • Server
  • group_queue๋กœ ์ผ์ข…์˜ DB๋ฅผ ๋งŒ๋“  ๊ฒƒ 
  • ํ•ด๋‹น ํ์— IP ์ฃผ์†Œ์™€ Port ๋ฒˆํ˜ธ ๋“ฑ๋“ฑ ์ •๋ณด๊ฐ€ ๋“ค์–ด์žˆ๋Š” request๋ฅผ ๋„ฃ๋Š”๋‹ค

 

 

 

 

 

 

 

socketserver ๊ธฐ๋ฐ˜ UDP Echo ์„œ๋น„์Šค ๊ฐœ๋ฐœ

  • TCP socketserver ์ฒ˜๋Ÿผ ๊ฐœ๋ฐœํ•จ
  • ์—ฐ๊ฒฐ ์„ค์ •, ํ•ด์ œ ๊ณผ์ •์ด ์—†๋‹ค
  • socketserver.TCPServer ๋Œ€์‹  socket server.UDPServer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Echo Server๋ฅผ ๊ฐœ๋ฐœ
  • UDP๋Š” connection-less ๋ฐฉ์‹์œผ๋กœ connect() ์ ˆ์ฐจ๊ฐ€ ์—†์Œ

 

  •  Client
    • ๋ฉ”์ธ์—์„œ ์—ฐ๊ฒฐ ์š”์ฒญ, ํ•ด์ œํ•˜๋Š” ๋ถ€๋ถ„์ด ์‚ฌ๋ผ์ง
    • connect() ํ•จ์ˆ˜ ํ˜ธ์ถœ X (connection-less)
    • Handler์—์„œ๋Š” ์ˆ˜์ •์ด ๊ฑฐ์˜ ์—†๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์œผ๋ฉด, ๋ฐ”๋กœ print

 

 

 

socketserver ๊ธฐ๋ฐ˜ UDP ์ฑ„ํŒ… ์„œ๋น„์Šค ๊ฐœ๋ฐœ

  • Connection-less์ธ ๊ด€๊ณ„๋กœ, ์„œ๋ฒ„์—์„œ client ๋“ค์˜ ์ •๋ณด๋ฅผ ์ง์ ‘ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•จ
    • UDP๋Š” TCP ์—ฐ๊ฒฐ ํ•ด์ œ์ฒ˜๋Ÿผ ๋งคํ•‘ํ•  ๊ฒƒ์ด ์—†๋‹ค -> ์ง์ ‘ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.
    • Client๋“ค์ด ์ง์ ‘ ํŠน์ˆ˜ ๋ช…๋ น์–ด(#REG, #DEREG)์„ ํ†ตํ•ด์„œ ์„œ๋ฒ„์— ๋“ฑ๋ก/ํ•ด์ œ ํ•˜๋Š” ์ ˆ์ฐจ๋ฅผ ๊ตฌํ˜„ํ•จ
    • ์ผ์ข…์˜ ํ”„๋กœํ† ์ฝœ(ํ†ต์‹ ์˜ ์•ฝ์†)์„ ๊ฐ•์ œ๋กœ ๋งŒ๋“  ๊ฒƒ 
    • ๋“ฑ๋ก( #REG)๋œ client ๋“ค์— ๋Œ€ํ•ด์„œ, ํŠน์ • ์‚ฌ์šฉ์ž์˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋ชจ๋“  ๋“ฑ๋ก๋œ client๋“ค์— ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•จ