Last active
October 23, 2019 22:25
-
-
Save jirassimok/7c6589645b77bdd12e08ad254b8d28b8 to your computer and use it in GitHub Desktop.
Stack Overflow Sockets question
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Code in other all other files adapted from here: | |
https://stackoverflow.com/q/58424446 | |
This is just a simple script that runs processes for the server and client. | |
My comments in server.py and client.py all start with '##'. | |
shared.py sets the global variables shared by the client and the server, | |
and it modifies a handful of functions they use to improve logging. | |
The arguments to this script are the port for the server to use | |
and the number of clients to test. | |
If the output includes the phrase "client thread completed" a number of | |
times equal to the number of clients, the behavior was what I believe the | |
asker expected (i.e. the server processed each client). However, the script | |
will not terminate, and will need to be closed manually. | |
""" | |
import subprocess | |
import sys | |
import time | |
try: | |
port = int(sys.argv[1]) # just make sure it's an int | |
port = str(port) | |
except IndexError: | |
print('usage: test.py PORT [NUMBER_OF_CLIENTS]', file=sys.stderr) | |
sys.exit(1) | |
if len(sys.argv) >= 3: | |
clients = int(sys.argv[2]) | |
if clients > 26: | |
print("Error: can only have up to 26 clients") | |
sys.exit(1) | |
else: | |
clients = 3 | |
procs = [subprocess.Popen([sys.executable, 'server.py', port, '(server)', str(clients)])] | |
time.sleep(1) # Give the server a moment to start | |
procs.extend(subprocess.Popen([sys.executable, 'client.py', port, '(client {})'.format(i)]) | |
for i in range(clients)) | |
for proc in procs: | |
proc.wait() # Note: this will never finish, as the server runs forever |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import socket | |
from shared import CONNECT, IP, PORT, BUFFER_SIZE, print | |
def receive_udp_msg(destination): | |
msg, origin = destination.recvfrom(BUFFER_SIZE) # receiving message OK | |
# This is the message sent as confirmation but is never received | |
destination.sendto("CHECK".encode('utf8'), origin) # sent but not received | |
msg = msg.decode() | |
return msg | |
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
s = (IP, PORT) | |
# Connecting to the server | |
c.sendto(CONNECT.encode('utf8'), s) | |
cport = receive_udp_msg(c) | |
print("Client done") | |
c.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import socket | |
import threading | |
from threading import Thread | |
from shared import CONNECT, IP, PORT, BUFFER_SIZE, print, num_clients, name_client | |
n_cons = 0 | |
def send_udp_mgs(origin, destination, msg): | |
msg = str(msg).encode('utf8') | |
origin.sendto(msg, destination) # sending message | |
# I never receive confirmation | |
opt, _ = origin.recvfrom(BUFFER_SIZE) # Code stucks here | |
opt = opt.decode('utf8') | |
print(opt) | |
def client_thread (s, c): | |
print("Connection petition from", c) | |
global n_cons | |
cport = PORT + n_cons # (see below) | |
send_udp_mgs(s, c, cport) | |
## Log when client is done | |
print("Client thread complete") | |
return | |
## Does 'cport' imply that you plan to create a new port, _in sequential order_, for each client? | |
## Consider that | |
## (a) you can only have so many ports open, | |
## (b) another process many be using one of those ports, | |
## (c) unless n_cons never goes down, _this process_ will be using those ports, | |
## (d) what do you need that many ports for? | |
## See also https://stackoverflow.com/a/11129641 | |
# UDP socket acting as server | |
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
s.bind((IP, PORT)) | |
i = -1 ## Loop index | |
while True: | |
i += 1 | |
data, addr = s.recvfrom(BUFFER_SIZE) | |
if data.decode() == CONNECT: | |
n_cons += 1 | |
try: | |
Thread(target=client_thread, args=(s,), kwargs={'c':addr}, | |
name=name_client(i)).start() | |
except: | |
print("Error creating thread") | |
break | |
## Log when other messages arrive, too | |
else: | |
print("Connect listener got {} from {}".format(data, addr)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment