Skip to content

mjubackend/chat_client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

1. client 사용법

실행 환경

client.py 는 python3 script 로 되어있습니다.

실행 인자

client.py 는 다음 실행 인자들을 사용할 수 있습니다.

  • --help : 사용 가능한 실행 인자 목록과 간단한 설명을 출력합니다.
  • --verbosity : 기본 로그 외에 상세 로그를 출력하게 됩니다. --verbosity=0 또는 --verbosity=1 또는 --verbosity=2 처럼 쓸 수 있으며, 0 은 아무것도 쓰지 않은 경우입니다. 1은 클라이언트-서버간 주고 받는 메시지를 출력하고, 2는 소켓 작업 내용까지 출력합니다.
  • --ip : 채팅 서버의 IP 주소를 입력합니다. 실습 서버에서 사용함을 가정해서 기본값은 127.0.0.1 로 지정되어 있습니다.
  • --port : 채탕 서버의 port 를 지정합니다. LMS 를 통해 고지된 각 개인에게 할당된 port 를 사용하세요.
  • --format : --format=json 이나 --format=protobuf 처럼 쓸 수 있습니다. 클라이언트-서버 간 메시지의 포맷을 지정합니다.

실행 예시

필요 패키지 설치

$ python3 -m venv .venv
$ source .venv/bin/activate
$ python3 -m pip install -r requirements.txt

JSON 을 이용해서 메시지를 주고 받을 예정이고, 개발한 채팅 클라이언트를 실습 서버 10101 번 포트에 띄운 경우

$ source .venv/bin/activate
$ python3 ./client.py --format=json --port=10101

Protobuf 를 이용해서 메시지를 주고 받을 예정이고, 개발한 채팅 클라이언트를 실습 서버 10101 번 포트에 띄운 경우

$ source .venv/bin/activate
$ python3 ./client.py --format=protobuf --port=10101

더 상세한 로그 메시지를 보고 싶은 경우

클라이언트 측에서 서버와 주고 받는 메시지의 상세 정보를 보고 싶은 경우 --verbosity 옵션을 추가할 수 있습니다. 기본 값은 0 인데, 1 은 좀 더 많은 로그 메시지, 2는 아주 많은 로그 메시지를 출력합니다.

예시 1

$ source .venv/bin/activate
$ python3 ./client.py --format=protobuf --port=10101 --verbosity=1

예시 2

$ source .venv/bin/activate
$ python3 ./client.py --format=json --port=10101 --verbosity=2

데모 서버

교수가 개발한 (1) JSON 사용 데모 서버가 실습 서버의 9000 번 포트에, (2) Protobuf 사용 데모 서버가 실습 서버의 9100 번 포트에 동작하고 있습니다. 따라서 아래 명령어에 대한 설명은 이 서버에 접속 후 테스트 해볼 수 있습니다.

데모 서버를 직접 실행해 보고 싶은 경우 다음 명령을 실행합니다. (해당 파일은 Linux 에서만 동작하며 Windows 나 macOS 에서는 실행이 되지 않습니다.)

$ python3 dist/server.py --port=내포트번호

(보다 자세한 옵션은 --help 인자를 주고 실행해 보면 알 수 있음)

사용 가능한 명령어 설명

client.py 를 실행해서 서버와 접속한 경우 다음과 같은 명령어들을 쓸 수 있습니다.

  • /help : 사용 가능 명령어를 나열한다.
  • /name : 채팅 이름을 지정한다.
  • /rooms : 채팅 방 목록을 출력한다.
  • /create : 채팅 방을 만든다.
  • /join : 채팅 방에 들어간다.
  • /leave : 채팅 방을 나간다.
  • /shutdown : 채팅 서버를 종료한다.

2. 서버 구현 요구 조건

client.py 명령어의 구현

앞에 나열한 client.py 명령어 중 /help 를 제외한 나머지는 모두 서버가 있어야 동작합니다. 각 명령어의 기대되는 동작은 다음과 같습니다.

/name

  • 클라이언트가 처음 연결되면 서버는 이 클라이언트에게 (127.0.0.1, 9001) 처럼 클라이언트 측 IP 주소와 port 번호를 이름으로 부여 합니다.
  • /name 명령은 연결한 클라이언트의 닉네임을 변경합니다.
  • 해당 클라이언트에게는 시스템 메시지로 [시스템 메시지] 이름이 test 으로 변경되었습니다. 와 같은 알림이 가야됩니다.
  • 만일 이 클라이언트가 대화방에 들어가 있는 경우, 대화방에 있는 모든 멤버들에게 [시스템 메시지] 이름이 test 으로 변경되었습니다. 와 같은 메시지가 추가로 가야됩니다.

/rooms

  • 현재 개설된 대화방 목록이 출력됩니다.
  • 대화방 목록은 (1) 방 번호, (2) 방 제목, (3) 참여중인 멤버들의 이름 이 나열되어야 됩니다.
  • 위 정보가 포함되는한 출력 형식은 자유롭게 하면 됩니다.
  • 개설된 대화방이 없는 경우 이를 알아볼 수 있게 자유롭게 표시하면 됩니다.

/create

  • 대화방을 개설하는 명령어로서, 뒤에 방제목을 입력해야 됩니다. 예시: /create hello world
  • 대화방 개설은 현재 참여 중인 대화방이 없는 경우만 가능해야됩니다. 만일 현재 다른 방에 들어가 있는 경우 서버는 [시스템 메시지] 대화 방에 있을 때는 방을 개설 할 수 없습니다. 메시지를 해당 유저에게 전송해야 됩니다.
  • 대화방 개설과 동시에 해당 유저는 그 방에 자동으로 입장하게 됩니다. 예시:
    /create hello world
    [시스템 메시지] 방제[hello world] 방에 입장했습니다.
    

/join

  • 이미 개설된 방에 참여할 수 있는 명령어로서, 뒤에 방 번호를 입력해야 됩니다. 예시: /join 2
  • 대화방 참여는 현재 참여중인 대화방이 없는 경우만 가능해야 됩니다. 만일 현재 다른 방에 들어가 있는 경우 서버는 [시스템 메시지] 대화 방에 있을 때는 다른 방에 들어갈 수 없습니다. 메시지를 해당 유저에게 전송해야 됩니다.
  • 없는 방 번호의 방으로 들어가려고 할 때 서버는 [시스템 메시지] 대화방이 존재하지 않습니다. 메시지를 해당 유저에게 전송해야 됩니다.
  • 방에 들어가면 서버는 해당 유저에게 [시스템 메시지] 방제[hello world] 방에 입장했습니다. 와 같은 메시지를 전송해야 됩니다.
  • 방에 들어간 경우 모든 기존 멤버들에게는 [시스템 메시지] [test2] 님이 입장했습니다. 와 같은 메시지를 전송해야 됩니다.

/leave

  • 대화방을 나가는 명령어입니다.
  • 대화방에 참여 중이지 않을 때 서버는 [시스템 메시지] 현재 대화방에 들어가 있지 않습니다. 메시지를 해당 유저에게 전송해야 됩니다.
  • 남아있는 멤버들에게는 [시스템 메시지] [test2] 님이 퇴장했습니다. 와 같은 메시지가 전송 되어야 됩니다.
  • 나간 유저 본인에게는 [시스템 메시지] 방제[hello world] 대화 방에서 퇴장했습니다. 와 같은 메시지를 전송해야 됩니다.

/shutdown

  • 채팅 서버를 종료하는 명령어입니다.
  • 서버는 이 명령어를 수신하면 생성한 쓰레드들을 정리하고 프로그램을 종료해야 됩니다.

그밖에 입력

/ 로 시작하지 않는 문자열은 채팅 메시지로 인식합니다.

  • 만일 대화 방에 없는 경우 서버는 [시스템 메시지] 현재 대화방에 들어가 있지 않습니다. 를 해당 유저에게 전송해야 됩니다.
  • 만일 대화 방에 있는 경우 해당 채팅 메시지는 본인을 제외한 나머지 모든 멤버들에게 전송되어야 합니다.

3. 클라이언트-서버 간 메시지

JSON 과 Protobuf 두 경우를 모두 구현하는 것이 목적입니다. 아래 설명에서 CS 가 붙는 메시지 포맷은 클라이언트 -> 서버 를 의미합니다. SC서버 -> 클라이언트 를 의미합니다.

JSON 을 이용하는 경우

  • 클라이언트 -> 서버 메시지: client.py 의 on_cs_name(), on_cs_rooms(), on_cs_create(), on_cs_join(), on_cs_leave(), on_cs_chat() 함수들을 보면 각 명령어에 대해서 서버 전송시 JSON 메시지 포맷을 알 수 있습니다. 이를 참고하길 바랍니다.
  • 서버 -> 클라이언트 메시지: /rooms 명령어에 대한 응답은 on_sc_rooms_result() 함수를 참고하길 바랍니다. 다른 유저가 입력한 채팅 메시지를 받는 경우는 on_sc_chat() 함수를 참고 바랍니다. 그 외에 / 로 시작하는 명령어들에 대한 처리는 모두 on_sc_system_message() 에 의해서 처리 됩니다.

Protobuf 를 이용하는 경우

메시지 형태는 message.proto 파일에 정의되어 있습니다. 이를 사용하기 위해서는 다음과 같은 명령어를 실행해서 message.proto 파일의 내용을 포함하는 python module 을 생성해야 됩니다. (본 repo 에 이미 포함하고 있지만, 만일 수정을 하는 경우 아래 명령어를 다시 실행해야 됩니다.)

$ protoc --python_out=. -I. message.proto

JSON 의 경우와 마찬가지로 대응되는 on_cs_XXX() 함수와 on_sc_YYY() 함수를 참고해서 메시지를 만들면 됩니다.

4. 구현 요구 조건

  • 앞의 client.py 명령어들이 동작하게끔 메시지 포맷 (= 프로토콜)이 호환되는 서버를 작성하시오.
  • 서버는 Python, C++, Java 어떤 것을 써도 상관 없지만, framework 은 사용할 수 없으며 직접 I/O multiplexing 과 producer-consumer 문제를 구현해야 함
  • 서버는 worker thread 들의 개수를 수정할 수 있어야 합니다. (프로그램 실행 인자로 할 수 있다면 가장 좋겠지만, 이 부분이 익숙치 않다면 코드 상에서 대응되는 변수 값을 고치면 쓰레드 개수가 수정되게 구현해야 됩니다.)
  • 서버가 클라이언트에 메시지를 전송하고 그게 클라이언트에서 출력되는 것이 중요합니다. 샘플 서버를 흉내낸다면 이 부분을 흉내내고, 서버 자체에서 출력되는 실행 로그 메시지는 똑같을 필요가 없습니다.

5. 평가 항목

  • worker thread 를 2개 이상으로 지정할 수 있도록 프로그래밍했는지 여부
  • worker thread 가 2개 이상일 때 위의 명령어들이 제대로 동작하는지 여부 (= synchronization 이 제대로 구현되었는지)
  • 둘 이상의 채팅 방에 유저들이 나눠 들어가 있는 경우 대화방 간 간섭 없이 제대로 채팅이 되는지 여부
  • I/O multiplexing 적용 여부
  • producer-consumer 적용 여부 (= queue, mutex, condition variable 사용 여부)
  • Message handler map 적용 여부
  • JSON 과 Protobuf 둘 다 지원하는지 여부

6. 주의점

구현 내용 중에 어느 부분이 됐든 I/O multiplexing 과 proder-consumer 문제를 구현하면 됩니다.

그런데 구현 해야되는 내용이 너무 뻔해서 아마도 I/O multiplexing 은 여러 클라이언트 소켓과 새로운 연결을 처리하는데 써야될 것 이고, producer-consumer 문제는 각 클라이언트에서 보내온 메시지를 처리하는 형태가 될 것입니다.

이 때 producer-consumer 의 queue 에 각 클라이언트의 메시지를 집어 넣는 경우는 주의가 필요합니다. 일반적인 경우에서는 경험하기 어렵지만, 메시지가 매우 빠른 속도로 들어오는 경우 한 클라이언트로부터 온 메시지가 2개 이상 queue 에 들어갈 수 있게 구현 할 경우, 이 두 메시지가 서로 다른 쓰레드에 의해 처리 된다면 메시지의 처리 순서가 어긋나는 문제가 생길 수 있습니다.

  • 예) client A 가 매우 빠르게 메시지1, 2 두개를 전송했는데, 둘을 큐에 넣는 경우 쓰레드1번은 메시지1 을 쓰레드2번은 메시지2를 처리하게 될 수 있습니다. 이 경우 처리 순서가 메시지1 -> 메시지2 여야 함에도 쓰레드에 의한 race condition 이 발생할 수 있습니다.

따라서 이 경우는 메시지들을 각각 큐에 넣어서는 안되고, 클라이언트 자체를 큐에 넣거나, 아니면 이미 해당 클라이언트로부터 받은 메시지가 큐에 있는 경우 기존 메시지를 처리 한 뒤에 다시 큐에 넣는 방식으로 구현해야 됩니다.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages