I try to make a two udp listening servers in one python code code is below,
import threading
import time
import socket
class udpreceive:
def __init__(self,port,ip):
self.port = port
self.ip = ip
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind((self.ip, self.port))
def startserver(self):
while True:
time.sleep(1)
data, addr = self.sock.recvfrom(1024)
print (data)
server1 = udpreceive(514,"192.168.1.5")
s1 = threading.Thread(target=server1.startserver())
server2 = udpreceive(515,"192.168.1.5")
s2 = threading.Thread(target=server2.startserver())
s2.start()
s1.start()
this is client code for udp sender 1
import socket
import time
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
counter =0
while True:
send_data = "hellow world server1 :- "+ str(counter)
sock.sendto(send_data.encode(), ("192.168.1.5", 514))
print (send_data)
counter +=1
this is client code for sender 2
import socket
import time
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
counter =0
while True:
send_data = "hellow world server2 :- "+ str(counter)
sock.sendto(send_data.encode(), ("192.168.1.5", 514))
print (send_data)
counter +=1
When i run receive code its only show sender 1 data. start only sender 2 and start receive code but its not show any sender 2 sending data but i start sender 1 receive code show sender 1 data.
what is the wrong thing i do? i need to show both sender 1 and sender 2 data in receive program
im new to oop and socket programming
thanks
In threading module, "target" keyword argument should not contain brackets,
see How NOT to wait for a thread to finish in Python . As it should be:
threading.Thread(target=server1.startserver)
Then, the two UDP server threads shall start then join, as fairly sharing CPU resources is important (especially when using infinite loops).
The code for the server could be:
import threading
import time
import socket
class udpreceive:
def __init__(self,port,ip):
self.port = port
self.ip = ip
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind((self.ip, self.port))
def startserver(self):
while True:
data, addr = self.sock.recvfrom(1024)
print(f'port {self.port} receives {data}')
s1 = udpreceive(514, "192.168.1.5")
s2 = udpreceive(515, "192.168.1.5")
threads = [threading.Thread(target=s1.startserver), threading.Thread(target=s2.startserver)]
for th in threads:
th.start()
print(f'threads {th} started')
th.join(0.1)
Meanwhile, you may need to change the code in sender 2 to:
sock.sendto(send_data.encode(), ("192.168.1.5", 515)) # Send to port 515, not 514
Related
I am trying to simply send messages from two client sockets to one server socket. When I start up the server socket, it works fine, and then when I start up each of the two client sockets (I'm using 3 different terminal windows) everything works fine. If I start up the server and one client, I can send messages from the client to the server. If I then start up the second client, I can send messages from the second client to the server, however now if I go back and try to send messages from the first client to the server, I get a " BlockingIOError: [Errno 11] Resource temporarily unavailable ". What is the problem?
clientclass.py:
from itertools import count
import select
import random
import threading
import time
class Client(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.host = "127.0.0.1"
self.port = 65432
def run(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.id = random.randrange(0, 1000)
print(f"client id {self.id} connected")
self.sock.connect((self.host, self.port))
while True:
text = input('m: ')
self.sock.sendall(text.encode())
server.py:
import socket
from itertools import count
import select
from _thread import start_new_thread
import threading
import time
from queue import Queue
class server(threading.Thread):
def __init__(self):
self.host = "127.0.0.1"
self.port = 65432
threading.Thread.__init__(self)
def run(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
self.sock.listen(5)
self.sock.setblocking(0)
print(f"server instantiated")
inputs = [self.sock]
outputs = []
message_queues = {}
while inputs:
inputready,outputready,exceptready = select.select(inputs,outputs,inputs)
for input_item in inputready:
if input_item is self.sock:
conn, addr = self.sock.accept()
print("New connection from: ", addr)
conn.setblocking(0)
inputs.append(conn)
else:
data = conn.recv(1024)
if data:
print("Client: " + data.decode())
#message_queues[input_item].put(data)
if input_item not in outputs:
outputs.append(input_item)
else:
if input_item in outputs:
outputs.remove(input_item)
inputs.remove(input_item)
input_item.close()
class Message_Sender(threading.Thread):
def __init__(self, client):
threading.Thread.__init__(self)
self.client = client
def run(self):
while True:
text = input('m: ')
server.conn.sendall(text.encode())
server = server()
server.start()
msg = Message_Sender(server)
msg.start()
client instances:
import clientclass
client = clientclass.Client()
client.start()
I saw your code and I think I have solved the problem you might have
I changed some code In a way It receives multiple clients at the same time
server.py:
import socket
from itertools import count
import select
from _thread import start_new_thread
import threading
import time
from queue import Queue
class server(threading.Thread):
def __init__(self):
self.host = "127.0.0.1"
self.port = 65432
threading.Thread.__init__(self)
def run(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind((self.host, self.port))
print(f"server instantiated")
inputs = [self.sock]
outputs = []
message_queues = {}
while True:
self.sock.listen(5)
conn, addr = self.sock.accept()
receive = threading.Thread(target=self.receive_data, args=(conn,))
receive.start()
inputs.append(conn)
def receive_data(self, conn):
while True:
data = conn.recv(1024)
if data:
print("Client: " + data.decode())
# do something
class Message_Sender(threading.Thread):
def __init__(self, client):
threading.Thread.__init__(self)
self.client = client
def run(self):
while True:
text = input('m: ')
server.conn.sendall(text.encode())
server = server()
server.start()
msg = Message_Sender(server)
msg.start()
I have made a loop inside the run function, when someone tries to connect it will make a new thread to receive their messages. it wasn't clear to me what you wanted to do with the variables inputs and input_item, ect. but I think you can get really far with this. If you still have any problems feel free to reach out.
my raspberry pi is the server and Im trying to send continuous message from rpi to android while recieving a command from client (android app),i really dont know if this is possible and how to do it is out of my reach and it is not a feedback message here is my code hope you will help me thank you.
import apptopi
from socket import *
from time import ctime
from nanpy import (ArduinoApi, SerialManager)
apptopi.setup()
connection = SerialManager()
a = ArduinoApi(connection = connection)
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
add = 0
add += 1
a = str(add) //**this is a sample that i want to send continously
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(0)
tcpSerSock.send(str.encode(a)) <== i really don't know how to send
continuously
while True:
print 'Waiting for connection'
tcpCliSock,addr = tcpSerSock.accept()
print '...connected from :', addr
try:
while True:
data = ''
data = tcpCliSock.recv(BUFSIZE)
if not data:
break
if data == ctrCmd[0]:
apptopi.forw()
print 'forward'
if data == ctrCmd[1]:
apptopi.back()
print 'backward'
if data == ctrCmd[2]:
apptopi.left()
print 'leftturn'
if data == ctrCmd[3]:
apptopi.right()
print 'rightturn'
if data == ctrCmd[4]:
apptopi.stp()
print 'stop'
except KeyboardInterrupt:
apptopi.close()
GPIO.cleanup()
tcpSerSock.close();
OK one approach is to use the select() function for this. There is information in the documentation about its operation.
As an example I've made a modified version of your program (see below). I don't have a raspberry pi, so that part of the code is commented out, but you can replace it as needed.
The example uses the timeout feature of select() to send "continuous" messages to clients whilst also monitoring them for incoming messages. You can adjust the message contents and timeout to whatever works for you. NB you may also need to respond to client messages, as this code only sends data to clients after a timeout. Make whatever changes you need.
import sys
import socket
import select
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpSerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(1)
print 'Waiting for connection'
sendInterval = 1.0 # interval(sec) for sending messages to connected clients
rxset = [tcpSerSock]
txset = []
while 1:
rxfds, txfds, exfds = select.select(rxset, txset, rxset, sendInterval)
if rxfds:
for sock in rxfds:
if sock is tcpSerSock:
# a client is connecting
tcpCliSock, addr = tcpSerSock.accept()
tcpCliSock.setblocking(0)
rxset.append(tcpCliSock)
print '...connected from :', addr
else:
# a client socket has data or has closed the connection
try:
data = sock.recv(BUFSIZE)
if not data:
print "...connection closed by remote end"
rxset.remove(sock)
sock.close()
else:
if data == ctrCmd[0]:
#apptopi.forw()
print 'forward'
if data == ctrCmd[1]:
#apptopi.back()
print 'backward'
if data == ctrCmd[2]:
#apptopi.left()
print 'leftturn'
if data == ctrCmd[3]:
#apptopi.right()
print 'rightturn'
if data == ctrCmd[4]:
#apptopi.stp()
print 'stop'
except:
print "...connection closed by remote end"
rxset.remove(sock)
sock.close()
else:
# timeout - send data to any active client
for sock in rxset:
if sock is not tcpSerSock:
sock.send("Hello!\n")
The simple client program I used to test this is here:
import sys
import socket
import time
ctrCmd = ['Up','Down','Left','Right','Stop','Connect']
HOST = '127.0.0.1'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST,PORT)
tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpCliSock.connect(ADDR)
time.sleep(1)
for i in range(len(ctrCmd)):
tcpCliSock.send(ctrCmd[i])
time.sleep(1)
data = tcpCliSock.recv(BUFSIZE)
print data
tcpCliSock.close()
Hope this helps, best of luck.
I have msg list and socket list and i want to change it between the 2 threads so one can change it and both can use the new one.
The code is the server of chat who more than 2 clients can connect and talk to each other
Here is the code:
import threading
import socket
import time
global Clients
global MsgQue
def inputmsg():
while 1:
try:
Clients.append(server.accept())
except socket.error:
print("No new Socket")
for cli in Clients:
try:
MsgQue.append(cli[0].recv(4096))
except socket.error:
print("Warning no input")
def outputmsg():
for cli in Clients:
if(MsgQue):
cli[0].send(MsgQue[0])
MsgQue.pop(0)
threads = []
server = socket.socket()
host = "127.0.0.1"
port = 1212
server.bind((host,port))
server.setblocking(0)
server.listen(5)
Clients = []
MsgQue = []
threading._start_new_thread(inputmsg,())
threading._start_new_thread(outputmsg,())
while 1:
if( 1 == 4):
print ("WTF")
I have implemented a small benchmark for socket communication via TCP and UDP in Python. Surprisingly, TCP is almost exactly double as fast as UDP.
To avoid routing effects, server and client are running on the same Unix machine, but on different threads.
Maybe the code is useful. Here is the server code:
import socket
import sys
host = 'localhost'
port = 8888
buffersize = 8
server_address = (host, port)
def start_UDP_server():
socket_UDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket_UDP.bind(server_address)
print("UDP server is running...")
while True:
data, from_address = socket_UDP.recvfrom(buffersize)
if not data: break
socket_UDP.sendto(data, from_address)
socket_UDP.close()
def start_TCP_server():
socket_TCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_TCP.bind(server_address)
socket_TCP.listen(1)
print("TCP server is running...")
while True:
client, client_address = socket_TCP.accept()
while True:
data = client.recv(buffersize)
if not data: break
client.sendall(data)
client.close()
So you can run either start_TCP_server() or start_UDP_server().
On client side the code is:
import socket
import sys
import time
host = 'localhost'
port = 8888
buffersize = 8
server_address = (host, port)
client_address = (host, port+1)
N = 1000000
def benchmark_UDP():
socket_UDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket_UDP.bind(client_address)
print("Benchmark UDP...")
duration = 0.0
for i in range(0, N):
b = bytes("a"*buffersize, "utf-8")
start = time.time()
socket_UDP.sendto(b, server_address)
data, from_address = socket_UDP.recvfrom(buffersize)
duration += time.time() - start
if data != b:
print("Error: Sent and received data are bot the same")
print(duration*pow(10, 6)/N, "µs for UDP")
def benchmark_TCP():
socket_TCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_TCP.connect(server_address)
print("Benchmark TCP...")
duration = 0.0
for i in range(0, N):
b = bytes("a"*buffersize, "utf-8")
start = time.time()
socket_TCP.sendall(b)
data = socket_TCP.recv(buffersize)
duration += time.time() - start
if data != b:
print("Error: Sent and received data are bot the same")
print(duration*pow(10, 6)/N, "µs for TCP")
socket_TCP.close()
Like for the server you can start the benchmark by benchmark_TCP() or benchmark_UDP().
The results are about 25 µs for TCP, and about 54 µs for UDP on Unix and even worse for Windows (about 30 µs for TCP and more than 200 µs for UDP). Why? I would expect a minimal advantage for UDP.
Your TCP socket is connected but your UDP socket is not. This means extra processing for every send/receive on the UDP socket. Call connect on each side for the UDP socket, just like you call connect/accept on the TCP socket.
Programs like iperf do this to measure accurately.
Trying to make a server that tells the client what number he/she is. For example, once you connect it should say something like "Welcome client #5" or something along those lines. Right now I'm just trying to write it so that it simply reads a line in and echos it back. Im stuck on as far as getting it to show the clients number.
import socket
import sys
host = ''
port = 37373
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(1)
while 1:
s, address = s.accept()
data = s.recv(1024)
if data:
s.send(data)
s.close()
that is
import socket
import sys
Clinet_number = 0
host = ''
port = 37373
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(10) # number of queued connections
while 1:
Client_number += 1
s, address = s.accept()
data = s.recv(1024)
if data:
s.send(str(Client_number))
s.close()