Python UDP program multiple connections with select - python

I'm making a UDP program that connects multiple clients/neighbors. There is no server everyone is using the same program. I'm trying to test it with localhost so consider all IPs and ports of neighbors work as intended. Using 127.0.0.1 as IP on all and connecting to different ports.
So my question is why do I receive the startup data that I send before the while loop but I cannot send any? Seems that I am doing something wrong with sys.stdin.
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((HOST, PORT))
going = True
input = [s]
while going:
i,o,e = select.select(input,[],[],)
try :
for x in i:
if x == sys.stdin:
data = sys.stdin.read()
for i in neighbors:
addr = (i[1][0], int(i[1][1]))
s.sendto(data, addr)
else:
msg, addr = s.recvfrom(100)
print msg
except socket.error, msg:
print 'Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
s.close()

input is always [s], so i is always going to be [s], so x == sys.stdin is never going to be True (because x is always s), so only the else clause will ever execute.
Maybe you meant input = [s, sys.stdin]?

Related

Black Hat Python proxy tool no data

I recently bought the book Black Hat Python, 2nd Edition, by Justin Seitz, which seems to be a very good book about networking and all that (i am writing my code on Kali Linux)
I have a problem on the TCP Proxy Tool on chapter 2 :
Here is the code :
import sys
import socket
import threading
HEX_FILTER = ''.join(
[(len(repr(chr(i))) == 3) and chr(i) or '.' for i in range(256)])
def hexdump(src, length = 16, show = True):
# basically translates hexadecimal characters to readable ones
if isinstance(src, bytes):
src = src.decode()
results = list()
for i in range(0, len(src), length):
word = str(src[i:i+length])
printable = word.translate(HEX_FILTER)
hexa = ' '.join(['{ord(c):02X}' for c in word])
hexwidth = length*3
results.append('{i:04x} {hexa:<{hexwidth}} {printable}')
if show :
for line in results :
print(line)
else :
return results
def receive_from(connection):
buffer = b""
connection.settimeout(10)
try :
while True :
data = connection.recvfrom(4096)
if not data :
break
buffer += data
except Exception as e:
pass
return buffer
def request_handler(buffer):
# perform packet modifications
return buffer
def response_handler(buffer):
# perform packet modifications
return buffer
def proxy_handler(client_socket, remote_host, remote_port, receive_first):
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
if receive_first :
# Check for any data to receive before
going into the main loop (i guess)
remote_buffer = receive_from(remote_socket)
hexdump(remote_buffer)
remote_buffer = response_handler(remote_buffer)
if len(remote_buffer):
print("[<==] Sending %d bytes to localhost." % len(remote_buffer))
client_socket.send(remote_buffer)
while True : # Start the loop
local_buffer = receive_from(client_socket)
if len(local_buffer):
line = "[==>] Received %d bytes from localhost." % len(local_buffer)
print(line)
hexdump(local_buffer)
local_buffer = request_handler(local_buffer)
remote_socket.send(local_buffer)
print("[==>] Sent to remote.")
remote_buffer = receive_from(remote_socket)
if len(remote_buffer):
print("[==>] Received %d bytes from remote." % len(remote_buffer))
hexdump(remote_buffer)
remote_buffer=response_handler(remote_buffer)
client_socket.send(remote_buffer)
print("[<==] Sent to localhost.")
if not len(local_buffer) or not len(remote_buffer):
# If no data is passed, close the sockets and breaks the loop
client_socket.close()
remote_socket.close()
print("[*] No more data. Closing connections. See you later !")
break
def server_loop(local_host, local_port, remote_host, remote_port, receive_first):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try :
server.bind((local_host, local_port)) # Bind the local host and the local port
except Exception as e:
print('Problem on bind : %r' %e)
# If an error occurs, prints a
print("[!] Failed to listen on %s:%d" % (local_host, local_port))
print("[!] Check for other listening sockets or correct permissions.")
sys.exit(0)
print("[*] Listening on %s:%d" % (local_host, local_port))
server.listen(5)
while True :
client_socket, addr = server.accept()
# print out the local connection information
line = "> Received incoming connection from %s:%d" % (addr[0], addr[1])
print(line)
# start a thread to talk to the remote host
proxy_thread = threading.Thread(
target = proxy_handler,
args=(client_socket,remote_host,
remote_port, receive_first))
proxy_thread.start()
def main():
if len(sys.argv[1:]) != 5:
print("Usage: ./proxy.py [localhost] [localport]")
print("[remotehost] [remoteport] [receive_first]")
print("Example : ./proxy.py 127.0.0.1 9000 192.168.56.1 9000 True")
sys.exit(0)
loca l_host = sys.argv[1]
local_port = int(sys.argv[2])
remote_host = sys.argv[3]
remote_port = int(sys.argv[4])
receive_first = sys.argv[5]
if "True" in receive_first:
receive_first = True
else :
receive_first = False
server_loop(local_host, local_port,
remote_host, remote_port, receive_first)
if __name__ == '__main__':
main()
(sorry, i had a bit of a trouble formatting it and it's quite long)
Now, normally, i just need to open 2 terminals and run the code with the command line :
sudo python proxy.py 127.0.0.1 21 ftp.dlptest.com 21 True
in one terminal, and :
ftp 127.0.0.1 21
in the other one.
My code seems to be working fine, except that... I receive no data. I tried different ftp servers (notice that i don't use the one quoted in the book), but it still doesn't work. It just says :
[*] Listening on 127.0.0.1
> Received incoming connection from 127.0.0.1:55856
but it doesn't actually displays anything until the connexion times out or that i stop the command with Ctrl + C.
I know this question has already been asked, but they don't resolve my problem.
Please tell me if i forgot a line of code (for example the one that prints the data on the screen lol) or did anything wrong :)
one the hexa variable you need to put and f'{ord(c):02x}' because you just have a string and not using the 'c' variable from the list comprehension. That's a small typo you missed fix that and try the whole process again.
hexa = ' '.join([f'{ord(c):02X}' for c in word])
The f should be here ^

How can I receive more than one character at a time from telnet server?

I open up CMD and create a telnet connection with:
telnet localhost 5555
And the connection will open with the server printing "Welcome" as you can see in the image below
However, when I type on the telnet window it sends the reply one character at a time rather than in full sentences (e.g. I go to type hello and it sends hello world one character at a time), like this:
serveroutput: h serveroutput: e serveroutput: l serveroutput: l serveroutput: o
I want it to send the full word hello or a full sentence rather than sending one character at a time.
How can I do this?
Here's the code:
import socket
import sys
from _thread import *
host = ''
port = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((host, port))
except socket.error as e:
print(str(e))
s.listen(1)
def threaded_client(conn):
conn.send(str.encode('Welcome, type your info\n'))
while True:
print("Waiting for input")
data = conn.recv(1024)
print("Data: ", data)
reply = 'Server output: ' + data.decode('utf-8')
if not data:
break
conn.sendall(str.encode(reply))
conn.close()
while True:
conn, addr = s.accept()
print('connected to: '+addr[0]+':'+str(addr[1]))
start_new_thread(threaded_client, (conn,))
Thanks
As suggested in the comments, you need to code the logic for accumulating data. Something like:
line = ""
while True:
data = conn.recv(1024)
for c in data:
if c == ord('\n'):
print "message: " + line
line = ""
else:
line = line + c
if not data:
break

Proper Non-blocking recv /select for TCP server

I have to write a code that allows non-blocking recv (along with non-blocking accept)
The following is what I got so far:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('', int(PortEntry_Page2_Text))
sock.bind(server_address)
sock.setblocking(0)
sock.settimeout(1)
sock.listen(1)
EnterToTerminal2("Listening to port "+str(PortEntry_Page2_Text)+"..")
EnterToTerminal2("Waiting for a connection. Press STOP to cancel.")
connected = 0
while (StopButtonStatePage2 == 0 and connected == 0):
try:
connection, client_address = sock.accept()
EnterToTerminal2("Connection from "+ str(client_address)+"..")
connected = 1
except Exception as inst:
template = "An exception of type {0} occured. Arguments:\n{1!r}"
message = template.format(type(inst).__name__,inst.args)
print message
finally:
if (connected == 0):
EnterToTerminal2("No client connected..")
StopButtonStatePage2 = GetStopButtonStatePage2()
###########################################
StopButtonStatePage2 = 0
sock.setblocking(0) ##?
print "xx0 "+str(connected)+" "+str(StopButtonStatePage2)
while (connected == 1 and StopButtonStatePage2 == 0):
a = select.select([sock], [], [], 1) # steelkiwi.com/blog/working-tcp-sockets
if a[0]:##?
data = sock.recv(64) # or connection.recv ??
EnterToTerminal2("Data recv: "+str(data))
StopButtonStatePage2 = GetStopButtonStatePage2()
Until sock.recv part, it works as expected. Now, the problem is that with the select approach, it does not enter the a[0] condition at all, even though I send stuff from client. Basically what I'm trying to achieve is to make recv part non-blocking/or with timeout so that I can stop its operation with a button, whenever I want.
Any help is appreaciated. Thanks in advance.

Raspberry pi python server not sending serial read/write commands

I've got two servers (written in python) that are nearly identical in the way they handle serial communications on the Pi. However, one works and the other one doesn't and I can't seem to find the problem. I've hooked up a logic analyzer and the first server triggers the rx/tx properly when communicating serially, however, the second server will not trigger anything.
First (working) server - cut down to show only the serial:
import socket
import sys
import RPi.GPIO as GPIO
from serial import Serial
#HOST = ' ' # Symbolic name meaning all available interfaces
PORT = 8888 # Arbitrary non-privleged port
ser = 0
#accepts a command as a string, parameters separated by white space
def processData( data ):
print ( "cmd : " + data).strip()
parseData = data.split(" ")
cmdLength = len(parseData)
cmd = parseData[0]
if cmd == "digitalWritePin":
pin = parseData[1]
state = parseData[2]
#GPIO.setup(pin, GPIO.OUT) # SHOULD HAVE ALREADY BEEN DONE W/ A CONFIG!!!
if state == '1':
GPIO.output(int(pin), True)
elif state == "0":
GPIO.output(int(pin), False)
elif cmd == "serialConfig":
baudRate = int(parseData[1])
timeOut = int(parseData[2])
global ser
ser = Serial('/dev/ttyAMA0', baudRate, timeout=timeOut)
elif cmd == "serialWrite":
serialcmd = parseData[1]
writeBuff = data.split("serialWrite")
#print writeBuff[1].strip(" ")
ser.write(writeBuff[1].strip(" "))
elif cmd == "serialReadLine":
print "serial read:"
response = ser.readline()
print response
conn.sendall(response)
print "read done"
return
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
s.bind((HOST,PORT))
print 'Socket bind complete'
s.listen(10) #parameter: backlog, controls number of connections that are 'queued'
print 'Socket now listening'
#Function f or handling connections. this will be used to create threads
def clientthread(conn):
#sending message to connected client
try:
while True:
data = conn.recv(1024)
if not data:
break
processData( data )
#out of the loop
conn.close()
except socket.error , msg:
print 'Recv failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#start new thread takes 1st argument as a function name to be run
#second is the tuple of arguments to the function
start_new_thread(clientthread,(conn,))
s.close
the most important parts of that being:
ser = Serial('/dev/ttyAMA0', baudRate, timeout=timeOut)
and the serial config/read/write areas of the el/if block
and the second sever (that is not working):
import socket
import sys
from time import sleep
from serial import Serial
from thread import *
import binascii
#HOST = ' ' # Symbolic name meaning all available interfaces
HOST = '10.1.10.28'
PORT = 8889 # Arbitrary non-privleged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
try:
s.bind((HOST,PORT))
except socket.error , msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket bind complete'
s.listen(10) #parameter: backlog, controls number of connections that are 'queued'
print 'Socket now listening'
ser = Serial('/dev/ttyAMA0', baudrate = 115200, timeout= 10)
#ser.open #--- uncommenting this does not make a difference
#Function f or handling connections. this will be used to create threads
def clientthread(conn):
#infinite loop so the function does not terminate and thread does not end
try:
while True:
print "step 1"
first = conn.recv(1)
print "step 2"
if not first:
break
hextFirst = hex( ord(first) )
print hextFirst
if hextFirst == '0xff':
print "step 3"
#ser.write(hextFirst) #send 0xff (converted)
ser.write(first) #send 0xff (orignal)
length = conn.recv(1) #get length
hextLength = hex( ord(length) ) #convert length
intlength = ord(length)
print "hextLength: " + hextLength
print "step 4"
#ser.write(hextLength) #send length (converted)
ser.write(length) #send length (original)
cmd = 0
if ord(length) == 0:
cmd = conn.recv(13)
else:
cmd = conn.recv(ord(length)-2)
hextCmd = binascii.b2a_hex(cmd)
print cmd
print "hextCmd: " + hextCmd
#ser.write(hextCmd) #send cmd (converted)
ser.write(cmd) #send cmd (original)
#sleep(1)
response = ser.read(1) #get response
#hextResponse = hex(ord(response))
print "serial resp: " + response
conn.sendall(response) #send response to LV
print "step 5"
print "step 6"
sleep(10)
#out of the loop
conn.close()
except socket.error , msg:
print 'Recv failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
try:
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#start new thread takes 1st argument as a function name to be run
#second is the tuple of arguments to the function
start_new_thread(clientthread,(conn,))
s.close
except KeyboardInterrupt:
ser.close
s.close
print "Exiting: Keyboard Interrupt"
I realize that is alot of code to go through, but you can ignore most of it, i'm just wondering what went wrong in the serial config/write. Like i said initially, the problem comes from the logic analyzer not seeing any serial communications (to or from) on the 2nd server, while the first server is working just fine
Try releasing /dev/ttyAMA0 from the default console by editing /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 ..
change it to
dwc_otg.lpm_enable=0 console=tty1 .....
and removing this line from /etc/inittab
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
also make sure you run the program as super user sudo

Python networking programming through sockets

I don't know how to make the server to take the command from the user ... I have untill now this code for the server
import socket, sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#HOST = sys.argv.pop() if len(sys.argv) == 3 else '127.0.0.1'
HOST = 'localhost'
PORT = 8080
def recv_all(sock, length):
data = ''
while len(data) < length:
more = sock.recv(length - len(data)).decode()
if not more:
raise EOFError('socket closed %d bytes into a %d-byte message' %
(len(data), length))
data += more
return data
#if sys.argv[1:] == ['server']:
if True:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
while True:
print('Listening at', s.getsockname())
sc, sockname = s.accept()
print('We have accepted a connection from', sockname)
print('Socket connects', sc.getsockname(), 'and', sc.getpeername())
message = recv_all(sc, 16)
print('The incoming sixteen-octet message says', repr(message))
sc.sendall('Farewell, client'.encode())
This is the rest from srver-side and i can't get working it from here , in rest everything works perfect! ....
if repr(message) == 'exit':
sc.close()
print('Reply sent, socket closed')
else:
print(sys.stderr, 'usage: tcp_local.py server|client [host]')
And this code for the client
import socket, sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# HOST = sys.argv.pop() if len(sys.argv) == 3 else '127.0.0.1'
HOST = 'localhost'
PORT = 8080
def recv_all(sock, length):
data = ''
while len(data) < length:
more = sock.recv(length - len(data)).decode()
if not more:
raise EOFError('socket closed %d bytes into a %d-byte message'
% (len(data), length))
data += more
return data
#elif sys.argv[1:] == ['client']:
if True:
print('Connecting to server on: ',HOST,' Port: ',PORT)
s.connect((HOST, PORT))
print('Client has been assigned socket name', s.getsockname())
s.sendall('Hi there, server'.encode())
print('Hi there, server, has been send')
reply = recv_all(s, 16)
print('The server said', repr(reply))
command = (input('enter:').encode())
s.sendall(command)
if s.send(command) == 'exit':
s.close()
else:
print(sys.stderr, 'usage: tcp_local.py server|client [host]')
I can get the client to ask the user for input , and when I enter the string 'exit' (without the quotation marks) in the client side I don't know how to make the server read the raw text and convert it into close server function ... any help would be greatly appreciated ... have a nice Sunday everyone !
I get "Type error : 'str' does not support the buffer interface"
Everythong works fine now , I've added the .encode() at the command = (input('enter:').encode()) part . but how do i make the server to close after this ?
I am not sure of what I am saying but for what I know, if you are using python 3.x, you need to convert string to bytes before sending to through an socket. On the client you should do command = bytes(input('enter:'), "utf-8") and on the server you have to put it back as string so, message = recv_all(sc, 16).decode("utf-8"). Not tested...

Categories