I'm attempting to write a game server and I need it to continue on with the code while listening for a connection. I know this is done with the threading module but I don't know how exactly to do this. Python documentation didn't work for me.

#[LISTENER]
    print "Initializing Listener..."
    Listener.Listen(server_ip, int(server_port))

    #(AFTER LISTENER HAS STARTED WAITING FOR A CONNECTION)
    os.system("cls")

    print "Server IP: %s"  % server_ip + ":" + server_port
    print "Level Name: %s" % level_name
    print "Public IP: %s"  % public_ip
    print "-------------------------------------------"

    os.system("pause")

Listener code

import os, socket
import Interpreter

class Listen:
    def __init__(self, server_ip, server_port):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind((socket.gethostname(), server_port))
        s.listen(5)

        while 1:
            (clientsocket, address) = s.accept()
            if clientsocket and address:
                Interpreter.newConnection(clientsocket, address)

Dani AI

Generated

Your listener is blocking because accept() stops the thread until a client arrives. The simplest fix is to run the accept loop in another thread (so the main thread can continue with the prints and os.system("pause")). Also note a bug in the original post: you call Listener.Listen(server_ip, port) but inside the listener code you bind to socket.gethostname() — bind to the server_ip you pass (or '' to listen on all interfaces).

's decorator is a neat shorthand for "run this function in a thread", and correctly explained that the @ syntax is a decorator and wraps preserves metadata. If you want explicit control (start/stop, join, graceful shutdown) use a dedicated Thread + Event and a Queue to hand new sockets back to the main thread (safer than calling into shared interpreter state from an accept thread).

Example pattern (works for Python 2/3 with small compatibility imports):

import socket, threading
try:
    import Queue as queue
except ImportError:
    import queue

def accept_loop(host, port, conn_q, stop_evt):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((host, int(port)))
    s.listen(5)
    s.settimeout(1.0)
    try:
        while not stop_evt.is_set():
            try:
                client, addr = s.accept()
            except socket.timeout:
                continue
            conn_q.put((client, addr))
    finally:
        s.close()

conn_q = queue.Queue()
stop_evt = threading.Event()
t = threading.Thread(target=accept_loop, args=(server_ip, server_port, conn_q, stop_evt))
t.setDaemon(True)  # or t.daemon = True
t.start()

# main thread continues: display UI, then process conn_q when ready

Notes and cautions: ensure server_port is an int, cleanly set the stop event and join() the thread on shutdown, and avoid touching shared interpreter state from multiple threads without locks. For many clients consider a worker pool (ThreadPoolExecutor or a queue + fixed worker threads) or use the standard library's ThreadingTCPServer for per-connection threads. raw_input() / os.system("pause") will block the main thread, so they don't solve the original problem.

Recommended Answers

All 5 Replies

try raw_input()?

Maybe this thread has a bad name lol...
While the server is listening for a connection it needs to continue on with the code.

#[LISTENER]
    print "Initializing Listener..."
    Listener.Listen(server_ip, int(server_port))

    #[Run this code after Listener is waiting for a connection] 
    os.system("cls")

    print "Server IP: %s"  % server_ip + ":" + server_port
    print "Level Name: %s" % level_name
    print "Public IP: %s"  % public_ip
    print "-------------------------------------------"

    os.system("pause")

But it will never get to that part after calling the Listener, because it is stuck in a while loop listening for connections.

You can run the listening function on an asynchronized thread.

from functools import wraps
from threading import Thread

def async(func):
    @wraps(func)
    def async_func(*args, **kwargs):
        func_handler = Thread(target=func, args=args, kwargs=kwargs)
        func_handler.start()
        return func_handler
    return async_func

@async
def listener():
    print "Initializing Listener..."
    Listener.Listen(server_ip, int(server_port))

os.system("cls")

print "Server IP: %s"  % server_ip + ":" + server_port
print "Level Name: %s" % level_name
print "Public IP: %s"  % public_ip
print "-------------------------------------------"

os.system("pause")

Cheers and Happy coding

I had given up on this now I'm trying again.
Your code works fine, but could someone please explain the code to me?

def async(func):
    @wraps(func)  #Purpose of this? @ sign?
    def async_func(*args, **kwargs):
        func_handler = Thread(target=func, args=args, kwargs=kwargs)
        func_handler.start()
        return func_handler
    return async_func

@async #And this? What does the @ sign mean?
def listener():
    print "Initializing Listener..."
    Listener.Listen(server_ip, int(server_port))

The @ symbol is syntax indicating a decorator. In this instance, the decorator takes the function it decorates (a.k.a. wraps) and makes a new function that starts the old function in a new thread. A normal decorator will not preserve the name and docstring of the old function, but @wraps will preserve that information in the new function.

Once the async decorator has been defined, you can decorate any function with it to have that function start in a new thread when called.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.