๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป ๐ŸŒฎ ๐Ÿ’ฌ
๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป/python

[python] socket ๋™์‹œ ์—ฐ๊ฒฐ

by ๋ฐ”์ฟ„๋ฆฌ 2024. 10. 22.

์ตœ๊ทผ์— ๊ฐœ๋ฐœํ•œ ๊ธฐ๋Šฅ ์ค‘์— 2๊ฐœ์˜ ๋กœ๋ด‡๊ณผ socket ํ†ต์‹ ์ด ์žˆ์—ˆ๋‹ค.

2๊ฐœ์˜ ๋กœ๋ด‡์— ๋™์‹œ์— ์š”์ฒญ์ด ๋“ค์–ด๊ฐ€๋ฉด 1๋ฒˆ ๋กœ๋ด‡ → 2๋ฒˆ ๋กœ๋ด‡ ์ด๋ ‡๊ฒŒ ์ˆœ์„œ๋Œ€๋กœ ์ง„ํ–‰๋˜์–ด์„œ

๋™์‹œ์— ์ง„ํ–‰๋˜๋„๋ก ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

ํ™•์ธ

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ๋ฐฉ์‹, ๋น„๋™๊ธฐ ๋ฐฉ์‹ ๋‘๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ ์†Œ์ผ“ ์—ฐ๊ฒฐ์„ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์ฒ˜๋ฆฌํ•˜์—ฌ ๋‘ ๊ฐœ์˜ ์—ฐ๊ฒฐ์„ ๋™์‹œ์— ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค

import socket
import threading

# ์ฒซ ๋ฒˆ์งธ ์†Œ์ผ“ ์—ฐ๊ฒฐ ํ•จ์ˆ˜
def connect_to_robot_a():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('123.123.123.123', 65432))

    # ๋ฐ์ดํ„ฐ ์ „์†ก ์˜ˆ์‹œ
    data = "Hello from Robot A"
    s.sendall(data.encode())
    response = s.recv(1024).decode()
    print(f"Robot A response: {response}")
    s.close()

# ๋‘ ๋ฒˆ์งธ ์†Œ์ผ“ ์—ฐ๊ฒฐ ํ•จ์ˆ˜
def connect_to_robot_b():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('123.123.123.123', 65433))

    # ๋ฐ์ดํ„ฐ ์ „์†ก ์˜ˆ์‹œ
    data = "Hello from Robot B"
    s.sendall(data.encode())
    response = s.recv(1024).decode()
    print(f"Robot B response: {response}")
    s.close()

# ๋ฉ”์ธ ํ•จ์ˆ˜์—์„œ ๋‘ ์Šค๋ ˆ๋“œ๋ฅผ ์‹œ์ž‘
if __name__ == "__main__":
    thread_robot_a = threading.Thread(target=connect_to_robot_a)
    thread_robot_b = threading.Thread(target=connect_to_robot_b)

    # ๋‘ ์Šค๋ ˆ๋“œ ์‹œ์ž‘
    thread_robot_a.start()
    thread_robot_b.start()

    # ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
    thread_robot_a.join()
    thread_robot_b.join()

    print("Both connections completed.")

๋น„๋™๊ธฐ(asyncio) ๋ฐฉ์‹

๋น„๋™๊ธฐ ๋ฐฉ์‹์€ ์ด๋ฒคํŠธ ๋ฃจํ”„๋ฅผ ํ†ตํ•ด ๋‘ ์†Œ์ผ“ ์—ฐ๊ฒฐ์„ ๋™์‹œ์— ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ. ๋„คํŠธ์›Œํฌ I/O ์ž‘์—…์—์„œ๋Š” ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ณด๋‹ค ๋” ํšจ์œจ์ ์ด๋‹ค.

import asyncio

async def connect_to_robot_a():
    reader, writer = await asyncio.open_connection('123.123.123.123', 65432)

    # ๋ฐ์ดํ„ฐ ์ „์†ก ์˜ˆ์‹œ
    data = "Hello from Robot A"
    writer.write(data.encode())
    await writer.drain()

    # ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์‘๋‹ต ๋ฐ›๊ธฐ
    response = await reader.read(1024)
    print(f"Robot A response: {response.decode()}")

    writer.close()
    await writer.wait_closed()

async def connect_to_robot_b():
    reader, writer = await asyncio.open_connection('123.123.123.123', 65433)

    # ๋ฐ์ดํ„ฐ ์ „์†ก ์˜ˆ์‹œ
    data = "Hello from Robot B"
    writer.write(data.encode())
    await writer.drain()

    # ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์‘๋‹ต ๋ฐ›๊ธฐ
    response = await reader.read(1024)
    print(f"Robot B response: {response.decode()}")

    writer.close()
    await writer.wait_closed()

# ๋ฉ”์ธ ๋น„๋™๊ธฐ ํ•จ์ˆ˜
async def main():
    await asyncio.gather(
    	connect_to_robot_a(),
        connect_to_robot_b(),
    )

if __name__ == "__main__":
    asyncio.run(main())

 

์ •๋ฆฌ

๋น„๋™๊ธฐ(asyncio)์™€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ(threading)๋Š” ๊ฐ๊ฐ์˜ ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ ํ•ฉํ•œ ์„ ํƒ์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ,

์†Œ์ผ“ ํ†ต์‹ ๊ณผ ๊ฐ™์€ I/O ๋ฐ”์šด๋“œ ์ž‘์—…์—์„œ๋Š” ๋น„๋™๊ธฐ ๋ฐฉ์‹์ด ์ผ๋ฐ˜์ ์œผ๋กœ ๋” ๋‚˜์€ ์„ฑ๋Šฅ๊ณผ ํšจ์œจ์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค.

  ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ๋น„๋™๊ธฐ
์žฅ์  1. CPU ๋ฐ”์šด๋“œ ์ž‘์—…์—์„œ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ๊ฐ€๋Šฅ (๋‹จ, Python์˜ *GIL๋กœ ์ธํ•ด ํ•œ์ •์ ์ธ ๋ณ‘๋ ฌ์„ฑ)

2. ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์€ ์ „ํ†ต์ ์ธ ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์ด๋ฏ€๋กœ, ๋น„๋™๊ธฐ ๋ฐฉ์‹์— ๋น„ํ•ด ์ง๊ด€์ ์ธ ์ฝ”๋“œ ์ž‘์„ฑ์ด ๊ฐ€๋Šฅ

3. ์ด๋ฏธ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์— ์ต์ˆ™ํ•œ ๊ฒฝ์šฐ, ๊ตฌํ˜„๊ณผ ๋””๋ฒ„๊น…์ด ๋” ์‰ฌ์šธ ์ˆ˜ ์žˆ๋‹ค
1. ๋‹จ์ผ ์Šค๋ ˆ๋“œ์—์„œ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋™์‹œ์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์Šค๋ ˆ๋“œ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์—†์Œ

2. ๋„คํŠธ์›Œํฌ ํ†ต์‹ ๊ณผ ๊ฐ™์€ I/O ์ž‘์—…์—์„œ๋Š” ๋น„๋™๊ธฐ ๋ฐฉ์‹์ด ๋” ํšจ์œจ์ . CPU ์ž์›์„ ๊ฑฐ์˜ ์†Œ๋ชจํ•˜์ง€ ์•Š์œผ๋ฉฐ, I/O ์ž‘์—…์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๋‹ค๋ฅธ ์ž‘์—…์„ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ

3. ์†Œ์ผ“ ํ†ต์‹ ์ฒ˜๋Ÿผ ๋น„๋™๊ธฐ ๋„คํŠธ์›Œํฌ ์ž‘์—…์ด ๋งŽ์„ ๋•Œ, ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ๋‹ค

4. ์ฝ”๋“œ๊ฐ€ ๋ช…ํ™•ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฌ์šด ๊ตฌ์กฐ๋กœ ์ž‘์„ฑ ๊ฐ€๋Šฅ
๋‹จ์  1. ์Šค๋ ˆ๋“œ ์˜ค๋ฒ„ํ—ค๋“œ: ์Šค๋ ˆ๋“œ ์ƒ์„ฑ๊ณผ ๊ด€๋ฆฌ์— ์ถ”๊ฐ€์ ์ธ ๋ฉ”๋ชจ๋ฆฌ์™€ CPU ์ž์›์ด ์†Œ๋ชจ

2. ๋™๊ธฐํ™” ์ด์Šˆ: ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์€ ์ข…์ข… ๋ฐ๋“œ๋ฝ, ๋ ˆ์ด์Šค ์ปจ๋””์…˜๊ณผ ๊ฐ™์€ ๋ณต์žกํ•œ ๋ฌธ์ œ๋“ค์„ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.

3. ์†Œ์ผ“ ํ†ต์‹ ์ฒ˜๋Ÿผ I/O ์ž‘์—…์ด ๋งŽ์€ ํ™˜๊ฒฝ์—์„œ๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ *์œ ํœด ์ƒํƒœ๋กœ ๋Œ€๊ธฐ ํ•˜๋Š” ์‹œ๊ฐ„์ด ๋งŽ์•„์„œ ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ๋‹ค.
1. CPU ๋ฐ”์šด๋“œ ์ž‘์—…(์˜ˆ: ๋ฐ์ดํ„ฐ ๋ถ„์„, ๋ณต์žกํ•œ ๊ณ„์‚ฐ ๋“ฑ)์—์„œ๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค. ๊ทธ๋Ÿฐ ๊ฒฝ์šฐ์—๋Š” GIL(Global Interpreter Lock) ๋ฌธ์ œ๋กœ ์ธํ•ด asyncio๋งŒ์œผ๋กœ๋Š” ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๊ฐ€ ํž˜๋“ค ์ˆ˜ ์žˆ๋‹ค.

2. ๋น„๋™๊ธฐ ํŒจํ„ด์— ์ต์ˆ™ํ•˜์ง€ ์•Š๋‹ค๋ฉด ์ฝ”๋“œ ์ž‘์„ฑ ๋ฐ ๋””๋ฒ„๊น…์ด ์กฐ๊ธˆ ๋ณต์žกํ•  ์ˆ˜ ์žˆ๋‹ค.
์ถ”์ฒœ ์ƒํ™ฉ 1. ์†Œ์ผ“ ํ†ต์‹ , ํŒŒ์ผ ์ฝ๊ธฐ/์“ฐ๊ธฐ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ์™€ ๊ฐ™์€ I/O ๋ฐ”์šด๋“œ ์ž‘์—…

2. ๋™์‹œ์„ฑ ์ฒ˜๋ฆฌ๊ฐ€ ์ค‘์š”ํ•˜๊ณ , ์—ฌ๋Ÿฌ I/O ์ž‘์—…์„ ๋น„ํšจ์œจ์ ์œผ๋กœ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์‹ถ์ง€ ์•Š์€ ๊ฒฝ์šฐ
 1. CPU ๋ฐ”์šด๋“œ ์ž‘์—…(๋ณต์žกํ•œ ๊ณ„์‚ฐ ์ž‘์—…)์—์„œ ์œ ์šฉ

2. ๋ฉ€ํ‹ฐ์ฝ”์–ด ์‹œ์Šคํ…œ์—์„œ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ๊ณผ ๊ฒฐํ•ฉํ•˜์—ฌ ๋” ๋‚˜์€ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ๋‹ค

 

*GIL: Global Interpreter Lock์˜ ์•ฝ์ž๋กœ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ํŒŒ์ด์ฌ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ํ•œ๋ฒˆ์— ํ•˜๋‚˜๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ Lock์„ ๊ฑฐ๋Š” ๊ฒƒ

*์œ ํœด ์ƒํƒœ: ์ปดํ“จํ„ฐ ์‹œ์Šคํ…œ์ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ์ด๋‚˜ ์‹ค์ œ์ ์ธ ์ž‘์—…์ด ์—†๋Š” ์‹œ๊ฐ„