2016-10-19 5 views
2

제 질문에 대한 맥락에서 저는 처음으로 파이썬을 시작하는 컴퓨팅 학생입니다. 이 전에는 주로 Java로 작업했으며 Java 관례 및 관행에 가장 익숙합니다.Python 3 소켓 프로그래밍 : sendall과 sendto 사용

배경

소켓 프로그래밍에 대한 할당 우리가 시스템에 로컬로 서버와 클라이언트 사이에 문자열을 보내 줄 것을 요청합니다. 우리는 서버와 클라이언트를 인스턴스화하는 샘플 (파이썬 2) 코드를 제공한다. 과제 컨텍스트 외부에서 파이썬 3에서도 실행되는이 코드의 버전을 만들고 싶었지만 파이썬 3에서 클라이언트가 똑같이 작동하도록하는 데 문제가있었습니다.

서버와 클라이언트 변경

원래 서버는 거의 변경하지 않아도 작동 할 수있었습니다.

#!/usr/bin/python3 

import socket 

HOST='' 
PORT=5870 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.bind((HOST, PORT)) 
sock.listen(1) 
conn, addr = sock.accept() 

print('Connected by ', addr) 
conn.sendto("Welcome to the server!", (HOST, PORT)) 

while True: 
    data = conn.recv(1024) 
    if not data: break 
    conn.sendall(data) 

conn.close() 

파이썬 3에서 실행 및 기능 나는이 문제에 깊이 파고 시도했다고 코딩하는 클라이언트 측 변환 할 수 아니지만, 다른 온라인 리소스를 다음과 같이 서버에 대한 내 코드는 나에게 도움이되지 않는다 (적어도 내 경험 수준에서). 내 서버 코드는 다음과 같습니다.

#!/usr/bin/python3 

import socket 

HOST='127.0.0.1' 
PORT=5870 

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.connect((HOST, PORT)) 
data = sock.recv(1024) 
print('Server sent', data) 

sock.sendto("Hello world".encode(), (HOST, PORT)) 

data = sock.recv(1024) 
print("Server sent", data) 

sock.sendto("This is the second message".encode(), (HOST, PORT)) 
data = sock.recv(1024) 
print('Server sent ', data) 

sock.close() 

가 원래 서버와 클라이언트 모두이 코드는 sendall() 대신 sendto()을 사용하지만 클라이언트에 TypeError을 받고 this question를 읽은 후 그것을 변경 실제 문제. 나는 아직도 이것이 왜 작동하는지, 왜 이것을해야만하는지에 대해 정확히 모르겠다. (비록 내가 설명을 감사 하겠지만).

이제 클라이언트 코드를 실행하면 sendto()을 사용할 때도 서버에 동일한 TypeError을 갖지만 파이썬 3에서이 문제를 해결하는 방법을 모르겠습니다. 내가 파이썬 3에서이 작업을 얻을 수

$ python3 mail_server.py 
Connected by ('127.0.0.1', 41866) 
Traceback (most recent call last): 
    File "mail_server.py", line 14, in <module> 
    conn.sendto("Welcome to the server!", (HOST, PORT)) 
TypeError: a bytes-like object is required, not 'str' 
내가 잘못 뭐하는 거지

방법입니다 : 서버에 대한 (I 클라이언트에서 깨진 파이프를 얻을) 다음과 같이? 왜 이것이 내 문제의 일부로 생각 하느냐에 따라 이것이 도움이 될 것이라는 배경 컨텍스트는이 변경이 왜 시작해야 하는지를 알 수 없다는 것입니다. 감사!

+1

'sendto를을, 소켓을 스트리밍 할. 스트림 소켓을 사용하면 스트림이 이미 특정 끝점에 연결되어 있기 때문에 보낼 곳을 말할 필요가 없습니다. – Barmar

+0

@Barmar 알겠습니다. 그렇다면이 프로그램의 응용 프로그램을위한 스트림 소켓을 어떻게 만들 수 있습니까? 내가해야 할 일과 다른 뭔가가 있는가, 아니면 sendall()을 사용하여 원하는대로 작동하도록 변경해야 하는가? – jflory7

+2

'sock.accept()'는 스트림 소켓을 돌려 준다. 특별한 일을 할 필요가 없다. – Barmar

답변

1

스트림 소켓에는 sendto()을 사용하지 마십시오. 일단 소켓이 연결되면 (그리고 연결 후까지 데이터 전송을 할 수없는 스트림 소켓과 함께) 대상을 지정할 수 없으며, 항상 연결되어있는 원격 주소/포트로 보내집니다.

그래서 send() 또는 sendall()을 사용 : (가)`데이터 그램 소켓을위한

socket.sendall("Hello world".encode());