At what point is the following Python socket-level-programming code stuck? - python-3.x

This is the server.py file which runs a basic server:
import socket
import sys
sockett = socket.socket()
sockett.bind(('127.0.0.1', 123))
sockett.listen(10)
while True:
print('1', end='')
while True:
print('2', end='')
try:
client, addr = sockett.accept()
print(client,addr)
break
except Exception as e:
print(e)
print(client.recv(400))
print(client.recv(1024))
print('3')
print('4')
And this is the client.py code that I am running:
import socket
import sys
sockett = socket.socket()
sockett.connect(('127.0.0.1', 123))
sockett.send(b'0')
print("Hello")
The doubt I have is that when I run the server.py (let S) file and then the client.py (let C) file, S keeps on running but C stops running which should be the case but the point at which S is stuck is the main problem. It prints 3 for the first time and then does not print anything, not 4 (so not out of the loop) not 1 (so not still looping). What could the reason be? Where is the code after it has printed 3?
This is the output I am getting:
12<socket......>(...)
b'0'
b''
3
_ (keeps on running indefinitely)
According to me, it should print 1 first, then 2, then run into an error which would be handled by try-except, and then print:
b''
b''
3
and then keep on looping like this.

The server is actually looping, but the reason you don't see the 1 or 2 when you're running this script is because you're not flushing your output:
import socket
import sys
sockett = socket.socket()
sockett.bind(('127.0.0.1', 123))
sockett.listen(10)
while True:
print('1', end='')
while True:
print('2', end='', flush=True)
try:
client, addr = sockett.accept()
print(client,addr)
break
except Exception as e:
print(e)
print(client.recv(400))
print(client.recv(1024))
print('3')
print('4')
You'll notice that with flush=True, in print('2', end='', flush=True) you'll see the 12 appear prior to the client's connection, and once again after the client disconnects.
12<socket...> (...)
b'0'
b''
3
12_ (keeps on running indefinitely)
With this, you can see that it's waiting again at client, addr = sockett.accept()

while True:
print('1', end='')
while True:
print('2', end='')
try:
client, addr = sockett.accept()
print(client,addr)
break
except Exception as e:
print(e)
This part will succeed (and not run into an error as you assume) once the client has connected.
print(client.recv(400))
This will read the b'0' send by the client.
print(client.recv(1024))
print('3')
This will wait for more data. Since the client closes the connection it will return with '', i.e. no data.
Then it will go to the beginning of the loop and from there into the inner loop where it is calling accept again. accept will block until it gets a new connection. Since you don't run the client again accept will block forever.

Related

Odd behavior with threads

I'm developping a little script in PYTHON3 for pinging IPs ranges with multiples threads.
I only ping my localhost for now.
Here is my code:
#!/usr/bin/python3
import _thread
import os
# Define a function for the thread
def pingBox( threadName, value):
range='127.0.0.'
host=''+str(range)+str(value)
response = os.system("ping -c 1 "+host +"2>&1 >/dev/null") #to don't show the output
print('response for pinging %s is %s' %(threadName, response))
if response == 0:
print ('%s : is up' %host)
else:
print ('%s : is down' %host)
# Create one thread by ping
try:
for x in range (1,100):
_thread.start_new_thread( pingBox, ("Thread-"+str(x), x) )
except Exception as e: print(e)
while 1:
pass
With this code, I get some strange answer, like for instance :
response for pinging Thread-89 is 512
Why 512? I don't understand why response has this value.
PS: I know that for now, this code is a completely massacre regarding the threading aspect.
Here's a few mistakes I found:
Use threading library in python3. Read more about threading interfaces here.
The while loop at end makes no sense, please remove that.
Replacing with _thread with threading interfaces, your program will now look like:
#!/usr/bin/python3
import threading
import os
# Define a function for the thread
def pingBox( threadName, value):
range='127.0.0.'
host=''+str(range)+str(value)
response = os.system("ping -c 1 "+host +"2>&1 >/dev/null") #to don't show the output
print('response for pinging %s is %s' %(threadName, response))
if response == 0:
print ('%s : is up' %host)
else:
print ('%s : is down' %host)
# Create one thread by ping
try:
tlist = []
for x in range (1,100):
tlist.append(
threading.Thread(
target=pingBox,
kwargs={
"threadName": "Thread:{0}".format(x),
"value":x
}
))
for t in tlist:
t.start()
for t in tlist:
t.join()
except Exception as e:
print(e)

Socket server - readlines() function causes my program to stop/stuck

I'm trying a example to create a simple socket server, I need to receive multiline data from clients so this is my code for the socket server:
import socket
import sys
host = 'localhost'
port = 5006
c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
c.bind((host, port))
c.listen(1)
while True:
try:
print("1")
csock, caddr = c.accept()
print("2")
with csock.makefile('rw', 2**16) as cfile:
print("3")
print(cfile.readline()) // When I use readline, it goes ok, but only get the first line, I need every line from data sent by client
print("4")
cfile.close()
print("5")
print("5.5")
csock.sendall("OK".encode('UTF-8'))
print("6")
csock.close()
print("7")
except KeyboardInterrupt:
print("Keyboard exit")
if 'csock' in locals():
csock.close()
sys.exit()
except Exception as e:
print(e)
Now when I use readlines(), my program just stuck and "does nothing" after print("3")
I tried with read() too, but still stuck, keep waiting both client and server
This is the code I'm using for client:
import socket
def query(host, port):
msg = \
'MSH|^~\&|REC APP|REC FAC|SEND APP|SEND FAC|20110708163513||QBP^Q22^QBP_Q21|111069|D|2.5|||||ITA||EN\r' \
'QPD|IHE PDQ Query|111069|#PID.5.2^SMITH||||\r' \
'RCP|I|'
# establish the connection
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((host, port))
# send the message
sock.sendall(msg.encode('UTF-8'))
# receive the answer
received = sock.recv(1024*1024)
return received
finally:
sock.close()
if __name__ == '__main__':
res = query('localhost', 5006)
print("Received response: ")
print(repr(res))
When I use readlines() and stop client after executing, server prints full message sent, I'm confused

Python CMD2 Interrupt printing promp

I am using CMD2 to create a server. I have broken my code down to the smallest bit of code that still produces the problem.
import socket
import _thread
from cmd2 import *
def grab_data(conn):
while True:
try:
data = conn.recv(1024)
print(data)
except:
print("disconnected.")
break
def grab_client(sock):
while True:
conn, addr = sock.accept()
print("New connection")
_thread.start_new_thread(grab_data, (conn,))
def start_conn(ip, port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((ip, int(port)))
sock.listen(10)
print("Socket listening")
_thread.start_new_thread(grab_client, (sock,))
class CLI(Cmd):
def __init__(self):
Cmd.__init__(self)
self.prompt = "Prompt> "
def do_listen(self, arg):
start_conn('0.0.0.0', '4446')
def emptyline(self):
pass
def do_quit(self, arg):
return True
cli = CLI()
cli.cmdloop("Welcome to the server.")
The issue I run into is when a client connects. It does not reprint the prompt. It hangs at a empty line with just the cursor. I am not sure how to get the prompt to print back.
You're blocking trying to read 1024 bytes, so it's got to wait until that entire buffer is filled. To do proper line-based buffering is a bit tricky, but a simple (albeit non-performant) implementation is to read a character at a time and check if it's a newline:
line = ""
while True:
data = conn.recv(1)
line += data
if data in "\n\r":
break
(This is not great code, but let's see if that solves the problem and we can improve it.)

python program not exiting on exception using aiozmq

I am using aiozmq for a simple RPC program.
I have created a client and server.
When the server is running, the client runs just fine.
I have a timeout set in the client to raise an exception in the event of no server being reachable.
The client code is below. When I run it without the server running, I get an expected exception but the script doesn't actually return to the terminal. It still seems to be executing.
Could someone firstly explain how this is happening and secondly how to fix it?
import asyncio
from asyncio import TimeoutError
from aiozmq import rpc
import sys
import os
import signal
import threading
import sys
import traceback
#signal.signal(signal.SIGINT, signal.SIG_DFL)
async def client():
print("waiting for connection..")
client = await rpc.connect_rpc(
connect='tcp://127.0.0.1:5555',
timeout=1
)
print("got client")
for i in range(100):
print("{}: calling simple_add".format(i))
ret = await client.call.simple_add(1, 2)
assert 3 == ret
print("calling slow_add")
ret = await client.call.slow_add(3, 5)
assert 8 == ret
client.close()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.set_debug(True)
future = asyncio.ensure_future(client())
try:
loop.run_until_complete(future)
except TimeoutError:
print("Timeout occurred...")
future.cancel()
loop.stop()
#loop.run_forever()
main_thread = threading.currentThread()
for t in threading.enumerate():
if t is main_thread:
print("skipping main_thread...")
continue
print("Thread is alive? {}".format({True:'yes',
False:'no'}[t.is_alive()]))
print("Waiting for thread...{}".format(t.getName()))
t.join()
print(sys._current_frames())
traceback.print_stack()
for thread_id, frame in sys._current_frames().items():
name = thread_id
for thread in threading.enumerate():
if thread.ident == thread_id:
name = thread.name
traceback.print_stack(frame)
print("exiting..")
sys.exit(1)
#os._exit(1)
print("eh?")
The result of running the above is below. Note again that the program was still running, I had to to exit.
> python client.py
waiting for connection..
got client
0: calling simple_add
Timeout occurred...
skipping main_thread...
{24804: <frame object at 0x00000000027C3848>}
File "client.py", line 54, in <module>
traceback.print_stack()
File "client.py", line 60, in <module>
traceback.print_stack(frame)
exiting..
^C
I also tried sys.exit() which also didn't work:
try:
loop.run_until_complete(future)
except:
print("exiting..")
sys.exit(1)
I can get the program to die, but only if I use os._exit(1). sys.exit() doesn't seem to cut it. I doesn't appear that there are any other threads preventing the interpreter from dying. (Unless I'm mistaken?) What else could be stopping the program from exiting?

Python 3.4 Socket and Threading issues

import sys
import socket
import threading
import time
QUIT = False
class ClientThread(threading.Thread): # Class that implements the client threads in this server
def __init__(self, client_sock): # Initialize the object, save the socket that this thread will use.
threading.Thread.__init__(self)
self.client = client_sock
def run(self): # Thread's main loop. Once this function returns, the thread is finished and dies.
global QUIT # Need to declare QUIT as global, since the method can change it/
done = False
cmd = self.readline() #Read data from the socket and process it
while not done:
if 'quit' == cmd:
self.writeline('Ok, bye')
QUIT = True
done = True
elif 'bye' == cmd:
self.writeline('Ok, bye')
done = True
else:
self.writeline(self.name)
cmd = self.readline()
self.client.close() # Make sure socket is closed when we're done with it
return
def readline(self): # Helper function, read up to 1024 chars from the socket, and returns them as a string
result = self.client.recv(1024)
if None != result: # All letters in lower case and without and end of line markers
result = result.strip().lower()
return result
def writeline(self, text): # Helper function, writes the given string to the socket with and end of line marker at end
self.client.send(text.strip() + '\n')
class Server: # Server class. Opens up a socket and listens for incoming connections.
def __init__(self): # Every time a new connection arrives, new thread object is created and
self.sock = None # defers the processing of the connection to it
self.thread_list = []
def run(self): # Server main loop: Creates the server (incoming) socket, listens > creates thread to handle it
all_good = False
try_count = 0 # Attempt to open the socket
while not all_good:
if 3 < try_count: # Tried more than 3 times without success, maybe post is in use by another program
sys.exit(1)
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create the socket
port = 80
self.sock.bind(('127.0.0.1', port)) # Bind to the interface and port we want to listen on
self.sock.listen(5)
all_good = True
break
except socket.error, err:
print('Socket connection error... Waiting 10 seconds to retry.')
del self.sock
time.sleep(10)
try_count += 1
print( 'Server is listening for incoming connections.')
print('Try to connect through the command line with:')
print('telnet localhost 80')
print('and then type whatever you want.')
print()
print("typing 'bye' finishes the thread. but not the server",)
print("eg. you can quit telnet, run it again and get a different ",)
print("thread name")
print("typing 'quit' finishes the server")
try:
while not QUIT:
try:
self.sock.settimeout(0.500)
client = self.sock.accept()[0]
except socket.timeout:
time.sleep(1)
if QUIT:
print('Received quit command. Shutting down...')
break
continue
new_thread = ClientThread(client)
print('Incoming Connection. Started thread ',)
print(new_thread.getName())
self.thread_list.append(new_thread)
new_thread.start()
for thread in self.thread_list:
if not thread.isAlive():
self.thread_list.remove(thread)
thread.join()
except KeyboardInterrupt:
print('Ctrl+C pressed... Shutting Down')
except Exception as err:
print('Exception caught: %s\nClosing...' % err)
for thread in self.thread_list:
thread.join(1.0)
self.sock.close()
if "__main__" == __name__:
server = Server()
server.run()
print('Terminated')
Resolved many issues, these are the ones left, thank you guys!
1st error: socket.error, err.This specifically tells me that this no longer works in Python 3.4, but does not offer an alternative.
2nd Error: except socket.error, err: Python 3.4 does not support this syntax
3rd Error: self.readline(), I also have to assume writeline does not work also.
In this case, self.readline() is totally not working, I get an error that says AttributeError: 'ClientThread' object has no attribute 'readline'
This only happens after the thread is created. Console shows:
Incoming connection. Started thread.
Thread-1
Then flags that error.
4th Error: Cannot get 2to3 to run? Terminal says not recognised as internal command, and python console gives a big FU.
Can I get any rectification suggestions for the following errors please?
There are multiple issues that prevent your code from woring on python3
you're using python2 print statements, so your code can't possibly run on python3 where print() is a function.
the recv and send methods require/return bytes in python3, not str
the syntax for catching errors is except ExceptionClass as name
The first step in porting Python 2 code to Python 3 is to run it though the 2to3 program that comes with Python.
If you run your code through 2to3 with the -w option, it will fix a lot of your problems automagically.
> 2to3 -w --no-diffs socktest1.py
If you want to see what would be changed, but not change anything;
> 2to3 socktest1.py |less

Resources