How to keep trying to establish connection in Python - python

If the server is not up when I try to run the following code, I just get a Connection refused error.
How can I make the sender below to keep trying to establish connection and perhaps sending until the remote server is indeed up and the connection is successfully established?
HOST = client_ip # The remote host
PORT = port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(msg)
if expect_receive:
received_data = s.recv(1024)
print received_data
#client has started
s.close()
return

How about brute force? Something like this
import time
while 1:
HOST = client_ip # The remote host
PORT = port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((HOST, PORT))
except:
print("FAILED. Sleep briefly & try again")
time.sleep(10)
continue
s.sendall(msg)
if expect_receive:
received_data = s.recv(1024)
print received_data
#client has started
s.close()
return

I am using ssl with threads and the following works for me.
import socket, ssl
from threading import *
from _thread import *
from time import sleep
HOST_1, PORT_1, CERT_1 = '127.0.0.1', 443, 'certificate_1.pem'
HOST_2, PORT_2 = '127.0.0.1', 4430
def enviar():
#global morte;
sock = socket.socket(socket.AF_INET)
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH);
context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1
context.check_hostname = False;
context.load_verify_locations(cafile='certificate_2.pem');
conn = context.wrap_socket(sock, server_hostname=HOST_2);
while True:
try:
conn.connect((HOST_2, PORT_2));
break;
except:
print("\n=====Failed connection=====\n");
sleep(1);#vital, without it the script raises an exception
try:
while True:
x = input("--> ");
x = bytes(x, "utf-8");
conn.write(x)
print(conn.recv().decode())
except ssl.SSLError as e:
print(e);
except Exception as e:
print(e);
except KeyboardInterrupt:
print("\n====Bye!====\n");
if conn:
conn.close();
#morte = True;
###################
#parte original abaixo
def receber():
sock = socket.socket();
sock.bind((HOST_1, PORT_1));
sock.listen(5);
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH);
context.load_cert_chain(certfile=CERT_1, keyfile="private_1.pem") # 1. key, 2. cert, 3. intermediates
context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 # optional
context.set_ciphers('EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH')
while True:
conn = None;
ssock, addr = sock.accept();
try:
conn = context.wrap_socket(ssock, server_side=True);
while True:
print(conn.recv());
conn.write(b'HTTP/1.1 200 OK\n\n%s' % conn.getpeername()[0].encode());
break
except ssl.SSLError as e:
print(e)
except Exception as e:
print(e);
if conn:
conn.close();
finally:
if conn:
conn.close()
print("End!");
if __name__ == '__main__':
start_new_thread(receber, ());#1
start_new_thread(enviar, ());#2
If you run in association with another similar script (using other private key and certificates, obviously) it will run mostly ok, but, it will raise an:
EOF occurred in violation of protocol (_ssl.c:2472)
I am still trying to figure out how to deal with it.

Related

how can i make python socket listen after one client disconnect?

My server.py
import socket
s = socket.socket()
port = 12345
while True:
s.bind(('', port))
s.listen(5)
c, addr = s.accept()
print ("Socket Up and running with a connection from",addr)
while True:
rcvdData = c.recv(1024).decode()
print("S:",rcvdData)
c.send(rcvdData.encode())
if(sendData == "Bye" or sendData == "bye"):
break
c.close()
My client.py
import socket
s = socket.socket()
s.connect(('127.0.0.1',12345))
while True:
str = input("S: ")
s.send(str.encode());
if(str == "Bye" or str == "bye"):
break
print ("N:",s.recv(1024).decode())
s.close()
I have read to try to add try/except but im not sure where should i add that. Sorry for my english.
I want to accept connections even if no one is waiting to be accepted.
Multiple client connections are handled by calling accept, once per client. Nominally, you could just add a while loop plus exception handling to manage the connections:
import socket
import struct
s = socket.socket()
port = 12345
while True:
s.bind(('', port))
s.listen(5)
while True:
c, addr = s.accept()
print ("Socket Up and running with a connection from",addr)
try:
while True:
rcvdData = c.recv(1024).decode()
print("S:",rcvdData)
c.send(rcvdData.encode())
if(sendData == "Bye" or sendData == "bye"):
break
except (OSError, socket.error) as e:
print("Error:", e)
# reset connection
c.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
c.close()
else:
c.shutdown(socket.SHUT_RDWR)
c.close()
This will only allow a single client connection at at time. If you want to handle multiple connections at once, there are a hundred ways to do it and that's beyond the scope of an SO answer.

Python socket client always sending message

So I have this server file which is ok, always is up for connections, after sending a message from the client, client connection closes. I want the client to be up again for sending a message (get input again). I don't want to start the client again (in my case it's odev1.py)
# server.py
import socket
HOST = socket.gethostname()
PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
server_socket.bind((HOST, PORT))
server_socket.listen()
while True:
print('waiting for a connection')
connection, client_address = server_socket.accept()
try:
print(f'{client_address[0]} has entered the chat\n')
while True:
data = connection.recv(1024)
print(f'{client_address[0]} - {str(data, encoding="utf-8")}')
if data:
print('sending data back to the client')
connection.sendall(data)
else:
print('no data from', client_address[0])
break
finally:
print("Closing current connection")
connection.close()
this is my client ->
# client.py
import sys
import socket
host = socket.gethostname()
port = 65432
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error as e:
print("Error creating socket: %s" % e)
sys.exit(1)
# Second try-except block -- connect to given host/port
try:
s.connect((host, port))
except socket.gaierror as e:
print("Address-related error connecting to server: %s" % e)
sys.exit(1)
except socket.error as e:
print("Connection error: %s" % e)
sys.exit(1)
# Third try-except block -- sending data
try:
# NOTE: I want it to take input again
# Send data
message = input('write something: ')
s.sendall(message.encode('utf-8'))
print('sending {!r}'.format(message))
# Look for the response
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = s.recv(1024)
amount_received += len(data)
print('received {!r}'.format(data))
finally:
print('closing socket')
s.close()
this is how it looks right now:

How to send files in "chunks" by socket?

I'm trying to send a large file (.avi) over socket by sending the content of the file in chunks (a little bit like torrents). The problem is that the script doesn't send the file. I'm out of ideas here.
Any help or twerking of the script would be very appreciated.
Server:
import socket
HOST = ""
PORT = 8050
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
conn, addr = sock.accept()
print("Connected by ", str(addr))
while 1:
data = conn.recv(1024)
if data.decode("utf-8") == 'GET':
with open(downFile,'rb') as output:
l = output.read(1024)
while (l):
conn.send(l)
l = output.read(1024)
output.close()
conn.close()
Client:
import socket
HOST = "localhost"
PORT = 8050
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST,PORT))
while 1:
message = input()
sock.send(bytes(message,'UTF-8'))
conn.send(str.encode('GET'))
with open(downFile, 'wb+') as output:
while True:
rec = str(sock.recv(1024), "utf-8")
if not rec:
break
output.write(rec)
output.close()
print('Success!')
sock.close()
Here are a working client and server that should demonstrate transferring a file over a socket. I made some assumptions about what your code was supposed to do, for example, I assumed that the initial message the client sent to the server was supposed to be the name of the file to download.
The code also includes some additional functionality for the server to return an error message to the client. Before running the code, make sure the directory specified by DOWNLOAD_DIR exists.
Client:
import socket
import sys
import os
HOST = "localhost"
PORT = 8050
BUF_SIZE = 4096
DOWNLOAD_DIR = "downloads"
def download_file(s, down_file):
s.send(str.encode("GET\n" + down_file))
rec = s.recv(BUF_SIZE)
if not rec:
return "server closed connection"
if rec[:2].decode("utf-8") != 'OK':
return "server error: " + rec.decode("utf-8")
rec = rec[:2]
if DOWNLOAD_DIR:
down_file = os.path.join(DOWNLOAD_DIR, down_file)
with open(down_file, 'wb') as output:
if rec:
output.write(rec)
while True:
rec = s.recv(BUF_SIZE)
if not rec:
break
output.write(rec)
print('Success!')
return None
if DOWNLOAD_DIR and not os.path.isdir(DOWNLOAD_DIR):
print('no such directory "%s"' % (DOWNLOAD_DIR,), file=sys.stderr)
sys.exit(1)
while 1:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((HOST, PORT))
except Exception as e:
print("cannot connect to server:", e, file=sys.stderr)
break
file_name = input("\nFile to get: ")
if not file_name:
sock.close()
break
err = download_file(sock, file_name)
if err:
print(err, file=sys.stderr)
sock.close()
Server:
import socket
import sys
import os
HOST = ""
PORT = 8050
BUF_SIZE = 4096
def recv_dl_file(conn):
data = conn.recv(1024)
if not data:
print("Client finished")
return None, None
# Get command and filename
try:
cmd, down_file = data.decode("utf-8").split("\n")
except:
return None, "cannot parse client request"
if cmd != 'GET':
return None, "unknown command: " + cmd
print(cmd, down_file)
if not os.path.isfile(down_file):
return None, 'no such file "%s"'%(down_file,)
return down_file, None
def send_file(conn):
down_file, err = recv_dl_file(conn)
if err:
print(err, file=sys.stderr)
conn.send(bytes(err, 'utf-8'))
return True
if not down_file:
return False # client all done
# Tell client it is OK to receive file
sent = conn.send(bytes('OK', 'utf-8'))
total_sent = 0
with open(down_file,'rb') as output:
while True:
data = output.read(BUF_SIZE)
if not data:
break
conn.sendall(data)
total_sent += len(data)
print("finished sending", total_sent, "bytes")
return True
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((HOST, PORT))
sock.listen(1)
keep_going = 1
while keep_going:
conn, addr = sock.accept()
print("Connected by", str(addr))
keep_going = send_file(conn)
conn.close() # close clien connection
print()
sock.close() # close listener

Connection reset by peer [errno 104] in Python 2.7

I've seen and read a lot about this particular issue on the internet.
I am writing a simple chat server and client using socket in python for learning purpose mainly.
I've observed an issue here.
Here is my server code :
__author__ = 'pchakraverti'
import socket
import select
import sys
class NickSocketMap(object):
count = 0
def __init__(self, nick, client_socket):
self.nick = nick
self.client_socket = client_socket
NickSocketMap.count += 1
#staticmethod
def display_count():
print "Total number of clients is %d" % NickSocketMap.count
host = ""
port = 7575
socket_list = []
nick_list = []
cnt = 0
recv_buffer = 1024
def register_nick(nick, client_socket):
obj = NickSocketMap(nick, client_socket)
nick_list.append(obj)
def process_request(request_string, client_socket):
parts = request_string.split("|")
if parts[0] == "set_nick":
register_nick(parts[1], client_socket)
client_socket.send("nick_set")
elif parts[0] == "transmit_msg":
broadcast_message(parts[1], parts[2])
return 1
def broadcast_message(message, client_nick):
for s in nick_list:
if s.nick == client_nick:
try:
s.client_socket.send(message)
except socket.errno, ex:
print ex
break
def run_server():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.bind((host, port))
except socket.errno, ex:
print ex
sys.exit(-1)
sock.listen(10)
# add the parent socket in the list
socket_list.append(sock)
# keep the server alive
while True:
try:
read_ready, write_ready, in_error = select.select(socket_list, [], [], 0)
except select.error, ex:
print ex
continue
for s in read_ready:
# check if s is the parent socket
if s == sock:
# accept new connection and append to list
try:
con, addr = s.accept()
if con not in socket_list:
socket_list.append(con)
except socket.errno, ex:
print ex
else:
try:
# receive packet from connected client
packet = s.recv(recv_buffer)
if not packet:
socket_list.remove(s)
read_ready.remove(s)
for n in nick_list:
if n.client_socket == s:
nick_list.remove(n)
break
break
print packet
except socket.errno, ex:
print ex
continue
process_request(packet, s)
sock.close()
if __name__ == "__main__":
run_server()
and here is my client code:
__author__ = 'pchakraverti'
import socket
nick = ""
host = "192.168.0.167"
port = 7575
sock = ""
def welcome():
print "Welecome to SecuChat!"
print "---------------------"
def init():
nick = raw_input("Enter your chat nickname : ")
print nick
global sock
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((host, port))
except socket.errno, ex:
print ex
sock.send("set_nick|"+nick)
#sock.close()
if __name__ == "__main__":
welcome()
init()
In the client code, when I don't do the sock.close(), the server runs into an exception :
Traceback (most recent call last):
File "server.py", line 102, in <module>
run_server()
File "server.py", line 84, in run_server
packet = s.recv(recv_buffer)
socket.error: [Errno 104] Connection reset by peer
how ever, when I add that line, the problem doesn't occur.
Now I've two questions :
i) I've handled exceptions in the server.py, why is this exception not being handled and why is it crashing the code ? How can I make the server more robust and what am I missing ?
ii) What is the logic behind this crash and exception in relation to the sock.close() line in the client ?
i) Your try-except block doesn't catch any exceptions.
The first argument to except must be the type of the exception you want to catch. socket.errno is not an exception class but a module. You need to catch socket.error:
except socket.error, ex:
print ex
It "crashes" your code because any exception that isn't handled somewhere in the call stack propagates outwards until it hits an except. If there is no handler the program is terminated.
ii) When the client terminates without closing the connection, a RST packet is sent by the TCP/IP stack of your OS. This is roughly the equivalent of hanging up a phone without saying goodbye. Python converts this into an exception with the text "Connection reset by peer". It simply means that since you called read() Python assumed you expect to receive something and when the connection suddenly disconnected, Python informs you of this by raising the exception.

Non-Blocking error when adding timeout to python server

I am writing a simple TCP server in python, and am trying to input a timeout. My current code:
import socket
def connect():
HOST = '' # Symbolic name meaning the local host
PORT = 5007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
s.settimeout(5)
conn, addr = s.accept()
print 'Connected by', addr
return conn
conn = connect()
while 1:
data = conn.recv(1024)
if not data: break
print data
conn.close()
Issue is when I try to connect I get an error at data = conn.recv(1024)
error: [Errno 10035] A non-blocking socket operation could not be completed immediately
Code works without the timeout.
You can turn on blocking:
# ...
conn.setblocking(1)
return conn
# ...
Try to set the timeout on the socket and the blocking on the connection. Like this:
import socket
def connect():
HOST = '' # Symbolic name meaning the local host
PORT = 5007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
s.bind((HOST, PORT))
s.listen(1)
return s
s = connect()
while 1:
conn, addr = s.accept()
print 'Connected by', addr
conn.setblocking(1)
data = conn.recv(1024)
conn.close()
if not data: break
print data
s.close()
Ran into the same problem 30 minutes ago. Found a simple non-elegant work around...if you give the socket time to breathe by doing time.sleep(1), catching the 10035 error and doing a retry it works. I'm using 2.7.5...maybe this is a bug that got fixed. Not real sure.
Code sample...please understand this is very simplistic test code I use (only recv 1 byte at a time).So where 's' is the socket with a 10s timeout and 'numbytes' is number of bytes I need...
def getbytes(s,numbytes):
din = ''
socketerror10035count = 0
while True:
try:
r = s.recv(1).encode('hex')
din += r
if len(din)/2 == numbytes:
print 'returning',len(din)/2, 'bytes'
break
except socket.timeout as e:
din = 'socket timeout'
break
except socket.error as e:
if e[0] == 10035 and socketerror10035count < 5:
socketerror10035count = socketerror10035count +1
time.sleep(1)
else:
din = 'socket error'
break
except:
din = 'deaddead'
break
return din
For Python 3 and above, the above code which references e as a scriptable object will need to be changed to "e.errno". And, of course the print statements require parenthesis around the arguments.
Additionally, you may want to change the "except socket.error as e:" line to "except BlockingIOError as e:". However, the code works as is under Python 3.8.5 on Windows.

Categories

Resources