Im trying to implement both TCP and UDP in my server. I can accept a TCP or UDP port connection from a client.
for example, I want to have code to accept TCP and UDP in one program:
# create a socket
sockTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP
sockUDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
# server address to connect to
server_addressTCP = ('localhost', tcp_port)
server_addressUDP = ('localhost', udp_port)
# bind socket to adress and port number
sockTCP.bind(server_addressTCP)
sockUDP.bind(server_addressUDP)
# wait for connections (clients)
print("Waiting for connections...")
print(" ")
sockTCP.listen(20)
request = ''
while True:
#TCP
client_sock, client_addr = sockTCP.accept()
data, addr = client_sock.recvfrom(1024)
#UDP
udp_data, udp_addr = sockUDP.recvfrom(1024)
# DO SOMETHING WITH DATA.........
client_sock.close()
If you want to implement a server that listens on UDP and TCP then create listener threads: one for UDP and one for TCP connections.
Here is an example of a server listening on both TCP and UDP ports.
import socket
import threading
tcp_port = udp_port = 1234
def udp_listen(conn):
while True:
data = conn.recv(1024)
if len(data) != 0:
print("recv:", data)
def tcp_listen(sock):
while True:
conn, _ = sock.accept()
try:
while True:
data = conn.recv(1024)
if len(data) == 0:
break
print("recv:", data)
except Exception:
pass
try:
conn.close()
except Exception:
pass
# create a socket
sockTCP = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP
sockUDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
# server address to connect to
server_addressTCP = ('localhost', tcp_port)
server_addressUDP = ('localhost', udp_port)
# bind socket to adress and port number
sockTCP.bind(server_addressTCP)
sockUDP.bind(server_addressUDP)
sockTCP.listen(20)
t1 = threading.Thread(target=tcp_listen, args=(sockTCP,))
t2 = threading.Thread(target=udp_listen, args=(sockUDP,))
print("Waiting for connections...")
t1.start()
t2.start()
t1.join()
t2.join()
Related
I cant figure out why the client is not communicating with the Server (2 seperate jupyter notebooks with own kernel), no error messages - any suggestions?
the following code is working (without multiprocessing):
Server:
import socket
HOST = '127.0.0.1'
PORT = 50000
def start_server():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen()
print ('waiting for client')
conn, addr = s.accept()
print('client connected #', addr[0], 'port:', addr[1])
return conn
Server0 = start_server()
Client:
import socket
HOST = '127.0.0.1'
PORT = 50000
data = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect_ex((HOST, PORT))
while True:
byte_message = s.recv(1024)
string_message = byte_message.decode('utf8')
header, time, data = string_message.split(' ')
if header == 'close':
s.shutdown(socket.SHUT_RDWR)
s.close()
print('client connection shut down')
header = ''
elif header == '<<':
print(time,float(data))
else:
pass
As soon as I pack the client into a function and run it as a process, client and server do not connect anymore(no error is given, and the server doesent get to this line:
print('client connected #', addr[0], 'port:', addr[1])
not working client:
import socket
import multiprocessing
HOST = '127.0.0.1'
PORT = 50000
def client():
data = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect_ex((HOST, PORT))
while True:
byte_message = s.recv(1024)
string_message = byte_message.decode('utf8')
header, time, data = string_message.split(' ')
if header == 'close':
s.shutdown(socket.SHUT_RDWR)
s.close()
print('client connection shut down')
header = ''
elif header == '<<':
print(time,float(data))
else:
pass
client_process = multiprocessing.Process(target= client)
client_process.start()
I created a TCP server and set the timeout to 30s but i want the timeout countdown to show on the screen in realtime and print Client not connected if the 30 elapsed.
Expected output:
import socket
#import datetime
import time
def countdown(t):
while t:
mins, secs = divmod(t, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
print(timer, end="\r")
time.sleep(1)
t -= 1
t = 30
#countdown(t)
def SocketServer():
host = input ("Enter the server IP addresss:" )
port = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((host, port))
s.listen(2)
s.settimeout(t)
print(""" ***********************************************************
This Server will timeout if no client connect in 30 seconds
************************************************************""")
countdown(t)
conn, addr = s.accept()
print(addr, "connectiom is establish")
conn.send("Hello Client!".encode())
conn.close()
except socket.timeout:
print("client not connected!")
s.close()
SocketServer()
I hope this will help you!
I will post the code for a client to connect with this server!
I wrote some lines in order to guide you!
import socket
import threading
import time
class SocketServer():
def __init__(self):
self.t=30
self.adr=""
print(""" ***********************************************************
This Server will timeout if no client connect in 30 seconds
************************************************************""")
#let's create a new thread for out server
# in the main thread, we will print and count seconds....
self.thread=threading.Thread(target=self.thread)
self.thread.daemon=True
self.thread.start()
self.counter()
def thread(self):
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8888 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('Connected by', addr)
#we want to know if someone is connected
#by set self.adr with something that has len>0 we will informe the main thread that it needs to stop
self.adr="Connected"
conn.send("Hello Client!".encode())
s.close() #if you want to close, or leave it to further connections
def counter(self):
for x in range(self.t + 1):
time.sleep(1)#sleep function
if (len(self.adr)!=0): #every time we chech if sel.adr is different from 0
print("Connection is established")
print("Connected after 00:{:02d}".format(x))
break #stop
else:
print ('00:{:02d}'.format(x))
#host = raw_input("Enter the server IP addresss:")
SocketServer()
Code for the client!
import socket
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 8888 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
print('Received', repr(data))
Output:
***********************************************************
This Server will timeout if no client connect in 30 seconds
************************************************************
00:00
00:01
00:02
00:03
Connected by ('127.0.0.1', 27191)
Connection is established
Connected after 00:04
Client output:
Received b'Hello Client!'
I'm using threads to have a server listening for both TCP and UDP messages. Here is the code:
from threading import Thread
import time
import socket
Listening_Port = 5005
Listening_IP = "127.0.0.1"
#define UDP listening function
def UDPListen():
BUFFER_SIZE = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # IPv4, UDP
sock.bind((Listening_IP, Listening_Port))
while True:
data, address = sock.recvfrom(BUFFER_SIZE)
print "UDP Messsage from address: ", address
print "Message: ", data
#define a TCP listening function
def TCPListen():
BUFFER_SIZE = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4, TCP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((Listening_IP, Listening_Port))
while True:
sock.listen(1)
conn, address = sock.accept()
print "TCP connection from", address
data = conn.recv(BUFFER_SIZE)
print "Mesage: ", data
conn.close()
# main function
def main():
ThreadUDP = Thread(target=UDPListen)
ThreadTCP = Thread(target=TCPListen)
print "Starting Server..."
ThreadUDP.start()
ThreadTCP.start()
print "Server Started!"
if __name__ == "__main__":
main()
The problem is that when I press ctrl + c (even multiple times), the program is not terminated and I should close the console.
I tried something like this for def main(), but it didn't work:
def main():
ThreadUDP = Thread(target=UDPListen)
ThreadTCP = Thread(target=TCPListen)
try:
print "Starting Server..."
ThreadUDP.start()
ThreadTCP.start()
print "Server Started!"
# Hit Break / Ctrl-C to exit
except KeyboardInterrupt:
print('\nClosing')
raise
Updated code according to the solution offered in the answers:
from threading import Thread
import time
import socket
Listening_Port = 5005
Listening_IP = "10.0.0.3"
#define UDP listening function
def UDPListen():
BUFFER_SIZE = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # IPv4, UDP
sock.bind((Listening_IP, Listening_Port))
while not eve.isSet():
data, address = sock.recvfrom(BUFFER_SIZE)
print "UDP Messsage from address: ", address
print "Message: ", data
#define a TCP listening function
def TCPListen():
BUFFER_SIZE = 1024
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4, TCP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((Listening_IP, Listening_Port))
while not eve.isSet():
sock.listen(1)
conn, address = sock.accept()
print "TCP connection from", address
data = conn.recv(BUFFER_SIZE)
print "Mesage: ", data
conn.close()
# main function
def main():
ThreadUDP = Thread(target=UDPListen)
ThreadTCP = Thread(target=TCPListen)
eve = threading.Event()
print "Starting Server..."
ThreadUDP.start()
ThreadTCP.start()
print "Server Started!"
try:
while True:
eve.wait(2)
except Exception:
eve.set()
if __name__ == "__main__":
main()
but I received an error:
NameError: Global name 'threading' is not defined
the problem you have is that you run your listeners in a thread - meaning that signals caught in the main should somehow signal the threads.
use threading.Event and then in the main function :
eve = threading.Event()
<start your threads>
try:
while True:
eve.wait(2)
except Exception
eve.set()
and in the threads instead of while True use while not eve.isSet():
I'm writing a proxy with tcp connection that listens to multiple ports from a client and forward it to a server.
The problem is that the software hangs on the sock.accept.
Maybe I'm doing a messy logic here, but I need a client that connects to a PC, and that PC connects to another device. So I wrote that small proxy, and I get INVALID ARGUMENT ERROR in socket.accept()
import select
import socket
import threading
class Proxy(object):
def __init__(self, ip, ports):
self._ip = ip
self._sockets = []
self._proxy = {}
for port in ports:
self._proxy[port] = self.add_socket(port)
def add_socket(self, port=None):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if port:
# sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sock.bind(('0.0.0.0',port))
self._sockets.append(sock)
return sock
def get_client(self, src_sock, src_addr):
src_ip, src_port = src_addr
_, dst_port = src_sock.getsockname()
if src_ip == self._ip:
# got packet from device
dst_addr = ("10.8.8.210", dst_port)
else:
# got packet from client
dst_addr = self._ip, dst_port
print(">", src_port, dst_addr)
dst_sock = self._proxy[src_port]
return dst_sock, dst_addr
def run(self):
while True:
read_list, _, _ = select.select(self._sockets, [], [])
if read_list:
for sock in read_list:
try:
conn, addr = sock.accept()
data = conn.recvfrom(16*2024)
# print("got data from {} {}".format(sock, addr))
dst_sock, dst_addr = self.get_client(sock, addr)
# print("forwarding data from {} to {}".format(addr, dst_addr, len(data)))
dst_sock.sendto(data, dst_addr)
except:
raise # pass # print("no recipient for data")
for s in self._sockets:
s.close()
ports = [30001,30002,30003, 30070, 30071,30072,30075]
p = Proxy("192.168.2.10", ports)
p.run()
You have to call listen on the socket before accept:
adding sock.listen(1) to add_socket after bind
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('0.0.0.0', port))
sock.listen(1)
self._sockets.append(sock)
then allows you to call accept without the error. You may want to set the listen backlog to a greater number.
Below are my three scripts. I need to send the message from sricpt 1(Sensor.py) to script 2.(Client.py). And then the script 2 should send the message to script 3(Server.py).
It works fine till script 2 but the message isn't being received at the script 3 and the recvfrom() keeps waiting. There is no error but the script 3 doesn't show the message. Im using UDP. Please help.
SCRIPT 1(Sensor.py)
from socket import *
from time import ctime
CLIENT_IP = '192.168.1.109'
PORT = 23567
BUFSIZE = 1024
ADDR = (CLIENT_IP, PORT)
udpCliSock = socket(AF_INET, SOCK_DGRAM)
while True:
sendData = input("> ")
if sendData is None:
break
udpCliSock.sendto(sendData.encode(), ADDR)
udpCliSock.close()
SCRIPT 2(Client.py)
from socket import *
from time import ctime
HOST = '192.168.1.103'
CLIENT_IP='192.168.1.109'
PORT = 5005
SENSOR_PORT_NO=23567
BUFSIZE = 1024
ADDR = (HOST, PORT)
CLIENT_ADDR=(CLIENT_IP,SENSOR_PORT_NO)
udpCliSock = socket(AF_INET, SOCK_DGRAM)
client = socket(AF_INET, SOCK_DGRAM)
client.bind(CLIENT_ADDR)
while True:
print("...waiting for response...")
#recv_data, ADDR = udpCliSock.recvfrom(BUFSIZE)
recv_data, ADDR = client.recvfrom(1024)
if recv_data is not None:
recv_data = recv_data.decode()
print("[%s]: receiving data from server %s:%s :%s" % (ctime(),ADDR[0], ADDR[1], recv_data))
sendData = recv_data
udpCliSock.sendto(sendData.encode(), ADDR)
udpCliSock.close()
SCRIPT 3(Server.py)
from socket import *
from time import ctime
HOST = '192.168.1.103'
PORT = 5005
BUFSIZE = 1024
ADDR = (HOST, PORT)
udpSerSock = socket(AF_INET, SOCK_DGRAM)
udpSerSock.bind(ADDR)
while True:
print("...waiting for message...")
data, ADDR = udpSerSock.recvfrom(BUFSIZE)
print(data.decode)
if data is None:
break
print("[%s]: From Address %s:%s receive data: %s" % (ctime(),ADDR[0],ADDR[1], data.decode()))
udpSerSock.close()
The problem is that, in the Client.py, you are overwriting the address of the server when you receive the datagram from the sensor. Here:
recv_data, ADDR = client.recvfrom(1024)
ADDR starts out with the server's socket address, but this function overwrites that variable with the sensor's socket address. So when you try to send, you're sending it back to the sensor (who of course isn't ever receiving it).
A better method is to connect that socket to the server at the beginning. Then you can just use send instead of sendto since the address won't be changing. Should work after that:
...
udpCliSock = socket(AF_INET, SOCK_DGRAM)
udpCliSock.connect(ADDR) # <<<<<<===============
client = socket(AF_INET, SOCK_DGRAM)
client.bind(CLIENT_ADDR)
while True:
print("...waiting for response...")
recv_data, addr = client.recvfrom(1024)
if recv_data is not None:
recv_data = recv_data.decode()
print("[%s]: receiving data from server %s:%s :%s" % (ctime(),addr[0], addr[1], recv_data))
sendData = recv_data
udpCliSock.send(sendData.encode()) # <<<<<<===============
udpCliSock.close()