Reputation: 3120
Currently, I am trying to develop a server framework which passes messages from twitch to other machines on a local network. I have a class called server and below I have a rudimentary example which demonstrates the problem I am running into. The issue is that the twitch_socket
is being created twice and bound to the address/port. My expected result is that the socket would be shared between the child processes of the Server class. How can I modify the class, or even get rid of it entirely, so that the Processes would be able to share sockets between them?
import multiprocessing
import socket
import re
from BotPass import PASSWORD
def send_message(socketobj, message):
'Sends a str as bytes through socket'
message = message.encode()
socketobj.sendall(message)
def recv_message(socketobj):
'Receives a str as bytes though socket'
return socketobj.recv(2048).decode()
class Server:
'Handles receiving messages from twitch and directs messages from clients'
twitch_socket = socket.socket()
twitch_socket.connect(('irc.chat.twitch.tv', 6667))
send_message(twitch_socket, 'PASS %s\r\n' % (PASSWORD))
send_message(twitch_socket, 'NICK %s\r\n' % ('squid_coin_bot'))
send_message(twitch_socket, 'JOIN #jtv\r\n')
send_message(twitch_socket, 'CAP REQ :twitch.tv/commands\r\n')
server_socket = socket.socket()
server_socket.bind(('', 9999))
work_queue = multiprocessing.Queue()
#Queue of messages from twitch
worker_queue = multiprocessing.Queue()
#Queue of free client socket objects
result_queue = multiprocessing.Queue()
#Queue of what to send back to twitch
def start():
accept_process = multiprocessing.Process(target=Server.accept_connections)
# *This is most likely where the issue is occurring*
accept_process.daemon = True
accept_process.start()
def accept_connections():
''
Server.server_socket.listen(10)
while 1:
(clientsocket, clientaddr) = Server.server_socket.accept()
# What I believe I am referencing here is the server socket which is inherent to the Server class
if re.match(r'192\.168\.\d{1,3}\.\d{1,3}', clientaddr[0])\
or clientaddr[0] == '127.0.0.1':
Server.worker_queue.put(clientsocket)
else:
clientsocket.close()
Server.start()
input()
Output in Console:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 105, in spawn_main
exitcode = _main(fd)
File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 114, in _main
prepare(preparation_data)
File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 225, in prepare
_fixup_main_from_path(data['init_main_from_path'])
File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 277, in _fixup_main_from_path
run_name="__mp_main__")
File "C:\Program Files\Python36\lib\runpy.py", line 263, in run_path
pkg_name=pkg_name, script_name=fname)
File "C:\Program Files\Python36\lib\runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name)
File "C:\Program Files\Python36\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\twitch-market\server.py", line 18, in <module>
class Server:
File "C:\twitch-market\server.py", line 27, in Server
server_socket.bind(('', 9999))
OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
Upvotes: 0
Views: 322
Reputation: 4538
Add this socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
This is because the previous execution has left the socket in a TIME_WAIT
state, and can’t be immediately reused.the SO_REUSEADDR
flag tells the kernel to reuse a local socket in TIME_WAIT
state, without waiting for its natural timeout to expire.
Upvotes: 1