반응형

cmd에서 파이썬을 구동시켜주기 위해서는 먼저 파이썬3를 설치해야 한다.

테스트 했던 버전은 python 3.8.2 이다. 아래 링크로 다운로드 할 수 있다. (windows OS)

www.python.org/downloads/release/python-382/

 

Python Release Python 3.8.2

The official home of the Python Programming Language

www.python.org

 

 

파이썬 코드를 이용해서 내부 공유기 환경에서 체팅 서버를 만들 수 있다.

하나의 컴퓨터가 서버로 코드를 구동하면, 여러 클라이언트들이 접속해서 대화를 나눌 수 있다.

 

 

아래는 소스코드

(서버 코드)

import socketserver
import threading

HOST = '192.168.219.104' # 서버의 ip를 열음. (이 서버의 ip로 클라이언트가 접속을 해야 한다), 그전에 ping을 먼저 확인하도록.
PORT = 9009				 # 포트번호 (같아야 함)
lock = threading.Lock()  # syncronized 동기화 진행하는 스레드 생성


class UserManager:  # 사용자관리 및 채팅 메세지 전송을 담당하는 클래스
    # ① 채팅 서버로 입장한 사용자의 등록
    # ② 채팅을 종료하는 사용자의 퇴장 관리
    # ③ 사용자가 입장하고 퇴장하는 관리
    # ④ 사용자가 입력한 메세지를 채팅 서버에 접속한 모두에게 전송

    def __init__(self):
        self.users = {}  # 사용자의 등록 정보를 담을 사전 {사용자 이름:(소켓,주소),...}

    def addUser(self, username, conn, addr):  # 사용자 ID를 self.users에 추가하는 함수
        if username in self.users:  # 이미 등록된 사용자라면
            conn.send('이미 등록된 사용자입니다.\n'.encode())
            return None

        # 새로운 사용자를 등록함
        lock.acquire()  # 스레드 동기화를 막기위한 락
        self.users[username] = (conn, addr)
        lock.release()  # 업데이트 후 락 해제

        self.sendMessageToAll('[%s]님이 입장했습니다.' % username)
        print('+++ 대화 참여자 수 [%d]' % len(self.users))

        return username

    def removeUser(self, username):  # 사용자를 제거하는 함수
        if username not in self.users:
            return

        lock.acquire()
        del self.users[username]
        lock.release()

        self.sendMessageToAll('[%s]님이 퇴장했습니다.' % username)
        print('--- 대화 참여자 수 [%d]' % len(self.users))

    def messageHandler(self, username, msg):  # 전송한 msg를 처리하는 부분
        if msg[0] != '/':  # 보낸 메세지의 첫문자가 '/'가 아니면
            self.sendMessageToAll('[%s] %s' % (username, msg))
            return

        if msg.strip() == '/quit':  # 보낸 메세지가 'quit'이면
            self.removeUser(username)
            return -1

    def sendMessageToAll(self, msg):
        for conn, addr in self.users.values():
            conn.send(msg.encode())


class MyTcpHandler(socketserver.BaseRequestHandler):
    userman = UserManager()

    def handle(self):  # 클라이언트가 접속시 클라이언트 주소 출력
        print('[%s] 연결됨' % self.client_address[0])

        try:
            username = self.registerUsername()
            msg = self.request.recv(1024)
            while msg:
                print(msg.decode())
                if self.userman.messageHandler(username, msg.decode()) == -1:
                    self.request.close()
                    break
                msg = self.request.recv(1024)

        except Exception as e:
            print(e)

        print('[%s] 접속종료' % self.client_address[0])
        self.userman.removeUser(username)

    def registerUsername(self):
        while True:
            self.request.send('로그인ID:'.encode())
            username = self.request.recv(1024)
            username = username.decode().strip()
            if self.userman.addUser(username, self.request, self.client_address):
                return username


class ChatingServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass


def runServer():
    print('+++ 채팅 서버를 시작합니다.')
    print('+++ 채텅 서버를 끝내려면 Ctrl-C를 누르세요.')

    try:
        server = ChatingServer((HOST, PORT), MyTcpHandler)
        server.serve_forever()
    except KeyboardInterrupt:
        print('--- 채팅 서버를 종료합니다.')
        server.shutdown()
        server.server_close()

runServer()

 

반응형

 

서버 사용 방법.

cmd로 해당 파이썬 파일을 실행시키며 구동.

 

서버 구동.

1. cmd 입력

2. 내 ip주소 확인

    ipconfig

서버의 ip주소를 192.168.219.104 로 한다.

3. 해당 ip주소로 파이썬 server.py 코드를 수정해준다.

4. 해당 디렉터리로 이동해서 명령 프롬프트로 아래와 같이 쓰면 서버가 실행된다.

python server.py

 

 

클라이언트 사용 방법.

cmd로 해당 파이썬 파일을 실행시키며 구동.

 

(클라이언트 소스코드)

import socket
from threading import Thread

HOST = '192.168.219.104'    # 내가 접속할 서버의 ip주소
PORT = 9009                 # 서버의 포트 번호 (서로 같아야 연결 가능)


def rcvMsg(sock):
    while True:
        try:
            data = sock.recv(1024)
            if not data:
                break
            print(data.decode())
        except:
            pass


def runChat():
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect((HOST, PORT))
        t = Thread(target=rcvMsg, args=(sock,))
        t.daemon = True
        t.start()

        while True:
            msg = input()
            if msg == '/quit':
                sock.send(msg.encode())
                break

            sock.send(msg.encode())


runChat()

 

클라이언트 구동.

1. cmd 입력

2. 접속할 서버의 ip주소로 파이썬 client.py 코드를 수정해준다.

3. 그리고 같은 공유기 망에 있는 어떤 컴퓨터든 간에 명령프롬프트로 client.py를 실행시키면 접속이 된다.

    필자는 컴퓨터가 1대이므로 루프백 방식으로 서버이자 클라이언트로 접속했다.

 

    3-1. 로그인 ID를 입력하라고 나오면 id를 입력하면 된다. 필자는 student1으로 입력해서 접속했다.

왼쪽 서버, 오른쪽 클라이언트

    3-2. student2, student3 계정을 더 만들어서 접속했다.

    서버에는 아래와 같이 현재 몇명이 접속되었는지 실시간으로 체크가 된다.

 

 

(에러 문제) 만약 서버의 ip주소를 잘못 입력하거나, 서버가 닫혀있을때 아래와 같은 에러가 발생한다.

 

반응형

+ Recent posts