Python UDP client-server with different matching incoming-outgoing ports - python-3.x

Based on the example at http://www.binarytides.com/programming-udp-sockets-in-python/ I modified it to run on python 3 and used two opposed ports on client and server, so replies from each one go to these ports. Here are my examples
Server:
'''
Simple udp socket server
'''
import socket
import sys
HOST = 'localhost'
PORT_IN = 8889 # Arbitrary non-privileged port
PORT_OUT = 8888
# Datagram (udp) socket
try :
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print('Socket created')
except socket.error as e:
print(e)
sys.exit()
# Bind socket to local host and port
try:
s.bind((HOST, PORT_IN))
except socket.error as e:
print(e)
sys.exit()
print('Socket bind complete')
#now keep talking with the client
while 1:
# receive data from client (data, addr)
d = s.recvfrom(1024)
data = d[0]
addr = d[1]
if not data:
break
reply = 'OK...' + str(data)
s.sendto(reply.encode('UTF-8'), ('localhost', PORT_OUT))
print('Message[' + addr[0] + ':' + str(addr[1]) + '] - ' + str(data).strip())
s.close()
Client:
'''
udp socket client
Silver Moon
'''
import socket #for sockets
import sys #for exit
# create dgram udp socket
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error:
print('Failed to create socket')
sys.exit()
host = 'localhost'
port_out = 8889
port_in = 8888
counter = 0
while(1) :
# msg = b'aoua'
msg = 'aoua' + str(counter)
try :
#Set the whole string
s1.sendto(msg.encode('UTF-8'), (host, port_out))
# receive data from client (data, addr)
s2.bind(('localhost', port_in))
d = s2.recvfrom(1472)
reply = d[0]
addr = d[1]
print('Server reply : ' + str(reply))
except socket.error as e:
print(e)
# sys.exit()
counter += 1
Problem is with the client which cannot receive any response from server and d = s2.recvfrom(1472) hangs with error [WinError 10022] An invalid argument was supplied.
I've noticed a slightly different behaviour with sock.settimeout(seconds), but I really can't figure why. Isn't d = s2.recvfrom(buffer) supposed to wait for incoming data?
What am I missing here?

Damn... Just saw it. Silly mistake. Calling s2.bind(('localhost', port_in)) in Client inside the loop.

Related

Why isnt my python socket server receiving the messages?

so i am making a chatroom in python using sockets for practice. I have made the server code using threading so that i can have more clients. Ive also made the client code, and when i try to run two clients at once so that they message from one to another, they connect to server, but the server doesnt seem to be receiving the message sent from either of the clients.
SERVER CODE:
import select
from threading import *
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# takes the first argument from command prompt as IP address
IP_address = "127.0.0.1"
# takes second argument from command prompt as port number
Port = int("50204")
server.bind((IP_address, Port))
server.listen(1000)
list_of_clients = []
def clientthread(conn, addr):
# sends a message to the client whose user object is conn
conn.send("Welcome to this chatroom!")
while True:
try:
message = conn.recv(4096)
if message:
print("<" + addr[0] + "> " + message.decode("UTF-8"))
# Calls broadcast function to send message to all
message_to_send = "<" + addr[0] + "> " + message
broadcast(message_to_send.encode("UTF-8"), conn)
else:
remove(conn)
except:
continue
def broadcast(message, connection):
for clients in list_of_clients:
if clients != connection:
try:
clients.send(message)
except:
clients.close()
# if the link is broken, we remove the client
remove(clients)
def remove(connection):
if connection in list_of_clients:
list_of_clients.remove(connection)
while True:
conn, addr = server.accept()
list_of_clients.append(conn)
# prints the address of the user that just connected
print(addr[0] + " connected")
# creates and individual thread for every user
# that connects
Thread(target=clientthread, args=(conn, addr))
conn.close()
server.close()
CLIENT CODE:
import socket
import sys
import time
class client:
def __init__(self):
self.server_ip = "127.0.0.1"
self.port = 50204
self.s = self.connect()
def connect(self):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print("Failed to create socket.")
sys.exit()
print("Socket created")
try:
s.connect((self.server_ip, self.port))
except socket.error:
print("Failed to connect to ip " + self.server_ip)
print("Connected to: " + str(s.getsockname()))
return s
def SocketQuery(self, Sock, cmd):
try:
try:
# Send cmd string
Sock.send(cmd)
print("Sent!")
time.sleep(1)
except socket.error:
# Send failed
print("Send failed!")
sys.exit()
reply = Sock.recv(4096)
return reply
except ConnectionResetError:
print("Server is down!")
def SocketClose(self, Sock):
# close the socket
Sock.close()
time.sleep(.300)
if __name__ == "__main__":
c = client()
c.connect()
print("connected")
while True:
inp = input(">>> ")
if inp == ":q":
break
reply = c.SocketQuery(c.s, inp.encode("UTF-8"))
if reply:
print(reply.decode("UTF-8"))
c.SocketClose(c.s)
So as i have already mentioned, they do connect, but dont send/receive messages.
i have checked the value in conn.recv(), and it is the same, also everything gets encoded to UTF-8 before sent, and then decoded back. I cant seem to find any other problem except that im running them all on localhost.
If anyone knows the answer to this, please tell me.
cheers!

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 3 socket client not connecting to server

I have a server.py and client.py pair. When I run the server on my machine and open multiple terminals to runs clients, I can connect fine. But when I try to run clients on another computer, the client never connects to the server. I'm pretty sure I tested this code a few months ago on multiple computers and it worked fine (though maybe I'm remembering wrong), but I think I updated my python version, so maybe that's why? How can I change my code below so it works?
server.py
import socket
from threading import Thread
import sys
clients = []
def recv(clientsocket):
while True:
msg = clientsocket.recv(1024) # wait for message from any of the clients.
print("\n" + msg.decode())
for c in clients: # send to all the clients.
c.send(msg)
def send(clientsocket):
while True:
msg = "[Server] %s" % input("\n") # wait for input
print(msg)
for c in clients: # send to all the clients.
c.send(msg.encode())
clientsocket.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create a socket object
host = socket.gethostname() # Get local machine name
#port = 3001 # Reserve a port for your service.
port = int(input("Enter port: "))
print ('Server started at [%s]' % socket.gethostbyname(host))
print ('Waiting for clients...')
#s.bind((host, port)) # Bind to the port
s.bind((socket.gethostbyname(host), port))
s.listen(5) # Now wait for client connection.
while True:
#Waits until someone new to accept
c, addr = s.accept()
print(addr, "connected.")
clients.append(c)
thread_recv = Thread(target=recv, args=((c,)))
thread_recv.start()
thread_send = Thread(target=send, args=((c,)))
thread_send.start()
s.close()
client.py
import socket
from threading import Thread
hostname = input("Enter hostname/IP to connect to: ")
# port = 3001
port = int(input("Enter port: "))
clientsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsocket.connect((hostname, port))
def recv():
while True:
print("\n" + clientsocket.recv(2048).decode())
def send(username):
while True:
msg = "[%s] %s" % (username, input(""))
clientsocket.send(msg.encode()) # send message to the server.
username = input("Choose a username: ")
msg = "[%s has just connected]" % (username)
clientsocket.send(msg.encode())
thread_send = Thread(target=send, args=(username,))
thread_send.start()
thread_recv = Thread(target=recv, args=())
thread_recv.start()
while True:
# keep the threads going.
pass
Edit
Every time I start the server, it says my ip address is the same: 192.168.56.1. Even though I've turned my computer off and tried again. But when I go to Google and ask what is my ip address, it is something totally different. Why does the socket keep choosing 192.168.56.1? Is there something special about it? Is this something related to my problem?
Just bind you server to 0.0.0.0 and bind it to all network interfaces:
server.py
s.bind(('0.0.0.0', port))
Then the code in server.py will end up being something like this:
import socket
from threading import Thread
import sys
clients = []
def recv(clientsocket):
while True:
msg = clientsocket.recv(1024) # wait for message from any of the clients.
print("\n" + msg.decode())
for c in clients: # send to all the clients.
c.send(msg)
def send(clientsocket):
while True:
msg = "[Server] %s" % input("\n") # wait for input
print(msg)
for c in clients: # send to all the clients.
c.send(msg.encode())
clientsocket.close()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create a socket object
host = socket.gethostname() # Get local machine name
#port = 3001 # Reserve a port for your service.
port = int(input("Enter port: "))
print ('Server started at [%s]' % socket.gethostbyname(host))
print ('Waiting for clients...')
#s.bind((host, port)) # Bind to the port
s.bind(('0.0.0.0', port))
s.listen(5) # Now wait for client connection.
while True:
#Waits until someone new to accept
c, addr = s.accept()
print(addr, "connected.")
clients.append(c)
thread_recv = Thread(target=recv, args=((c,)))
thread_recv.start()
thread_send = Thread(target=send, args=((c,)))
thread_send.start()
s.close()

s.recv hang in python sockets

I have a client and server machine.
From client I am sending a linux command which replies after 80 sec.
As the server does not reply initial80 seconds the (s.recv) and a timeout error occurs.
Please help how to proceed here?
s= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(300)
s.connect((hostname, self.port))
s.sendall(self.msg)) # where msg is some linux command or script which replies after 80 seconds
#s.shutdown(socket.SHUT_WR)
while 1:
data = s.recv(1024)
if data == b"":
break
datai = datai + data.decode()
self.result[hostname.decode()] = datai
I couldn't reproduce it. Here's server and client code that is almost what you have - it works as desired:
client:
#!/usr/bin/env python3
import socket #for sockets
import sys #for exit
try:
#create an AF_INET, STREAM socket (TCP)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
print 'Failed to create socket. Error code: ' + str(msg[0]) + ' , Error message : ' + msg[1]
sys.exit();
print 'Socket Created'
host = 'localhost'
port = 8888
try:
remote_ip = socket.gethostbyname( host )
except socket.gaierror:
#could not resolve
print 'Hostname could not be resolved. Exiting'
sys.exit()
print 'Ip address of ' + host + ' is ' + remote_ip
message = "The message \n"
#Code from Stackoverflow question
#s= socket.socket(socket.AF_INET, socket.SOCK_STREAM) # this is already done
s.settimeout(300)
#Connect to remote server
#s.connect((hostname, self.port)) # different variable name
s.connect((remote_ip , port))
print 'Socket Connected to ' + host + ' on ip ' + remote_ip
s.sendall(message) # where msg is some linux command or script which replies after 80 seconds
#s.shutdown(socket.SHUT_WR)
while 1:
data = s.recv(1024)
print("Ok, I get the response :)")
if data == b"":
break
datai = "DATAI: "
datai = datai + data.decode()
#self.result[hostname.decode()] = datai
print("Datai: " + str(datai))
#End
break
s.close()
server:
#!/usr/bin/env python3
'''
Simple socket server using threads.
Taken from: https://www.binarytides.com/python-socket-server-code-example/
'''
#Code for reproduce stackoverflow question
from time import sleep
#End
import socket
import sys
HOST = '' # Symbolic name, meaning all available interfaces
PORT = 8888 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
#Bind socket to local host and port
try:
s.bind((HOST, PORT))
except socket.error as msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket bind complete'
#Start listening on socket
s.listen(10)
print 'Socket now listening'
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
while True:
#Receiving from client
data = conn.recv(1024)
#Code for reproduce stackoverflow question
print("Waiting 80secs...")
sec = 0
while(sec < 80):
sleep(10)
sec = sec + 10
print(str(sec))
print("Ok, I'll reply...")
#End
if not data:
reply = ""
else:
reply = 'OK...' + data
conn.sendall(reply)
break
conn.close()
s.close()

Python socket server that can send different data to multiple clients at the same time

I'm working on a socket based application in Python 3 that will be used to configure several raspberry pi devices from a central Python server.
I have managed to write a bit of code that allows for multiple devices to connect at the same time but I can only send data from the server on the newest connection.
Here is the code:
import socket
import sys
import threading
import time
def manageClient(conn, addr):
def Ping(conn):
count = 0
while True:
conn.send(str(count).encode())
time.sleep(1)
count += 1
print(count)
conn.send(b'Welcome to the server. Type something and hit enter\n')
threading.Thread(target = Ping, args = (conn,)).start()
while True:
data = conn.recv(1024)
print(addr[0] + ': ' + data.decode())
reply = 'OK...' + data.decode()
if not data:
break
conn.sendall(reply.encode())
print('Disconnected from ' + addr[0] + ':' + str(addr[1]))
conn.close()
def addClient():
host = '192.168.1.24'
port = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('Socket created')
try:
s.bind((host, port))
except socket.error as msg:
print('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
print('Socket bind complete')
s.listen(10)
print('Socket now listening')
while True:
conn, addr = s.accept()
print('Connected with ' + addr[0] + ':' + str(addr[1]))
threading.Thread(target = manageClient, args = (conn, addr,)).start()
s.close()
threading.Thread(target = addClient).start()
I would like to be able to have multiple users at the same time but a GUI that allows me to configure each device separately over the connection. I understand that this means coming up with a separate name for each connection but I'm not sure how I would achieve this. As of now bi directional communication does work even when multiple devices are connected I'm just unable to send unique messages to each system from the server once a new connection is established.
Thanks
Oliver.

Resources