Python: [Errno 10054] an Existing Connection Was Forcibly Closed by the Remote Host

Python - [Errno 10054] An existing connection was forcibly closed by the remote host - sending pickled data issues

I managed to finally accomplish what I wanted to do in the first place. I wanted to write a send function that sent out X amount of pickled data alongside a receive function that received X amount of pickled data without throwing errors when it received data that was too small to be pickled.

See the send_data and the receive_data functions for the solution in network.py. The server file server.py requires these functions as well although slightly different. In your client file you should thus make use of the network.send_data function to send data from the client to the server.

network.py

import socket
import pickle
HEADERSIZE = 10

class Network:
def __init__(self):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server = "enter server address"
self.port = 5555
self.addr = (self.server, self.port)
self.p = self.connect()

def getP(self):
return self.p

def connect(self):
try:
self.client.connect(self.addr)
return self.client.recv(2048).decode()
except:
pass

# works but only sends and receives string encoded data without a buffer
def send1(self, data):
try:
self.client.send(str.encode(data))
return pickle.loads(self.client.recv(2048))
except socket.error as e:
print(e)

# works but only sends and receives pickled data without a buffer
def send2(self, data):
try:
self.client.send(pickle.dumps(data))
return pickle.loads(self.client.recv(2048))
except socket.error as e:
print(e)

# this is the function you should use, it uses a receive function that has a buffer
# and ensures that you receive ALL the information that you sent without throwing errors
def send_data(self, data):
data_to_send = pickle.dumps(data)
data_size = bytes(f'{len(data_to_send):<{10}}', "utf-8")
try:
self.client.send(data_size + data_to_send)

package = self.receive_data()
return package
except socket.error as e:
print(e)

def receive_data(self):
full_msg = b''
new_msg = True
while True:
msg = self.client.recv(16)
if new_msg:
msglen = int(msg[:HEADERSIZE])
new_msg = False

full_msg += msg

if len(full_msg)-HEADERSIZE == msglen:
data = pickle.loads(full_msg[HEADERSIZE:])
break

return data

server.py

import socket
import pickle
from _thread import *
import sys
from game import Game

server = "enter server address"
port = 5555

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
s.bind((server, port))
except socket.error as e:
print(e)

s.listen(2)
print("Waiting for a connection, Server Started")

connected = set()
games = {}
id_count = 0
HEADERSIZE = 10

def receive_data(sock):
full_msg = b''
new_msg = True
while True:
msg = sock.recv(16)
if new_msg:
msglen = int(msg[:HEADERSIZE])
new_msg = False

full_msg += msg

if len(full_msg)-HEADERSIZE == msglen:
data = pickle.loads(full_msg[HEADERSIZE:])
break

return data

def send_data(clientsocket, data):
data_to_send = pickle.dumps(data)
data_size = bytes(f'{len(data_to_send):<{10}}', "utf-8")
try:
clientsocket.send(data_size + data_to_send)

except socket.error as e:
print(e)

def threadedClient(conn, p, game_id):
global id_count
conn.send(str.encode(str(p)))

reply = ""
while True:
try:
data = receive_data(conn)
# check if the game still exists
if game_id in games:
game = games[game_id]

if not data:
break
else:
if data == "reset":
game.resetWent()
elif data != "get":
game.play(p, data)

reply = game

send_data(conn, reply)

else:
break
except Exception as e:
print("Failed try")
print(e)
break

print("Lost connection")

try:
print("Closing game", game_id)
del games[game_id]
except:
pass

id_count -=1
conn.close()


while True:
conn, addr = s.accept()
print("Connected to: ", addr)

id_count += 1
p = 0
game_id = (id_count - 1) // 2

if id_count % 2 == 1:
games[game_id] = Game(game_id)
print("Creating a new game...")
else:
games[game_id].ready = True
p = 1


start_new_thread(threadedClient, (conn, p, game_id))

How to handle urllib.error.URLError: <urlopen error [WinError 10054] An existing connection was forcibly closed by the remote host>?

For possible causes for this error, you could have a look at python: [Errno 10054] An existing connection was forcibly closed by the remote host. My conclusion after reading the highest vote answers is just that it can happen and your code should be prepared to it.

I would use a try: ... except ... block in a loop here and and add a increasing delay before retrying a failed connection:

def download_file(url):
# prefere with when exceptions are expected
with open(url.split("=")[-1] + ".pdf", 'wb') as fp:
delay = 5
max_retries = 3
for _ in range(max_retries):
try:
req = urlopen(url)
CHUNK = 20480
chunk = req.read(CHUNK)
fp.write(chunk)
break # do not loop after a successfull download...
except urllib.error.URLError:
time.sleep(delay)
delay *= 2
else: # signal an abort if download was not possible
print(f"Failed for {url} after {max_retries} attempt")
# or if you want to abort the script
# raise Exception(f"Failed for {url} after {max_retries} attempt")

How to catch this Python exception: error: [Errno 10054] An existing connection was forcibly closed by the remote host

The error type is socket.error, the documentation is here.
Try modiffying your code like this:

import socket
import errno

try:
Deleting filename
self.ftp.delete(filename)
return True
except (error_reply, error_perm, error_temp):
return False
except socket.error as error:
if error.errno == errno.WSAECONNRESET:
reconnect()
retry_action()
else:
raise


Related Topics



Leave a reply



Submit