먼저 설명해야 할 점은 이 기사에서는 심오한 소켓 프로그래밍을 기록하지 않고 가장 간단한 소켓 프로그래밍 채팅방에서 몇 가지 특별한 예외 처리를 분석한다는 것입니다.
서버:
import socket HOST = "" PORT = 8870 sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sk.bind((HOST, PORT)) sk.listen(5) while True: print("服务器启动") conn, addr = sk.accept() print(addr) while True: try: server_recv_data = conn.recv(1024) #若客户端输入exit退出,则此处并没有阻塞,只是收到的信息为空 #若客户端输入空,即直接按下回车键,那么此处将会被阻塞 if len(server_recv_data) == 0: print("收到为空") break except ConnectionResetError as err: print(err) break print(str(server_recv_data, encoding="utf-8")) server_resp_data = input(">>>") conn.sendall(bytes(server_resp_data, encoding="utf-8")) conn.close() sk.close()
클라이언트:
import socket HOST = "127.0.0.1" PORT = 8870 sk = socket.socket() sk.connect((HOST, PORT)) print("客户端启动...") while True: inp = input(">>>") if inp == "exit"or not inp: #此处需要说明的是,当直接在客户端按下回车enter键的时候,inp为空 break sk.sendall(bytes(inp, encoding="utf-8")) server_response = sk.recv(1024) print(str(server_response, encoding="utf-8")) sk.close()
참고:
1. 클라이언트가 강제로 닫힐 때(예: pycharm에서 디버그를 누를 때) 창 왼쪽에 있는 버튼을 누르면 클라이언트는 당연히 오류를 보고하지만, Linux 시스템에서는 서버는 수신된 정보, 즉 server_recv_data가 비어 있다고만 생각합니다. 여기가 비어 있으므로 서버가 이를 수행합니다. 다른 클라이언트가 보낸 연결 요청을 연결할 수 있도록 내부 루프를 종료하라는 판단이 내려집니다.
2. 현재 채팅에서 클라이언트는 중단을 판단하여 이때 서버가 얻은 결과가 server_recv_data가 비어 있다는 것입니다. 이는 위의 상황과 동일합니다.
3. server-recv_data = conn.recv(1024)를 차단할 수 있는 것은 클라이언트가 직접 Enter 키를 누르는 것입니다. 이때 당황스러운 상황은 서버가 여전히 클라이언트가 정보를 보내기를 기다리고 있다는 것입니다(정보가 없다고 생각함). 도착) 클라이언트는 방금 Enter를 눌렀기 때문에 더 이상 정보를 보낼 수 없습니다. 정보를 다시 입력할 수는 있지만 보낼 수는 없습니다(Enter를 다시 눌러도 소용 없음). 따라서 이 문제를 해결하기 위해 다음을 기본값으로 설정합니다. 클라이언트가 이 작업을 수행한다는 것은 이때 inp가 비어 있음을 의미하므로 클라이언트가 inp가 아닌지 판단을 통과한 후 채팅을 종료하면 서버는 빈 메시지를 수신하고 휴식 후에도 계속 다른 인연을 기다리세요