2단계: 애코 구현

1. 학습 목표
2. Telnet 활성화
더보기

Telnet 클라이언트는 사용자가 입력한 문자열을 그대로 TCP 서버로 전송하는, 가장 단순한 네트워크 테스트 도구입니다.

- Telnet = 가장 단순한 TCP 클라이언트
- 데이터 형식 = Plain Text(문자열)
- 목적 = 서버 연결 테스트, 데이터 수신 확인, 디버깅
2-1단계: 서버 수신 구조 이해
더보기




(1) 동작 구조

(2) 서버 구현
# 2-1단계: 서버 수신 구조 이해
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QLabel
from PySide6.QtNetwork import QTcpServer, QHostAddress
class ServerWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Server Window")
self.resize(400, 300) # 창 크기
self.label = QLabel("Waiting...", self)
self.label.setGeometry(50, 50, 300, 50)
self.server = QTcpServer(self)
self.server.newConnection.connect(self.on_new_connection)
# 가장 단순한 안전장치: 연결 소켓을 저장
self.client_socket = None
ok = self.server.listen(QHostAddress("10.10.21.100"), 8888)
if not ok:
self.label.setText("Listen failed")
def on_new_connection(self):
# 단일 클라이언트만 받는 가장 단순 버전
self.client_socket = self.server.nextPendingConnection()
self.client_socket.readyRead.connect(self.on_ready_read)
self.label.setText("Client connected")
def on_ready_read(self):
data = self.client_socket.readAll()
message = bytes(data).decode(errors="replace")
# [추가 1] telnet 입력 그대로 콘솔 출력
print(message, end="")
# [추가 2] 마지막 입력만 라벨에 표시
self.label.setText(f"Received: {message}")
if __name__ == "__main__":
app = QApplication(sys.argv)
w = ServerWindow()
w.show()
sys.exit(app.exec())
(3) Telnet 클라이언트에서, 서버 연결 테스트



2-2단계: 에코 서버 구현
더보기


(1) 동작 구조

(2) 구현 방향
1-3 단계에서 클라이언트의 데이터 전송 로직을
서버의 데이터 수신 후에 동작하도록 추가합니다.
(3) 서버 구현
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QLabel
from PySide6.QtNetwork import QTcpServer, QHostAddress
class ServerWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Echo Server")
self.resize(400, 300)
self.label = QLabel("Waiting...", self)
self.label.setGeometry(50, 50, 300, 50)
self.server = QTcpServer(self)
self.server.newConnection.connect(self.on_new_connection)
# 단일 클라이언트용 연결 소켓
self.client_socket = None
ok = self.server.listen(QHostAddress("10.10.21.100"), 8888)
if not ok:
self.label.setText("Listen failed")
def on_new_connection(self):
self.client_socket = self.server.nextPendingConnection()
self.client_socket.readyRead.connect(self.on_ready_read)
self.label.setText("Client connected")
def on_ready_read(self):
data = self.client_socket.readAll()
message = bytes(data).decode(errors="replace")
# 1) 서버 콘솔에 그대로 출력
print(message, end="")
# 2) GUI 라벨에 마지막 메시지 표시
self.label.setText(f"Received: {message}")
# 3) Echo: 받은 데이터를 그대로 클라이언트에게 재전송
self.client_socket.write(data)
self.client_socket.flush() # Telnet에서 즉시 보이도록 보조
if __name__ == "__main__":
app = QApplication(sys.argv)
w = ServerWindow()
w.show()
sys.exit(app.exec())

ㄴ Telnet 모바일 앱에서 Data 전송
더보기


모바일에서 telnet 앱으로 검색하고, IP, Port 입력한다.

터미널에서 입력하던 방법과 동일한 결과를 보여준다.
(1) 동작 구조

(2) 시연


2-3단계: (과제) 에코 클라이언트 구현
더보기

(1) 동작 구조

(2) 구현 방법
이전 포스트의 클라이언트 코드 기반으로 구현.
위의 서버 로직에서 "메시지를 전달받고, UI로 출력하는 부분"을 클라이언트에 추가 구현
(3) 클라이언트 구현
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton, QLineEdit, QLabel
from PySide6.QtNetwork import QTcpSocket
class ClientWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Echo Client Window")
self.resize(420, 220)
# 입력창
self.line = QLineEdit(self)
self.line.setGeometry(50, 40, 250, 30)
# 전송 버튼
btn = QPushButton("Send", self)
btn.setGeometry(310, 40, 70, 30)
btn.clicked.connect(self.send_message)
# [추가 1] 에코 출력용 레이블
self.echo_label = QLabel("Echo: (아직 수신 없음)", self)
self.echo_label.setGeometry(50, 90, 330, 30)
# [1] 클라이언트 소켓 생성
self.socket = QTcpSocket(self)
# [추가 2] 서버로부터 데이터 수신 시 처리할 슬롯 연결
self.socket.readyRead.connect(self.on_ready_read)
# (선택) 연결/해제 상태를 보고 싶으면 아래도 사용 가능
# self.socket.connected.connect(lambda: self.echo_label.setText("Echo: 서버 연결됨"))
# self.socket.disconnected.connect(lambda: self.echo_label.setText("Echo: 서버 연결 끊김"))
# [2] 서버로 연결 요청
self.socket.connectToHost("127.0.0.1", 8888)
def send_message(self):
# [3] 전송(송신) 로직
text = self.line.text()
if not text:
return
# Telnet/서버 코드에서 줄 단위 처리할 때를 대비해 \n을 붙이는 것을 권장
self.socket.write((text + "\n").encode("utf-8"))
self.line.clear()
# [추가 3] 서버 에코 수신 처리(수신 로직)
def on_ready_read(self):
data = self.socket.readAll()
message = bytes(data).decode("utf-8", errors="replace").strip()
# UI에 표시(마지막 수신만 표시)
self.echo_label.setText(f"Echo: {message}")
# 콘솔에서도 확인(학습용)
print("ECHO:", message)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = ClientWindow()
w.show()
sys.exit(app.exec())
3. 목표: 서버 클라이언트 구조

