Python socket

๋„คํŠธ์›Œํฌ ๊ณ„์ธต (OSI, TCP/IP)

๋„คํŠธ์›Œํฌ ๊ณ„์ธต์€ OSI 7 ๊ณ„์ธต์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๊ณ , ์ธํ„ฐ๋„ท ์‚ฌ์šฉ ํ™˜๊ฒฝ์—์„œ๋Š” TCP/IP 4๊ณ„์ธต(๋˜๋Š” 5๊ณ„์ธต)์˜ ์‹œ๊ฐ์œผ๋กœ ๋ฐ”๋ผ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜ ๊ทธ๋ฆผ์€ ๋‘ ๋ชจ๋ธ์„ ์„ค๋ช…ํ•˜๋Š” ๊ทธ๋ฆผ์ž…๋‹ˆ๋‹ค.

Ref: https://community.fs.com/blog/tcpip-vs-osi-whats-the-difference-between-the-two-models.html

Ref: https://www.researchgate.net/figure/The-logical-mapping-between-OSI-basic-reference-model-and-the-TCP-IP-stack_fig2_327483011

๊ฐ ๊ณ„์ธต์˜ ์—ญํ• ์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • 7 ๊ณ„์ธต, Application : ํ†ต์‹  ํ”„๋กœํ† ์ฝœ๊ณผ ์ธํ„ฐํŽ˜์ด์Šค ๋‹ด๋‹นํ•˜๋Š” ๊ณ„์ธต
  • 6 ๊ณ„์ธต, Presentation : ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜, ์•”ํ˜ธํ™” ๋“ฑ์„ ๋•๋Š” ๊ณ„์ธต
  • 5 ๊ณ„์ธต, Session : ์–‘ ๋๋‹จ ์‘์šฉ ํ”„๋กœ์„ธ์Šค์—๊ฒŒ ํ†ต์‹  ์—ฐ๊ฒฐ, ์œ ์ง€ ๋“ฑ์— ๋Œ€ํ•œ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” ๊ณ„์ธต
  • 4 ๊ณ„์ธต, Transport : ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” ๊ณ„์ธต
  • 3 ๊ณ„์ธต, Network : ๋‹ค์ค‘ ๋…ธ๋“œ ๋„คํŠธ์›Œํฌ์˜ ๊ตฌ์กฐํ™”์™€ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ์ฃผ์†Œ ์ง€์ •, ๋ผ์šฐํŒ…๊ณผ ํŠธ๋ž˜ํ”ฝ ์ œ์–ด๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ๊ณ„์ธต
  • 2 ๊ณ„์ธต, Data link : 1 ๊ณ„์ธต์— ์˜ํ•ด ์—ฐ๊ฒฐ๋œ ๋‘ ๋…ธ๋“œ ์‚ฌ์ด์˜ ์‹ ๋ขฐ์„ฑ ์žˆ๋Š” ์ „์†ก์„ ์œ„ํ•œ ๊ณ„์ธต
  • 1 ๊ณ„์ธต, Physical : ํ•˜๋“œ์›จ์–ด ์ „์†ก ๊ธฐ์ˆ ๋กœ ๊ตฌ์„ฑ๋œ ๊ณ„์ธต

์†Œ์ผ“ ํ†ต์‹ 

์†Œ์ผ“์€ TCP/IP ๋ชจ๋ธ์—์„œ Application ๊ณ„์ธต๊ณผ Transport ๊ณ„์ธต ์‚ฌ์ด์—์„œ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ๋„์™€์ฃผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค ์ž…๋‹ˆ๋‹ค.

ํ•จ์ˆ˜ ์„ค๋ช…

socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
  • @brief ์†Œ์ผ“ ๊ฐ์ฒด ์ƒ์„ฑ
  • @param family address family ์„ค์ •, ์ด ์„ค์ •์— ๋”ฐ๋ผ address format์ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.
socket.bind(address)
  • @brief address์— ์†Œ์ผ“์„ ์—ฐ๊ฒฐ
  • @param address socket.AF_INET์˜ ๊ฒฝ์šฐ (host, port)์ž…๋‹ˆ๋‹ค.
socket.listen([backlog])
  • @brief ์„œ๋ฒ„๊ฐ€ ์—ฐ๊ฒฐ์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •
  • @param backlog client๊ฐ€ ์—ฐ๊ฒฐ์„ ์š”์ฒญํ–ˆ์„ ๋•Œ, socket.accept() ์—†์ด ๋Œ€๊ธฐ ๊ฐ€๋Šฅํ•œ ์š”์ฒญ์˜ ์ตœ๋Œ€ ๊ฐœ์ˆ˜, ์ฃผ๋กœ 5 ์ •๋„ ์„ค์ •
socket.accept()
  • @brief ์—ฐ๊ฒฐ ์š”์ฒญ์„ ์ˆ˜๋ฝ
  • @return (connected_socket, address)
socket.connect(address)
  • @brief address์— ์—ฐ๊ฒฐ๋œ socket๊ณผ ์—ฐ๊ฒฐ
socket.recv(bufsize[, flags])
  • @brief ์ตœ๋Œ€ bufsize๋งŒํผ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ , bufsize๋Š” 2^n ๊ฐ’์ด ์ ์ ˆํ•จ
  • @return byte

์ƒ๋Œ€ ์†Œ์ผ“์ด ๋‹ซํžˆ๋ฉด ๋นˆ byte (b'')๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์— if not socket.recv(1024): ๋กœ ์—ฐ๊ฒฐ์ด ๋Š๊ฒผ๋Š”์ง€ ํ™•์ธ ๊ฐ€๋Šฅ

socket.send(bytes[, flags])
  • @brief ๋ฐ์ดํ„ฐ๋ฅผ ์†ก์‹ 
socket.sendall(bytes[, flags])
  • @brief ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ์†ก์‹ ๋  ๋•Œ๊นŒ์ง€ ์†ก์‹ 
socket.close()
  • @brief ์†Œ์ผ“ ์ข…๋ฃŒ
socket.gethostname()
  • @return string ํ˜ธ์ŠคํŠธ ์ด๋ฆ„ ๋ฐ˜ํ™˜

TCP, UDP

TCP(Transmission Control Protocol)UDP(User Datagram Protocol)
์—ฐ๊ฒฐํ˜•๋น„์—ฐ๊ฒฐํ˜•
1:11:1, 1:N, N:N
๋†’์€ ์‹ ๋ขฐ์„ฑ.
.๋” ๋น ๋ฅธ ์†๋„

TCP server - client ๊ธฐ๋ณธ ์˜ˆ์ œ

server

import socket
import signal
import sys
import logging
import threading
import time
log = logging.getLogger(__name__)
logging.basicConfig(
format='[%(levelname)-8s] %(filename)-10s %(lineno) 4d ํ–‰ : %(message)s',
level=logging.DEBUG)
# ์„œ๋ฒ„ IP, PORT
_HOST = "xxx.xxx.xxx.xxx"
_PORT = 12345
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((_HOST, _PORT))
server_socket.listen()
def signal_handler(sig, frame):
server_socket.close()
time.sleep(1)
sys.exit()
signal.signal(signal.SIGINT, signal_handler)
def recv_thread(connected_socket):
while True:
try:
data = connected_socket.recv(1024)
if data == b'':
break
log.debug(data)
except:
break
while True:
log.info("์—ฐ๊ฒฐ ๋Œ€๊ธฐ")
connected_socket, client_address = server_socket.accept()
log.info("{} ์—ฐ๊ฒฐ".format(client_address))
t = threading.Thread(target=recv_thread, args=(
connected_socket,), daemon=True)
t.start()
while t.isAlive():
try:
connected_socket.send("hello client\n".encode())
time.sleep(1)
except:
break

client

import socket
import signal
import sys
import logging
import threading
import time
log = logging.getLogger(__name__)
logging.basicConfig(
format='[%(levelname)-8s] %(filename)-10s %(lineno) 4d ํ–‰ : %(message)s',
level=logging.DEBUG)
# ์„œ๋ฒ„ IP, PORT
_HOST = "xxx.xxx.xxx.xxx"
_PORT = 12345
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((_HOST, _PORT))
def signal_handler(sig, frame):
client_socket.close()
time.sleep(1)
sys.exit()
signal.signal(signal.SIGINT, signal_handler)
def recv_thread(client_socket):
while True:
try:
data = client_socket.recv(1024)
if data == b'':
break
log.debug(data)
except:
break
t = threading.Thread(target=recv_thread, args=(client_socket,), daemon=True)
t.start()
while t.isAlive():
client_socket.send("hello server\n".encode())
time.sleep(1)

Bluetooth

server

import socket
import signal
import sys
HOST = socket.BDADDR_ANY # '๋ธ”๋ฃจํˆฌ์Šค ์ปจํŠธ๋กค๋Ÿฌ ๋งฅ ์ฃผ์†Œ'๋ฅผ ์ง์ ‘ ์ž…๋ ฅํ•ด๋„ ๋จ
PORT = 1
def signal_handler(sig, frame):
try:
connected_socket.close()
except:
pass
server_socket.close()
sys.exit()
signal.signal(signal.SIGINT, signal_handler)
# ๋ธ”๋ฃจํˆฌ์Šค ์„œ๋ฒ„ ์†Œ์ผ“ ์ƒ์„ฑ
server_socket = socket.socket(
socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
server_socket.bind((HOST, PORT))
server_socket.listen()
# ํด๋ผ์ด์–ธํŠธ ์ ‘์† ๋Œ€๊ธฐ
connected_socket, client_address = server_socket.accept()
try:
while True:
data = connected_socket.recv(1024)
print("client :", data)
connected_socket.send(data)
except:
pass
connected_socket.close()
server_socket.close()

client

import socket
import signal
import sys
# ์„œ๋ฒ„์˜ HOST์™€ PORT ์ •๋ณด
HOST = ''
PORT = 1
def signal_handler(sig, frame):
client_socket.close()
sys.exit()
signal.signal(signal.SIGINT, signal_handler)
# ๋ธ”๋ฃจํˆฌ์Šค ํด๋ผ์ด์–ธํŠธ ์†Œ์ผ“ ์ƒ์„ฑ
client_socket = socket.socket(
socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
# ์„œ๋ฒ„ ์ ‘์†
client_socket.connect((HOST, PORT))
try:
while True:
data = input("client : ")
if data:
client_socket.send(data.encode())
data = client_socket.recv(1024)
print("server :", data)
except:
pass
client_socket.close()

Reference

Last updated on