



• 소켓의 정의
• 소켓은 1982년 BSD(Berkeley Software Distribution) UNIX 4.1에서 처음 소개되었고, 현재 널리
사용되는 것은 1986년 BSD UNIX 4.3에서 개정된 것
• 소켓은 소프트웨어로 작성된 통신 접속점
• 소켓은 응용프로그램에서 TCP/IP를 이용하는 창구(인터페이스) 역할
• 주로 TCP 상에서 동작하는 소켓을 사용해서 “TCP 소켓”
또는 “TCP/IP 소켓” 이라고 함
• 물론, UDP 소켓도 가능


import socket
# 1번 방법
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET - IPv4
# socketAF_INET - IPv6 / socket.SOCK_STREAM : TCP , socket.SOCK_DGRAM : UDP
sock.connect(("www.google.com", 80)) # 주소와 80 설정이 괄호로 되어 있음 (튜플형)
sock.send("GET \n".encode()) # encode() 메소드 - 문자열을 byte로 변환 (필수)
data = sock.recv(1024) # receive의 약자, 버퍼의 크기를 1024 바이트로 설정
print(data.decode())
sock.close()
# 2번 방법
with socket.socket() as sock: # with 블록을 벗어나는 순간 자동으로 close 함수를 실행해줌
addr = ("www.google.com", 80)
sock.connect(addr)
sock.send("GET \n".encode())
data = sock.recv(1024) # receive의 약자, 버퍼의 크기를 1024 바이트로 설정
print(data.decode())
< encode() 메소드 >
• 문자열을 전송할 때 byte로 변환해주는 메소드 (사용 안 할 경우 에러 발생)
• 1바이트 단위 값으로 저장하는 자료형
• b’ ‘ 또는 b” “으로도 쓰임
• cf) str과 다름, bytes()와 유사
• bytes(“ABC”, “utf-8”) vs. “ABC”.encode()


import socket
# 1.소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 바인딩
sock.bind(("",9999)) # 괄호 필수, bind(IP, PORT)
# bind() : "" 는 모든 네트워크 인터페이스에서 들어오는 연결을 수신함
# 3. 접속대기
sock.listen() # 1일 경우 하나의 접속만 허용 (비어있을 경우 모두 받기)
print("The echo server start....")
# 4. 접속 수락
conn, addr = sock.accept() # accept() : 클라이언트의 소켓 객체와 클라이언트의 주소 정보를 리턴
# 5. 데이터 수신
read_data = conn.recv(1024) # 버퍼 사이즈 1024 byte
print("recv : {}".format(read_data))
# 6. 접속종료
conn.close()
sock.close()
# 소켓 생성 -> 바인딩 -> 접속 대기 -> 접속 수락 -> 데이터 수신 -> 접속 종료

import socket
# 1. 소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 접속 시도
sock.connect(("127.0.0.1", 9999))
# 3. 데이터 송신
send_data = input("입력: ")
sock.sendall(bytes(send_data, "utf-8")) # 인코딩을 utf-8 형식으로 byte 변환
# 4. 접속 종료
print("클라이언트 종료")
sock.close()
# seldall() 을 사용하더라도 send를 거쳐간다
서버 쪽 코드 실행 후 - 오른쪽 아래 아이콘 눌러서 split 해주고 클라이언트 쪽 실행

서버쪽 터미널
클라이언트 터미널

import socket
# 1.소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 바인딩
sock.bind(("",9999)) # 괄호 필수, bind(IP, PORT)
# bind() : "" 는 모든 네트워크 인터페이스에서 들어오는 연결을 수신함
# 3. 접속대기
sock.listen() # 1일 경우 하나의 접속만 허용 (비어있을 경우 모두 받기)
print("The echo server start....")
# 4. 접속 수락
conn, addr = sock.accept() # accept() : 클라이언트의 소켓 객체와 클라이언트의 주소 정보를 리턴
# 5. 데이터 수신
read_data = conn.recv(1024) # 버퍼 사이즈 1024 byte
print("recv : {}".format(read_data))
# 5 - 1. 데이터 송신(에코)
conn.sendall(read_data)
print("send : {}".format(read_data))
# 6. 접속종료
conn.close()
sock.close()
# 소켓 생성 -> 바인딩 -> 접속 대기 -> 접속 수락 -> 데이터 수신 -> 접속 종료

import socket
# 1. 소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 접속 시도
sock.connect(("127.0.0.1", 9999))
# 3. 데이터 송신
send_data = input("입력: ")
sock.sendall(bytes(send_data, "utf-8")) # 인코딩을 utf-8 형식으로 byte 변환
# 3-2 데이터 수신 ( 추가됨 )
recv_data = sock.recv(1024)
print(f"recv : {recv_data}")
# 4. 접속 종료
print("클라이언트 종료")
sock.close()
# seldall() 을 사용하더라도 send를 거쳐간다


import socket
# 1.소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 바인딩
sock.bind(("",9999)) # 괄호 필수, bind(IP, PORT)
# bind() : "" 는 모든 네트워크 인터페이스에서 들어오는 연결을 수신함
# 3. 접속대기
sock.listen() # 1일 경우 하나의 접속만 허용 (비어있을 경우 모두 받기)
print("The echo server start....")
# 4. 접속 수락
conn, addr = sock.accept() # accept() : 클라이언트의 소켓 객체와 클라이언트의 주소 정보를 리턴
while True : # while문 추가하여 여러 번 송수신
# 5. 데이터 수신
read_data = conn.recv(1024) # 버퍼 사이즈 1024 byte
print("recv : {}".format(read_data))
# 5 - 1. 데이터 송신(에코)
conn.sendall(read_data)
print("send : {}".format(read_data))
if read_data.decode() == 'end' : # 종료문
break
# 6. 접속종료
conn.close()
sock.close()

import socket
# 1. 소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 접속 시도
sock.connect(("127.0.0.1", 9999))
while True : # while문 추가
# 3. 데이터 송신
send_data = input("입력: ")
sock.sendall(bytes(send_data, "utf-8")) # 인코딩을 utf-8 형식으로 byte 변환
if send_data == 'end' :
break
# 3-2 데이터 수신 ( 추가됨 )
recv_data = sock.recv(1024)
print(f"recv : {recv_data}")
# 4. 접속 종료
print("클라이언트 종료")
sock.close()
# seldall() 을 사용하더라도 send를 거쳐간다

end 입력시 종료됨
에코 서버2, 에코 클라이언트2를 수정하여 숫자 맞추기 게임
서버에서 randint(10,99)를 이용해 2자리 난수를 생성
클라이언트가 임의의 2자리 수 입력하면 낮음, 높음, 정답의 결과를 리턴
- 정답을 맞추면 종료
server
import socket
import random
randNum = random.randint(10, 99)
# 1.소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 바인딩
sock.bind(("",9999)) # 괄호 필수, bind(IP, PORT)
# bind() : "" 는 모든 네트워크 인터페이스에서 들어오는 연결을 수신함
# 3. 접속대기
sock.listen() # 1일 경우 하나의 접속만 허용 (비어있을 경우 모두 받기)
print("The echo server start....")
print(randNum) # 서버에서 정답 미리보기
# 4. 접속 수락
conn, addr = sock.accept() # accept() : 클라이언트의 소켓 객체와 클라이언트의 주소 정보를 리턴
while True : # while문 추가하여 여러 번 송수신
# 5. 데이터 수신
read_data = conn.recv(1024) # 버퍼 사이즈 1024 byte
print("recv : {}".format(read_data.decode())) # byte code를 문자열로 캐스팅함
# 5 - 1. 데이터 송신(에코)
print("send : {}".format(read_data))
if int(read_data.decode()) == randNum : # 종료문 .
print('정답!')
conn.send(('정답!').encode('UTF-8'))
break
elif int(read_data.decode()) < randNum : # read_data가 바이트 코드이므로 .decode()를 통해 문자열로 변환해 준 후 -> int형으로 바꿔줘야 함.
conn.send(('정답보다 높음').encode('UTF-8'))
elif int(read_data.decode()) > randNum :
conn.send(('정답보다 낮음').encode('UTF-8'))
# 6. 접속종료
conn.close()
sock.close()
client
import socket
# 1. 소켓 생성
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 접속 시도
sock.connect(("127.0.0.1", 9999))
while True : # while문 추가
# 3. 데이터 송신
send_data = input("입력: ")
sock.sendall(bytes(send_data, "utf-8")) # 인코딩을 utf-8 형식으로 byte 변환
# if send_data == 'end' :
# break
# 3-2 데이터 수신 ( 추가됨 )
recv_data = sock.recv(1024)
print(f"recv : {recv_data.decode()}")
if recv_data.decode() == '정답!' :
break
# 4. 접속 종료
print("클라이언트 종료")
sock.close()
# seldall() 을 사용하더라도 send를 거쳐간다
