2016-10-19 1 views
2

В качестве контекста для моего вопроса я впервые участвую в Python. До этого я работал в основном с Java, и сейчас я лучше всего разбираюсь в соглашениях и практиках Java.Программирование сокетов Python 3: использование sendall vs. sendto

фон

Уступка для программирования сокетов спрашивает, что мы посылаем строки между сервером и клиентом на локальном компьютере. Нам предоставляется образец (Python 2), который создает сервер и клиент. Вне контекста задания, я хотел создать версию этого кода, который также работает в Python 3, но у меня были проблемы с получением клиента работать так же в Python 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() 

Я не в состоянии преобразовать стороне клиента в код, который работает и функционирует в Python 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. Я все еще не совсем уверен, почему это работает или почему я должен это делать (хотя я был бы признателен за объяснение).

Теперь, когда я запускаю клиентский код, я получаю тот же TypeError на сервере, даже когда я использую sendto(), но я не уверен, как решить эту проблему на Python 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' 

Что я делаю неправильно и как я смог получить эту работу в Python 3? Фоновый контекст, почему это было бы особенно полезно, поскольку, по моему мнению, часть моей проблемы заключается в том, что я не вижу, почему это изменение необходимо для начала. Благодаря!

+1

'SendTo()' для датаграмм сокетов, а не поток сокеты. С потоковым сокером вам не нужно указывать, куда отправлять, потому что поток уже подключен к определенной конечной точке. – Barmar

+0

@ Бармар я вижу. Итак, как я смогу создать сокет потока для приложения этой программы? Есть ли что-то другое, что я должен делать, или мне нужно внести изменения в использование 'sendall()', чтобы заставить его работать, как я бы хотел? – jflory7

+2

'sock.accept()' возвращает сокет потока, вам не нужно ничего делать специальным. – Barmar

ответ

1

Не используйте sendto() на розетке потока. Как только сокет подключен (и с сокетами потока вы не можете выполнять передачу данных до тех пор, пока не подключитесь), вы не можете указать получателя, он всегда отправляется на удаленный адрес/порт, к которому он подключен.

Так используйте send() или sendall():

socket.sendall("Hello world".encode()); 
Смежные вопросы