【问题标题】:Python 3 socket programming: using sendall vs. sendtoPython 3 套接字编程:使用 sendall 与 sendto
【发布时间】:2016-10-19 19:16:23
【问题描述】:

作为我的问题的上下文,我是一名计算机专业的学生,​​第一次开始使用 Python。在此之前,我主要使用 Java,现在我最熟悉 Java 约定和实践。

背景

套接字编程的任务要求我们在机器上本地的服务器和客户端之间发送字符串。我们提供了实例化服务器和客户端的示例 (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 后,我对其进行了更改。我仍然不确定为什么会这样或者为什么我必须这样做(尽管我希望得到解释)。

现在,当我运行客户端代码时,即使我使用 sendto(),我也会在服务器上得到相同的 TypeError,但我不确定如何在 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 中让它工作?关于为什么这样做的背景背景会特别有帮助,因为我认为我的问题的一部分是我不明白为什么要开始进行这种更改。谢谢!

【问题讨论】:

  • sendto() 用于数据报套接字,而不是流套接字。使用流套接字,您不需要告诉它发送到哪里,因为流已经连接到特定的端点。
  • @Barmar 我明白了。那么我如何才能为这个程序的应用程序创建一个流套接字呢?我应该做些什么不同的事情,还是我需要更改使用 sendall() 才能让它像我想要的那样工作?
  • sock.accept() 返回一个流套接字,你不需要做任何特别的事情。
  • 只需使用conn.send()conn.sendall()
  • 您说您从 sendall 更改为 sendto 是因为您在另一个问题中读到的内容。我在那个问题中没有看到任何内容表明您应该这样做。它说使用message.encode()message.decode() 来解决他们遇到的问题。

标签: python sockets python-3.x networking


【解决方案1】:

不要在流套接字上使用sendto()。一旦连接了套接字(并且使用流套接字,在连接之前您无法进行任何数据传输),您无法指定目的地,它总是被发送到它所连接的远程地址/端口。

所以使用send()sendall()

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

【讨论】:

    猜你喜欢
    • 2021-10-11
    • 2012-06-15
    • 2011-04-29
    • 2011-02-09
    • 2015-07-20
    • 2015-09-14
    • 2015-07-27
    • 2014-05-23
    • 1970-01-01
    相关资源
    最近更新 更多