• 티스토리 홈
  • 프로필사진
    소쩍소쩍이
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
소쩍소쩍이
  • 프로필사진
    소쩍소쩍이
    • 분류 전체보기 (89)
      • 파이썬 (18)
        • 문제 및 예제 (8)
      • PySide6 (24)
        • Signal & Slot (6)
        • Layout (8)
        • Model & View (3)
        • File (4)
        • Resource (3)
      • Server - Client (17)
        • GUI 채팅 (1)
      • MySQL (4)
      • 리눅스 (5)
      • 아두이노 (0)
      • 일지 (20)
  • GitHub
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    # Home
    # 공지사항
    #
    # 태그
    # 검색결과
    # 방명록
    • 스레드로 클라이언트 처리
      2026년 06월 23일
      • 소쩍소쩍이
      • 작성자
      • 2026.06.23.:19

      서버 - handle_client() 함수 만들기

      handle_client() 함수 코드 보기
      import socket
      import threading
      
      HOST = "127.0.0.1"
      PORT = 5000
      
      def handle_client(client_socket, client_address):
          print(f"클라이언트 처리 시작: {client_address}")
      
          with client_socket:
              while True:
                  data = client_socket.recv(1024)
      
                  if not data:
                      print(f"클라이언트 연결 끊김: {client_address}")
                      break
      
                  message = data.decode("utf-8")
                  print(f"{client_address} 메시지: {message}")
      
                  if message == "exit":
                      print(f"클라이언트 종료 요청: {client_address}")
                      break
      
                  response = f"서버가 받은 메시지: {message}"
                  client_socket.send(response.encode("utf-8"))
      
          print(f"클라이언트 처리 종료: {client_address}")

       

      handle_client()의 흐름

      handle_client() 시작
      ↓
      while True: recv() 대기
      ↓
      if not data → 연결 끊김 → break
      if message == "exit" → 정상 종료 → break
      그 외 → 확인 응답 send()
      ↓
      with 블록 종료 → client_socket 자동으로 닫힘
      ↓
      handle_client() 종료

       

      주의
      if not data 조건은 꼭 필요하다.
      recv() 결과가 비어 있다는 것은 상대방이 연결을 끊었다는 의미이며, 이 조건이 없으면 반복문이 계속 실행되면서 오류가 발생할 수 있다.

       

      with client_socket 사용 이유
      break로 반복문을 빠져나와도 with 블록이 종료되면서 client_socket.close()가 자동으로 호출된다. 스레드가 많아질수록 소켓을 직접 닫는 코드를 빼먹기 쉬운데, with 문을 사용하면 이런 실수를 줄일 수 있다.

       

      서버 - 메인 루프 만들기

      서버 소켓 생성 코드 보기
      with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
          server_socket.bind((HOST, PORT))
          server_socket.listen()

      with socket.socket(...) 구조를 사용하면 서버 종료 시 server_socket.close()가 자동으로 호출된다.

       

      accept() 반복과 스레드 생성

      accept() + Thread 코드 보기
      while True:
          client_socket, client_address = server_socket.accept()
      
          print(f"클라이언트 접속: {client_address}")
      
          client_thread = threading.Thread(
              target=handle_client,
              args=(client_socket, client_address)
          )
      
          client_thread.start()

       

      코드 의미
      target=handle_client 새 스레드에서 실행할 함수 (괄호 없이 함수 이름만 전달)
      args=(client_socket, client_address) handle_client()에 전달할 인자
      client_thread.start() 스레드 실행 시작, 메인 흐름은 즉시 다음 accept()로 이동

       

      핵심
      accept()가 while True 안에 있기 때문에 서버는 한 명의 클라이언트를 처리하느라 멈추지 않는다. 클라이언트 처리는 스레드가 담당하고, 메인 스레드는 계속 새 접속을 받는다.

       

      자주 하는 실수
      client_thread.start() 다음에 join()을 호출하면 메인 스레드가 해당 스레드가 끝날 때까지 기다리게 된다. 결국 한 명씩 순차 처리하게 되므로 다중 접속 서버의 장점이 사라진다.

       

      클라이언트 - 반복 송수신 구조

      클라이언트 코드 보기
      import socket
      
      HOST = "127.0.0.1"
      PORT = 5000
      
      with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:
          client_socket.connect((HOST, PORT))
      
          print("서버에 연결되었습니다.")
          print("종료하려면 exit을 입력하세요.")
      
          while True:
              message = input("보낼 메시지: ")
              client_socket.send(message.encode("utf-8"))
      
              if message == "exit":
                  print("서버와의 연결을 종료합니다.")
                  break
      
              data = client_socket.recv(1024)
              response = data.decode("utf-8")
      
              print(response)
      
      print("클라이언트 소켓을 닫았습니다.")

       

      주의
      서버가 exit를 받은 뒤 소켓을 닫으므로, 클라이언트는 exit를 보낸 뒤 recv()를 호출하면 안 된다. 그래서 exit를 전송한 직후 break로 반복문을 종료한다.

      'Server - Client' 카테고리의 다른 글

      전체 채팅 브로드캐스팅  (0) 2026.06.23
      접속자 목록 관리  (0) 2026.06.23
      스레드 개념과 기초 사용법  (0) 2026.06.23
      여러 클라이언트 접속 구조  (0) 2026.06.23
      1:1 터미널 채팅 완성하기  (0) 2026.06.22
      다음글
      다음 글이 없습니다.
      이전글
      이전 글이 없습니다.
      댓글
    조회된 결과가 없습니다.
    스킨 업데이트 안내
    현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
    ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
    목차
    표시할 목차가 없습니다.
      • 안녕하세요
      • 감사해요
      • 잘있어요

      티스토리툴바