롸?

소켓과 스레드를 이용한 간단 에코서버, 챗 서버 본문

프로그래밍/Python

소켓과 스레드를 이용한 간단 에코서버, 챗 서버

허니버터새우깡 2020. 5. 13. 17:35

1-1. 소켓을 이용한 간단 에코 서버.py

import socket

HOST = '127.0.0.1'   #호스트를 지정하지 않으면 가능한 모든 인터페이스를 의미
PORT = 9999
ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ss.bind((HOST, PORT))
ss.listen(1)               #접속이 있을 때 까지 기다림
conn, addr = ss.accept()   #접속을 승인
print('client addr :', addr)
while True:
    data = conn.recv(1024).decode()    #클라이언트로부터 데이터 수신
    if data == 'q':
        print('quit connection') 
        exit()
    conn.send(data.encode('utf-8'))    #받은 데이터를 그대로 클라이언트에 전송
ss.close()
conn.close()

 

1-2. 소켓을 이용한 간단 클라이언트.py

import socket

HOST = '127.0.0.1'
PORT = 9999
cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cs.connect((HOST, PORT)) #server와 연결

while True:
    str = input('echo : ')
    cs.send(str.encode(encoding='utf_8')) #서버에 데이터 전송
    data = cs.recv(1024).decode()    #서버로부터 정보를 받음
    print('server : ', data)

cs.close()

 

 

2-1. 간단한 챗 서버.py

import threading, socket

ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ss.bind(('127.0.0.1', 7777))
ss.listen(5)

users = []

def ChatUser(conn):
    name = conn.recv(1024)
    data = '__' + name.decode('utf-8') + '님 입장__'
    print(data)
    
    try:
        for p in users:
            p.send(data.encode('utf-8'))
            
        while True:
            msg = conn.recv(1024)
            data = name.decode('utf-8') + ' --> ' + msg.decode('utf-8')
            print('server : ', data)
            
            for p in users:
                p.send(data.encode('utf-8'))
            
    except:
        users.remove(conn) #유저가 종료한 경우 
        data = '__' + name.decode('utf-8') + '님 퇴장__'
        if users:
            for p in users:
                p.send(data.encode('utf-8'))
        else:
            print('서버 종료')
    

while True:
    conn, addr = ss.accept()
    users.append(conn)
    th = threading.Thread(target=ChatUser, args=(conn, ))
    th.start()    #클라이언트가 들어올때마다 users에 담기고 유저마다 chatuser 스레드를 스타드

 

2-2. 간단한 챗 클라이언트.py

import threading, socket, sys

def Handle(socket):
    while True:
        data = socket.recv(1024)
        if not data: continue # 데이터가 없는 경우
        print(data.decode('utf-8'))
        
sys.stdout.flush() #버퍼 비우기

name = input('닉네임 입력 :')
cs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cs.connect(('127.0.0.1', 7777))
cs.send(name.encode('utf-8')) #대화명 전송

th = threading.Thread(target=Handle, args=(cs, ))
th.start()

while True:
    msg = input('>>')
    sys.stdout.flush()
    if not msg: continue
    cs.send(msg.encode('utf-8')) #대화 메세지 전송
    
cs.close()
    

 

3. socket(), bind(), listen()

socket.socket() 함수를 이용해서 소캣 객체를 생성할 수 있다. 이 함수는 두가지 인자를 받는데 하나가 패밀리이고 하나는 타입이다.

 

패밀리 : 소켓의 패밀리란 "택배상자에 쓰는 주소 체계가 어떻게 되어있냐"에 관한 것으로 흔히 AF_INET나 AF_INET6를 많이 쓴다. AF_INET는 IP4v, AF_INET6는 IP6v에 사용된다.

타입 : 소켓 타입이다. raw 소켓, 스트림 소켓, 데이터그램 소켓 등등이 있는데 주로 많이 쓰는 것은 SOCK_STREAM 와 SOCK_DGRAM이다.

 

 

 

 


참고 

1.  참고 서적 - 빠르게 활용하는 파이썬 3.6 프로그래밍

2.  https://soooprmx.com/archives/8737

'프로그래밍 > Python' 카테고리의 다른 글

DB연동 (mariaDB)  (0) 2020.05.13
파일 입출력  (0) 2020.05.13
모듈  (0) 2020.05.08
클래스  (0) 2020.05.08
함수, lambda  (0) 2020.05.07
Comments