J.W.F.
J.W.F.

Reputation: 701

Python 3 socket programming: using sendall vs. sendto

As context to my question, I am a computing student getting started with Python for the first time. Before this, I've worked mostly with Java and I am most comfortable with Java conventions and practices right now.

Background

An assignment for socket programming asks that we send strings between a server and client locally on the machine. We are provided sample (Python 2) code that instantiates a server and client. Outside of the context of the assignment, I wanted to create a version of this code that also runs in Python 3, but I was having problems getting the client to work the same in Python 3.

Changing server and client

Originally, the server required little changes and I was able to get it working. My code for the server is as follows:

#!/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()

I'm not able to convert the client side to code that runs and functions within Python 3. I've tried digging deeper into the issue, but other online resources are not helpful for me (or at least, at my experience level). My server code is as follows.

#!/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()

The actual problem

Originally, this code for both the server and client used sendall() instead of sendto(), but I changed it after getting a TypeError in the client and reading this question. I'm still not exactly sure why this works or why I have to do this (although I would appreciate an explanation).

Now, when I run the client code, I'll get the same TypeError on the server even when I'm using sendto(), but I'm not sure how to resolve this problem in Python 3. The stacktrace I receive for the server as follows (I get a broken pipe on the client):

$ 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'

What am I doing wrong and how am I able to get this working in Python 3? Background context as to why this is would be especially helpful as I think part of my problem is that I'm not seeing why this change is necessary to begin with. Thanks!

Upvotes: 4

Views: 13458

Answers (1)

Barmar
Barmar

Reputation: 781300

Don't use sendto() on a stream socket. Once a socket is connected (and with stream sockets you can't do any data transfer until after connecting), you can't specify the destination, it's always sent to the remote address/port to which it's connected.

So use send() or sendall():

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

Upvotes: 3

Related Questions