When i run my server, when server is listening, there is no way to stop the server rather than closing the terminal. I tried to handle ctrl+c using KeyboardInterrupt, but it doesnt work. I can terminate the script using ctrl+break but i dont know how to handle it in my code.
Here is the code for my server:
import socket
try:
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listener.bind(('127.0.0.1', 4444))
listener.listen(0)
print('Listening...')
listener.accept()
print('Got a connection.')
except KeyboardInterrupt:
print('Exiting...')
exit()
How can i handle ctrl+break in my code?
If no client is waiting, socket.accept() hangs until a connection is made and can't be interrupted by CTRL-C or CTRL-BREAK. Use select.select() to wait for a connection to be readable from the server socket along with a timeout. The timeout will allow CTRL-C and CTRL-BREAK to be recognized.
CTRL-C raises KeyboardInterrupt, but CTRL-BREAK needs a signal handler. I've set up a custom exception to be raised on the SIGBREAK signal below:
import signal
import socket
import select
# Custom exception with same base class as KeyboardInterrupt
class CtrlBreakInterrupt(BaseException):
pass
def handler(*args):
raise CtrlBreakInterrupt
signal.signal(signal.SIGBREAK, handler)
# Set up server
with socket.socket() as sock:
sock.bind(('', 5000))
sock.listen()
# Loop, accepting one connection at a time.
while True:
try:
# Check server has a connection with timeout
readable, _, _ = select.select([sock], [], [], 1.0)
if sock in readable:
with sock.accept() as (client, address):
while True:
data = client.recv(4096)
if not data: break
print(data)
except CtrlBreakInterrupt:
print('CTRL-BREAK')
break
except KeyboardInterrupt:
print('CTRL-C')
break
something like this .
def handler(signum, frame):
print 'Shutting down...'
sys.exit(1)
signal.signal(signal.SIGTERM, handler)
while True:
clientsocket, address = listener.accept()
clientsocket.send(bytes("hi.","utf-8"))
Related
In CPython environment, One thread does not acquire GIL from another thread, unless it is blocked(say using sleep()) or on IO
In below server code,
# server.py
import socket
import sys
from threading import Thread
def echoHandler(conn, addr):
try:
while True:
data = conn.recv(16) # Blocking call
if data:
print(data.decode('utf-8'))
conn.sendall(data)
else:
break
finally:
print('Closing the connection from server')
conn.close()
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 10006)
sock.bind(server_address)
sock.listen(1)
while True:
conn, addr = sock.accept()
t = Thread(target=echoHandler, args=(conn, addr))
t.daemon = True
t. start()
print('Waiting for another conn')
#client.py
import socket
import pdb
# pdb.set_trace()
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 10006)
print('connecting to', server_address)
sock.connect(server_address)
while True:
try:
message = input().encode('utf-8')
except EOFError: #EAFP
print('Breaking ')
break
sock.sendall(message)
data = sock.recv(16) # Blocking call
print(data.decode('utf-8'))
print('close the socket')
sock.close()
Question:
When does one thread get the chance to acquire GIL from another thread to serve client? Is conn.recv(16), allowing server to behave multi threaded?
Yes, the GIL is not held during conn.recv(16) (which is, after all, network I/O).
It's also periodically released (pre-2010, every 100 opcodes; more recently, on a configurable 5ms interval) to avoid thread starvation.
Problem with socket server while loop and waiting serial command in python.
I have server code in python like this:
import serial
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 9000))
sock.listen(1)
print "Listening on TCP 9000"
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
print "Connected at: /dev/ttyUSB0"
while(1):
print "Waiting For Connection..."
connection, addr = sock.accept() #PROBLEM HERE
# IF THERE IS NOT CLIENT, PROGRAM CAN NOTO CONTINUE TO NEXT LINE
print "Connected"
#SO I CAN NOT CHECK THE COMMAND FROM SERIAL IN THE SAME TIME
dataFromSerial = ser.readline()
if dataFromSerial == "ON":
#SET LED ON
Help me please...
Thanks...
Set the listening socket nonblocking and catch socket timeouts (which apparently can also manifest themselves as EAGAIN or EWOULDBLOCK errors):
import errno
sock.setblocking(False) # just once, probably right after listen()
try:
conn, addr = sock.accept()
# conn accepted
except socket.error as e:
if e.errno not in (errno.EAGAIN, errno.EWOULDBLOCK):
raise # some sort of error we don't recognize; re-raise
pass # no connections were pending
I'm writing a simple TCP socket server with pyBonjour support. To do this I figured using threading. The problem is how I get the server to stop... I figured the following should work (according to this) but it isn't
Is there a nicer way to do this (that works)..
import SocketServer
import threading
import pybonjour
import select
import time
class BonjourThread(threading.Thread):
def run(self):
sdRef = pybonjour.DNSServiceRegister(name = 'MacroServer - Mac',
regtype = '_macroserver._tcp',
port = 12000,
callBack = self.bonjour_register_callback)
while True:
ready = select.select([sdRef], [], [])
if sdRef in ready[0]:
pybonjour.DNSServiceProcessResult(sdRef)
def bonjour_register_callback(self, sdRef, flags, errorCode, name, regtype, domain):
if errorCode == pybonjour.kDNSServiceErr_NoError:
print 'Bonjour started'
class TCPThread(threading.Thread):
def run(self):
try:
HOST, PORT = "localhost", 12000
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
print 'TCP server started'
server.serve_forever()
except KeyboardInterrupt:
print 'Closing Down'
exit()
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
try:
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print "{} wrote:".format(self.client_address[0])
print self.data
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
except KeyboardInterrupt:
print 'Closing Down'
exit()
if __name__ == "__main__":
try:
thread1 = TCPThread()
thread1.start()
thread2 = BonjourThread()
thread2.start()
while True: time.sleep(100)
except (KeyboardInterrupt, SystemExit):
print 'Received keyboard interrupt, quitting threads.\n'
finally:
print 'And its bye from me'
In python, only the main thread gets the KeyboardInterrupt signal. How you want to handle termination of your socket servers and their various clients can get complex. I've made logging servers where I kept the sockets in a master list, protected by a lock, and closed them all then waited for termination in the keyboard interrupt. You could even mark the threads as daemons and just exit - let the operating system clean up the sockets.
from place you linked to:
thread.daemon=True causes the thread to terminate when the main process ends.
which you missed in your code, so that's why they don't stop
as to nicer ways to do it, you could create your own signal handler and terminate your threads but not sure if it's any nicer than:
thread.daemon=True
I have a problem trying to learn about sockets for network communication. I have made a simple thread that listens for connections and creates processes for connecting clients, my problem though is that I can't get the thread to join properly as I haven't found a way to cancel the socket.accept()-call when I want to quit the program.
My code looks like this;
class ServerThread( threading.Thread ):
def __init__(self, queue, host, port):
threading.Thread.__init__(self)
self.queue = queue
self.running = True
self.hostname = host
self.port = port
def run(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((self.hostname, self.port))
self.socket.listen(1)
while self.running:
try:
conn, address = self.socket.accept()
process = Process(target=server_slave, args=(conn, address, self.queue))
process.daemon = True
process.start()
except socket.timeout:
pass
def stop(self):
self.running = False
self.socket.close()
I have managed to get the program to close by setting self.setDaemon(True) and just exiting the main program, handing everything to the great garbage collector - but that seems like a bad solution. I've also tried setting a timeout for the socket but that results in getting [Errno 35] Resource temporarily unavailable (regardless of the actual timeout, even when I set it to years...).
What am I doing wrong? Have I designed the thread in a dumb way or have I missed something about accepting connections?
One way to get the thread to close seems to be to make a connection to the socket, thus continuing the thread to completion.
def stop(self):
self.running = False
socket.socket(socket.AF_INET,
socket.SOCK_STREAM).connect( (self.hostname, self.port))
self.socket.close()
This works, but it still feels like it might not be optimal...
In most cases you will open a new thread or process once a connection is accepted. To close the connection, break the while loop. Garbage collection will remove the thread or process but join will ensure none get left behind.
Persistent sockets close when the user closes them or they timeout. Non-persistent, like static webpages will close after they've sent the information.
Here's a good example of a persistent socket server in Python. It uses multiprocessing which means it can run across multiple cores for CPU-bound tasks. More commonly known as multithreading.
import socket
import multiprocessing
def run():
host = '000.000.000.000'
port = 1212
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', port))
sock.listen(3)
while True:
p = multiprocessing.Process(target=worker, args=sock.accept()).start()
def worker(conn, addr):
while True:
if data == '':
#remote connection closed
break
if len(dataList) > 2:
# do stuff
print 'This code is untested'
run()
A dirty solution which allows to exit your program is to use os._exit(0).
def stop(self):
self.socket.close()
os._exit(0)
note that sys.exit doesn't work/blocks as it tries to exit cleanly/release resources. But os._exit is the most low level way and it works, when nothing else does.
The operating system itself will release the resources (on any modern system) like when doing exit in a C program.
The best way to do this is to have a single listening thread that has nothing to do with your connection threads and give it a reasonable length timeout. On timeout, check if this thread should shutdown and if not, loop again and go back to listening.
def tcp_listen_handle(self, port=23, connects=5, timeout=2):
"""This is running in its own thread."""
sock = socket.socket()
sock.settimeout(timeout)
sock.bind(('', port))
sock.listen(connects) # We accept more than one connection.
while self.keep_running_the_listening_thread():
connection = None
addr = None
try:
connection, addr = sock.accept()
print("Socket Connected: %s" % str(addr))
# makes a thread deals with that stuff. We only do listening.
self.handle_tcp_connection_in_another_thread(connection, addr)
except socket.timeout:
pass
except OSError:
# Some other error.
print("Socket was killed: %s" % str(addr))
if connection is not None:
connection.close()
sock.close()
The only thing this does is listen, timeout, checks if it should die during the timeout, and goes back to listening. The general rule of thumb is that threads should check whether they should die and try to do that themselves as fast as they can. And if you don't want to take the 2 second hit for timeout wait before the thread unblocks and checks. You can connect to it yourself.
Partially tested solution
Put self.socket.settimeout(0.1) right before while
Put conn.settimeout(None) right after accept
I am struggling to get my python socket to behave.
There are two major problems:
1) When it listens for the client connection the program stalls which is a problem because it is running on a IRC client python interpreter causing the IRC client not to respond until the client connects.
2) When the client disconnects the entire script has to be stopped and then restarted again inorder to get the socket server to listen once more.
I thought the way around it might be to start the socket listening in a separate thread, so the IRC client can continue while it waits for the client connection. Also, once the client has decided to close the connection I need a way restart it.
The following code is terrible and doesn't work but it might give you an idea as to what I'm attempting:
__module_name__ = "Forward Module"
__module_version__ = "1.0.0"
__module_description__ = "Forward To Flash Module by Xcom"
# Echo client program
import socket
import sys
import xchat
import thread
import time
HOST = None # Symbolic name meaning all available interfaces
PORT = 7001 # Arbitrary non-privileged port
s = None
socketIsOpen = False
def openSocket():
# start server
print "starting to listen"
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC,
socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
af, socktype, proto, canonname, sa = res
try:
s = socket.socket(af, socktype, proto)
except socket.error as msg:
s = None
continue
try:
s.bind(sa)
s.listen(1)
except socket.error as msg:
s.close()
s = None
continue
break
if s is None:
print 'could not open socket'
global socketIsOpen = False
sys.exit(1)
conn, addr = s.accept()
print 'Connected by', addr
global socketIsOpen = True
def someone_said(word, word_eol, userdata):
username = str(word[0])
message = str(word[1])
sendMessage = username + " : " + message
send_to_server(sendMessage)
def send_to_server(message):
conn.send(message)
def close_connection():
conn.close()
print "connection closed"
xchat.hook_print('Channel Message' , someone_said)
def threadMethod(arg) :
while 1:
if (not socketIsOpen) :
openSocket()
try:
thread.start_new_thread(threadMethod, args = [])
except:
print "Error: unable to start thread"
The python is running on an IRC client called HexChat which is where the xchat import comes from.
The way you usually program a threaded socket server is:
call accept() in a loop
spawn a new thread to handle the new connection
A very minimal example would be somethig like this:
import socket
import threading
import time
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', 9999))
server.listen(1)
def handle(conn):
conn.send(b'hello')
time.sleep(1) # do some "heavy" work
conn.close()
while True:
print('listening...')
conn, addr = server.accept()
print('handling connection from %s' % (addr,))
threading.Thread(target=handle, args=(conn,)).start()
You're spawning new threads in which you create your listening socket, then accept and handle your connection. And while socketIsOpen is True your programm will be using a lot of cpu looping through your while loop doing nothing. (btw, the way you check socketIsOpen allows for race conditions, you can start multiple threads before it is set.)
And one last thing, you should try to use the threading module instead of the deprecated thread.