Firefox shows connection reset error when server closes connection - python

I have created a simple python server that sends back everything it receives.
I wonder if it would be possible to close the connection immediately after sending the data to the client (web browser), and the client then displays the data it has received. Currently, the client displays The connection was reset.
Thanks
#!/user/bin/env python3
import socket
HOST = 'localhost' # loopback interface address
PORT = 3000 # non-privileged ports are > 1023
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
while True:
# connect to the next client in queue
conn, addr = s.accept()
with conn:
print('Connected by', addr)
data = conn.recv(1024).decode()
print(data)
conn.sendall(data.encode())

Solution
#!/user/bin/env python3
import socket
HOST = 'localhost' # loopback interface address
PORT = 3000 # non-privileged ports are > 1023
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
while True:
# connect to the next client in queue
conn, addr = s.accept()
print('Connected by', addr)
data = conn.recv(1024).decode()
print(data)
conn.sendall(data.encode())
conn.shutdown(socket.SHUT_WR) # changed
Explanation
The solution uses conn.shutdown(socket.SHUT_WR) which sends a FIN signal instead of conn.close() which sends a RST signal.
We don't want to force the connection to close. TCP setup is expensive, so the browser would ask the server to keep the connection alive to query assets, and in this example the browser asks for style.css.
RST confuses the browser, and Firefox will show you "connection reset" error.
FIN says: "I finished talking to you, but I'll still listen to everything you have to say until you say that you're done."
RST says: "There is no conversation. I won't say anything and I won't listen to anything you say."
from FIN vs RST in TCP connections
Here is the Wireshark capture of using shutdown, we see that both the server at 3000 and the browser acknowledged each other's FIN.
When using close, we see that
A better option would be to wait for the client to initiate the 4 way finalization by programming the server to shut down the socket when the client signals FIN.
The 4 way finalization
From https://www.geeksforgeeks.org/tcp-connection-termination/

Related

server-client where the client listens and responds in a loop doesn't work (python)

I'm building a Client-Server connection for an assignment. The server basically runs everything and the client only receives messages from the server and responds when the server needs it to.
For some reason, I can't build a client that repeatedly listens and then responds.
I thought that I could just listen with socket.recv() and it ended up just stopping everything.
this is what I ended up with after some tweaking (for the client) :
import socket
HOST = 'localhost'
PORT = 65432
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((HOST, PORT))
conn.setblocking(False)
while True :
try :
msg_lgn = len(conn.recv(1024,socket.MSG_PEEK))
server_message = conn.recv(1024).decode()
print('Server Sent:\n' + server_message)
if server_message == 'exit':
break
except :
conn.send(input().encode())
conn.close()
I set it to non-blocking so it won't hang on the conn.recv() and move on to input in the exception, but then it just freezes on the input.
does the server close the connection every time recv() gets nothing ? why is this happening ?
I just want the client to receive messages whenever the server sends them, and when the server doesn't send, the client will send the server it's input.
would appreciate any help!
Lidor
Edit : the server file is much bigger, so i'll show the important parts.
#imported some classes for the game itself also (that i've created), but has nothing to do with the problem
import socket
import time
import threading
def startGame(conn):
#this is where the servers sends the questions and receives answer (pretty basic send and recv)
# Establish Client-Server Connection
HOST = 'localhost' # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(3)
# Use Threading to start the game for an new player
while True:
if playerCount < 3:
(conn, addr) = s.accept()
playerCount += 1
x = threading.Thread(target=startGame, args=(conn,))
x.start()
# Close Server Socket
s.close()

Is there a way to send two messages with socket

Im trying to send a messages from the server to the client
I tried deleting the .close and puting a while loop on print but it still doesn't won't to work
Client
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.connect((host, port))
while True:
print (s.recv(1024))
Server
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print ('Got connection from', addr)
x = str(input("ënter a message"))
data = x.encode()
c.send(data)
I expect the output to be 2 messages from the server but it is only sending 1 and then closing the connection
Switch your accept and while True: lines. Once you accept a connection, keep sending on the same connection.
Note that TCP is a streaming protocol. There is no concept of "messages", but just a bunch of bytes. If you send fast enough, such as:
c.send(b'abc')
c.send(b'def')
then recv(1024) could receive b'abcdef'. For more complex communication, you'll have to define a protocol and buffer recv until you are sure you have a complete message. A simple way in this case is read until you find a newline, or send a byte (or more) indicating the size of the total message before sending the actual message.

Python socket sends the first message but nothing afterward

My socket sends the first message but nothing afterward.
The output in the server:
What do you want to send?
lol
The client receives:
From localhost got message:
lol
And then it doesn't want to send anything else.
I don't get the what do you want to send printed anymore.
My code:
server.py file:
#!/usr/bin/python3
import socket
# create a socket object
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = socket.gethostname()
print ("got host name:", host)
port = 9996
print("connecting on port:", port)
# bind to the port
serversocket.bind((host, port))
print("binding host and port")
# queue up to 5 requests
serversocket.listen(5)
print("Waiting for connection")
while True:
clientsocket, addr = serversocket.accept()
msg = input("what do you want to send?\n")
clientsocket.send(msg.encode('ascii'))
client.py file:
#!/usr/bin/python3
import socket # create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # get local machine
# name
host = socket.gethostname()
port = 9996 # connection to hostname on the port.
s.connect((host, port)) # Receive no more than 1024 bytes
while True:
msg = s.recv(1024)
print(msg.decode("ascii"))
The client only connects once (OK) but the server waits for an incoming connection every start of the while loop.
Since there are no more connection requests by a client, the server will freeze on the second iteration.
If you just want to handle a single client, move clientsocket, addr = serversocket.accept() before the while loop. If you want to handle multiple clients, the standard way is to have the server accept connections inside the while loop and spawn a thread for each client.
You can also use coroutines, but that may be a bit overkill if you are just starting out.

Python socket not receiving without sending

I copied the echo server example from the python documentation and it's working fine. But when I edit the code, so it wont send the data back to the client, the socket.recv() method doesn't return when it's called the second time.
import socket
HOST = ''
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(b'ok')
conn.close()
In the original version from the python documentation the while loop is slightly different:
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
Client's code:
import socket
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
s.close()
print('Received', repr(data))
TCP sockets are streams of data. There is no one-to-one correlation between send calls on one side and receive calls on the other. There is a higher level correlation based on the protocol you implement. In the original code, the rule was that the server would send exactly what it received until the client closed the incoming side of the connection. Then the server closed the socket.
With your change, the rules changed. Now the server keeps receiving and discarding data until the client closes the incoming side of the connection. Then the server sends "ok" and closes the socket.
A client using the first rule hangs because its expecting data before it closes the socket. If it wants to work with this new server rule, it has to close its outgoing side of the socket to tell the server its done, and then it can get the return data.
I've updated the client and server to shutdown parts of the connection and also have the client do multiple recv's in case the incoming data is fragmented. Less complete implementations seem to work for small payloads because you are unlikely to get fragmentation, but break horribly in real production code.
server
import socket
HOST = ''
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(b'ok')
conn.shutdown(socket.SHUT_WR)
conn.close()
client
import socket
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
s.shutdown(socket.SHUT_WR)
data = b''
while True:
buf = s.recv(1024)
if not buf:
break
data += buf
s.close()
print('Received', repr(data))
The number of receive and send operations have to match because they are blocking. This is the flow diagram for your code:
Server listen
Client connect
Server receive (this waits until a message arrives at the server) [1]
Client send 'Hello world' (received by [1])
Server receive (because there was data received) [2]
Client receive [3]
Because the server and the client are blocked now, no program can continue any further.
The fix would be to remove the client's receive call because you removed the server's send call.

How to open a Port on Server

I am new to opening a port and server side programming. And I am trying to open a port on my server in python and then form an iOS app get some data from that port. I have done some research and know I can open a port like this
import socket # Import socket module
s = socket.socket() # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print 'Got connection from', addr
c.send('Thank you for connecting')
c.close() # Close the connection
But my question is lets say I just wanted to retrieve a simple string from this port how do I add that string to this open port, I have found some ways to get data from the port in iOS like this library https://github.com/armadsen/ORSSerialPort but how do I put the data like a string on the open port?
Thanks for the help in advance.
When you call the method s.accept() it will return the socket object as the first return. You can call socket.rescv method to read data -
data = c.recv(1024)
But do remember this is a blocking call. For more information, you can read this post.

Categories

Resources