can't close socket on KeyboardInterrupt - python

from socket import socket, AF_INET, SOCK_STREAM
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.listen(1)
while True:
try:
connection, address = sock.accept()
print("connected from " + address)
received_message = sock.recv(300)
if not received_message:
break
connection.sendall(b"hello")
except KeyBoardInterrupt:
connection.close()
so Im trying to wrap my head around sockets and have this pretty simple script
but for some reason I can't kill this script with a KeyboardInterrupt
how do I do kill the script with a KeyboardInterrupt that and why can't I kill it with a KeyboardInterrupt?

To break to get out the while loop. Without break, the loop will not end.
To be safe, check whether connection is set.
from socket import socket, AF_INET, SOCK_STREAM
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.listen(1)
while True:
connection = None # <---
try:
connection, address = sock.accept()
print("connected from ", address)
received_message = connection.recv(300)
if not received_message:
break
connection.sendall(b"hello")
except KeyboardInterrupt:
if connection: # <---
connection.close()
break # <---
UPDATE
There was a typo: KeyBoardInterrupt should be KeyboardInterrupt.
sock.recv should be connection.recv.

Try to use timeout to make the program periodically "jumps out" from the accept waiting process to receive KeyboardInterrupt command.
Here is an example of socket server:
import socket
host = "127.0.0.1"
port = 23333
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host,port))
sock.listen()
sock.settimeout(0.5)
print("> Listening {}:{} ...".format(host,port))
try:
while True:
try:
conn, addr = sock.accept()
data = conn.recv(1024)
if not data:
print("x Client disconnected!")
# break
else:
print("> Message from client: {}".format(data.decode()))
msg = "> Message from server".format(data.decode()).encode()
conn.sendall(msg)
except socket.timeout:
# print("Timeout")
pass
except KeyboardInterrupt:
pass
except KeyboardInterrupt:
print("Server closed with KeyboardInterrupt!")
sock.close()

Try adding a timeout to the socket, like so:
from socket import socket, AF_INET, SOCK_STREAM
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.settimeout(1.0)
sock.listen(1)
while True:
try:
connection, address = sock.accept()
print("connected from " + address)
received_message = sock.recv(300)
if not received_message:
break
connection.sendall(b"hello")
except IOError as msg:
print(msg)
continue
except KeyboardInterrupt:
try:
if connection:
connection.close()
except: pass
break
sock.shutdown
sock.close()

I had this issue on Windows. Here's how I handle stopping the process:
try:
while self.running:
try:
c, addr = self.socket.accept()
print("Connection accepted from " + repr(addr[1]))
# do special stuff here...
print("sending...")
continue
except (SystemExit, KeyboardInterrupt):
print("Exiting....")
service.stop_service()
break
except Exception as ex:
print("======> Fatal Error....\n" + str(ex))
print(traceback.format_exc())
self.running = False
service.stop_service()
raise
except (SystemExit, KeyboardInterrupt):
print("Force Exiting....")
service.stop_service()
raise
def stop_service(self):
"""
properly kills the process: https://stackoverflow.com/a/16736227/4225229
"""
self.running = False
socket.socket(socket.AF_INET,
socket.SOCK_STREAM).connect((self.hostname, self.port))
self.socket.close()
Note that in order to trigger a KeyboardInterrupt exception, use:
Ctrl+Fn+PageUp(Pause/Break)

The CTRL+C event can be caught in a separate process and sent back to another thread running in the main process to kill the socket. Example below, tested successfully on Windows 10 with Python 3.5.4. Placed some comments and print statements around so you can see what's happening.
from multiprocessing import Pipe, Process
from socket import socket, AF_INET, SOCK_STREAM
from threading import Thread
import time
def detect_interrupt(conn):
try:
print("Listening for KeyboardInterrupt...")
while True:
time.sleep(1)
except KeyboardInterrupt:
print("Detected KeyboardInterrupt!")
print("Sending IPC...")
conn.send(True)
conn.close()
def listen_for_interrupt(conn, sock):
print("Listening for IPC...")
conn.recv()
print("Detected IPC!")
print("Closing sock...")
sock.close()
if __name__ == "__main__":
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.listen(1)
# Crate a Pipe for interprocess communication
main_conn, detect_conn = Pipe()
# Create a thread in main process to listen on connection
listen_for_interrupt_thread = Thread(
target=listen_for_interrupt, args=(main_conn, sock), daemon=True)
listen_for_interrupt_thread.start()
# Create a separate process to detect the KeyboardInterrupt
detect_interrupt_process = Process(
target=detect_interrupt, args=(detect_conn,))
detect_interrupt_process.start()
connection = None
try:
while True:
print("Running socket accept()")
connection, address = sock.accept()
print("connected from " + address)
received_message = sock.recv(300)
if not received_message:
break
connection.sendall(b"hello")
except KeyboardInterrupt:
print("Handling KeyboardInterrupt")
sock.close()
if connection:
connection.close()

For windows users,
Above solutions which try to catch KeyBoard interrupts don't seem to work. I ended up setting a timeout on my socket.
Something like:
server_socket.settimeout(10)
Here an exception is raised after 10 seconds of inactivity (like not receiving anything for 10 secs)

If the far-end sends data rarely, you should set timeout for the connection as well.
In this case the connection will raise timeout Exception, when the KeyboardInterrupt can be checked.
from socket import socket, AF_INET, SOCK_STREAM
sock = socket(AF_INET, SOCK_STREAM)
sock.bind(("localhost", 7777))
sock.settimeout(1.0)
sock.listen(1)
while True:
try:
connection, address = sock.accept()
connection.settimeout(1.0)
print("connected from " + address)
received_message = sock.recv(300)
if not received_message:
break
connection.sendall(b"hello")
except socket.timeout:
continue
except IOError as msg:
print(msg)
continue
except KeyboardInterrupt:
try:
if connection:
connection.close()
except: pass
break
sock.shutdown
sock.close()

Related

Client not responding - multi thread in Python

I am trying to make 2 threads. One will always be listening and second one will check if the server is listening or not.
Host='127.0.0.1'
Port= 5555
threads=[]
threads2=[]
def server() :
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((Host, Port))
while 1:
print("listen() ")
s.listen()
conn, address= s. accept()
with conn:
print(" Connected by", address)
while True:
data=conn.recv(1024)
print("from caller", representing(data))
def client () :
s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind(('127.0.0.1', 5555))
except socket.error as e:
if e.errno==errno.EADDRINUSE:
print("port in use")
else:
print("connected")
s.close()
served = threading.Thread(target=server)
threads.append(served)
served.start()
print("started the server thread")
time.sleep(2)
click =threading.Thread(target=client)
threads2.append(click)
click.start()
print("click started")
I am getting the below output
started the server thread
listen()
click started
And after this it doesnt show anything.
You're trying to bind the socket in both the server and the client. You can only bind once. (See the Python documentation on this.
Instead, for the client, you should use connect:
def client () :
s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# use s.connect instead of s.bind
s.connect(('127.0.0.1', 5555))
except socket.error as e:
if e.errno==errno.EADDRINUSE:
print("port in use")
else:
print("connected")
s.close()

Accepting output of the socket generated by Python in MQL5

I have created a socket file something like the following and want that the output of the socket must be read by the MQL5. See the following Python code:
daemon.py
import socket
#import arcpy
def actual_work():
#val = arcpy.GetCellValue_management("D:\dem-merged\lidar_wsg84", "-95.090174910630012 29.973962146120652", "")
#return str(val)
return 'dummy_reply'
def main():
sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
try:
sock.bind( ('127.0.0.1', 6666) )
while True:
data, addr = sock.recvfrom( 4096 )
reply = actual_work()
sock.sendto(reply, addr)
except KeyboardInterrupt:
pass
finally:
sock.close()
if __name__ == '__main__':
main()
client.py
import socket
import sys
def main():
sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
sock.settimeout(1)
try:
sock.sendto('', ('127.0.0.1', 6666))
reply, _ = sock.recvfrom(4096)
print reply
except socket.timeout:
sys.exit(1)
finally:
sock.close()
if __name__ == '__main__':
main()
Kindly, help me in accepting the output of the socket through MQL5
EDITED
I just want that the reply should be accepted on the MQL5 in a variable, which produced by the daemon.py. How I can do that? Say I want that MQL5 should print the response from the Python , as in the above example, I want that MQL5 should give output as dummy_reply in string variable if possible.
Is there any possibility with ZeroMQ?
I want to get the client.py to be done with MQL5 instead of using Python. Please help me.
Please find a running example. Important element is to create byte object of the payload instead of string before you send as reply. socket object produces and ingests only bytes
import socket
import threading
import sys
def actual_work(data):
print(data)
return b'ACK'
def daemon():
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('127.0.0.1', 6666))
print("Listening on udp %s:%i" % ('127.0.0.1', 6666))
try:
while True:
data, addr = sock.recvfrom(4096)
ack = actual_work(data)
sock.sendto(ack, addr)
except Exception as e:
print(e)
finally:
sock.close()
def client():
sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
sock.settimeout(1)
try:
sock.sendto(b'payload', ('127.0.0.1', 6666))
reply, _ = sock.recvfrom(4096)
print(reply)
except socket.timeout as e:
print(e)
sys.exit(1)
finally:
sock.close()
if __name__ == '__main__':
thread = threading.Thread(target=daemon)
thread.start()
client()
client()
client()
client()
#Issue kill thread here
thread.join()

an empty file after sending it to tcp server in python

I am new to python and i am trying to make a multithreded tcp server and client to be able to send files between them. I did write some simple codes for these two programs but every time I get empty file on server's site. The file does create in the folder but when I open it it is blank inside. I also tried to send .png files but windows photoviewer doesn't open them saying they are empty. I didn't find anyone encourting such problem so that's why i am asking
Client.py
import socket # Import socket module
HOST = "localhost" # Host address / name
PORT = 2137 # Reserves port for the service
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((HOST, PORT))
fileToSend = open('test.txt', 'rb')
print "File ready to be sent"
l = fileToSend.read(1024)
while l:
print "Sending the file"
client.send(l)
l = fileToSend.read(1024)
fileToSend.close() print "done"
client.close()
Server.py
import socket
from threading import Thread
from SocketServer import ThreadingMixIn
import sys
TCPHOST = "localhost"
TCPPORT = 2137
BUFFER_SIZE = 20
class ClientThread(Thread):
def __init__(self, HOST, PORT):
Thread.__init__(self)
self.HOST = HOST
self.PORT = PORT
print "New thread started for " + HOST + " on port " + str(PORT)
def run(self):
f = open('received.py', 'wb')
while True:
try:
data = conn.recv(1024)
except socket.error, e:
print "Error receiving data: %s" % e
sys.exit(1)
while data:
print "Receiving"
f.write(data)
data = conn.recv(1024)
f.close()
try:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((TCPHOST, TCPPORT))
print "Socket created"
except socket.error, err:
print "Failed to create socket" % err
threads = []
while True:
server.listen(4)
print "Waiting for connections"
(conn, (HOST, PORT)) = server.accept()
thread = ClientThread(HOST, PORT)
thread.start()
threads.append(thread)
for t in threads:
t.join()
I am not sure what you actually want to do, because I see that you import SocketServer however you are not using it all.
If you are trying to run a simple socket server then the class ClientThread and all the other stuff about threads in that file are not necessary.
The following code in server.py will do the job
import socket
import sys
TCPHOST = "localhost"
TCPPORT = 2137
BUFFER_SIZE = 20
try:
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((TCPHOST, TCPPORT))
server.listen(4)
print "Socket created"
except socket.error, err:
print "Failed to create socket" % err
while True:
print "Waiting for connections"
(conn, (TCPHOST, TCPPORT)) = server.accept()
try:
while True:
data = conn.recv(1024)
f = open('received.py', 'wb')
if data:
print "Receiving " + data
f.write(data)
else:
f.close()
break;
except socket.error, e:
#pass
print "Error receiving data: %s" % e
#sys.exit(1)
finally:
conn.close()
However if you are trying to implement a threaded TCPServer using the ThreadingMixIn then you need to create a class that subclasses SocketServer and override its handle() function
Python documentation is quite helpful on this
https://docs.python.org/3.5/library/socketserver.html
(ThreadingMixin is at the bottom of the page)

Python socket: Bad File Descriptor for simple client connection script

My script is very simple.
1.) Server listens for an HTTP connection
2.) Client establishes connection
3.) Server prints our the client's HTTP request data
When a client connects to the server and makes a browser request it triggers the Socket error "Bad File Descriptor".
I'm not sure why it does this. Can anyone help me out?
import socket
host = ''
port = 1000
def proxy(connection,client):
request = connection.recv(MAX_DATA_RECV)
print request
connection.close()
def main():
try:
# create a socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# associate the socket to host and port
s.bind((host, port))
# listenning
s.listen(BACKLOG)
print("Listening for connections")
except socket.error, (value, message):
if s:
s.close()
print "Could not open socket:", message
# get the connection from client
while 1:
try:
conn, client_addr = s.accept()
print("Received connection from " + str(client_addr))
proxy(conn,client_addr)
#thread.start_new_thread(proxy, (conn,client_addr))
if s:
s.close()
except socket.error, (value,message):
print value
print message
sys.exit(1)
main()
You are closing the server socket after first client. Don't do this.
while True:
try:
conn, client_addr = s.accept()
print("Received connection from " + str(client_addr))
proxy(conn,client_addr)
except socket.error, (value,message):
print value
print message

How to close a connection of a client when multiple clients are connected?

I am having a multi-client server which listens to multiple clients. Now if to one server 5 clients are connected and I want to close the connection between the server and just one client then how am I going to do that.
My server code is:
import socket
import sys
from thread import *
try:
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
except socket.error,msg:
print "Socket Creation Error"
sys.exit();
print 'Socket Created'
host = ''
port = 65532
try:
s.bind((host, port))
except socket.error,msg:
print "Bind Failed";
sys.exit()
print "Socket bind complete"
s.listen(10)
print "Socket now listening"
def clientthread(conn):
i=0
while True:
data = conn.recv(1024)
reply = 'OK...' + data
conn.send(reply)
print data
while True:
conn, addr = s.accept()
start_new_thread(clientthread,(conn,))
conn.close()
s.close()

Categories

Resources