Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
815 views
in Technique[技术] by (71.8m points)

multithreading - python multithreaded server

What I'm trying to program is a simple multithreaded python game server for fun. After much frustration, I've not been able to figure out why my test client connection times out. Here's my server.py code:

import socket
import threading
import clientThread
import struct
import string


class Server:
    def __init__(self):
        self.HOST = 'localhost'
        self.PORT = 22085
        self.BUFFIZE = 1024
        self.ADDRESS = (self.HOST,self.PORT)
        self.clientList = []
        input("Press enter to start the server. . .")
        self.running = True
        self.serverSock = socket.socket()
        self.serverSock.bind(self.ADDRESS)
        self.serverSock.listen(2)
        self.clientThread = clientThread.clientThread(self)
        print("Starting client thread. . .")
        self.clientThreadObj = threading.Thread(target = self.clientThread.start, args = (self))
        print("Awaiting connections. . .")
        while self.running:
            clientInfo = self.serverSock.accept()
            print("Client connected from %s." % clientInfo[1])
            # Append to clientThread list...

        self.serverSock.close()
        print("- end -")


serv = Server()

The server starts the thread for existing connections and starts listening. The thread built for existing connections, clientThread, loops through a list of client objects which for now do nothing, they are simply architectural. Here is the clientThread.py

import socket
import threading
import struct
import string


class clientThread:
    def __init__(self, serv):
        self.server = serv
        self.clientList = []
        self.running = True
        print("Client thread created. . .")
    def start(self):
        print("Beginning client thread loop. . .")
        while self.running:
            for client in self.clientList:
                message = client.sock.recv(self.server.BUFFSIZE)
                if message != None and message != "":
                    client.update(message)

And finally, the very simple client object:

import string


class clientObject:
    def start(self,clientInfo):
        self.sock = clientInfo[0]
        self.address = clientInfo[1]
    def update(self,message):
        self.sock.send("Testamundo.
".encode())

Now, the problem here is that my client can't even connect to my server. It simply times out. Here is the code for my simple client test:

import socket
import string

address = ("192.168.1.1",22085)
mySocket = socket.socket()

mySocket.connect(address)
print("Connected successfully!")

This returns on the line that connects to address, "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond."

Any suggestions? Thanks! Sorry for all this code, I wasn't sure if I needed to post it all or not, so I figured it couldn't hurt too much.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Do you have two systems? Does the server system have an IP of 192.168.1.1? If you only have one system, the localhost address is 127.0.0.1. That was the first change I had to make to your code to get a connection when running the server and client on the same system.

Another issue is your client thread doesn't actually start. Since you want a client thread class, here's how to declare and start it:

  1. Subclass from threading.Thread.
  2. Override __init__ for your behavior, but call __init__ in the base class first.
  3. Override run for the thread work.
  4. Create an instance and call its start method.

Another problem is recv blocks if the client hasn't sent any data, so if you try to connect multiple clients it will hang in your loop over the client list. You'll need a thread per client or use select.select to query the client sockets for read/write readiness.

Below is the changed code that got a single client to respond, but it needs work to handle multiple clients. It also needs to set up a protocol to handle messages. TCP is a streaming protocol (no message boundaries), so a send of 'abc' and '123' could result in a receive of 'abc123' or 'ab' and 'c123', etc. It'll have to handle closing the connections and remove the client objects from the client list as well.

Good luck! You'll learn a lot figuring out how to do all this from scratch. Look at the socketserver.py library as well for example code.

srv.py

import socket
import threading
import struct
import string

class clientThread(threading.Thread):
    def __init__(self, serv):
        threading.Thread.__init__(self)
        self.server = serv
        self.clientList = []
        self.running = True
        print("Client thread created. . .")
    def run(self):
        print("Beginning client thread loop. . .")
        while self.running:
            for client in self.clientList:
                message = client.sock.recv(self.server.BUFFSIZE)
                if message != None and message != "":
                    client.update(message)

class clientObject(object):
    def __init__(self,clientInfo):
        self.sock = clientInfo[0]
        self.address = clientInfo[1]
    def update(self,message):
        self.sock.send("Testamundo.
".encode())

class Server(object):
    def __init__(self):
        self.HOST = 'localhost'
        self.PORT = 22085
        self.BUFFSIZE = 1024
        self.ADDRESS = (self.HOST,self.PORT)
        self.clientList = []
        input("Press enter to start the server. . .")
        self.running = True
        self.serverSock = socket.socket()
        self.serverSock.bind(self.ADDRESS)
        self.serverSock.listen(2)
        self.clientThread = clientThread(self)
        print("Starting client thread. . .")
        self.clientThread.start()
        print("Awaiting connections. . .")
        while self.running:
            clientInfo = self.serverSock.accept()
            print("Client connected from {}.".format(clientInfo[1]))
            self.clientThread.clientList.append(clientObject(clientInfo))

        self.serverSock.close()
        print("- end -")

serv = Server()

clnt.py

import socket
import string

address = ('localhost',22085)
mySocket = socket.socket()

mySocket.connect(address)
print("Connected successfully!")
mySocket.send('blah'.encode())
print(mySocket.recv(1024))

Output (srv.py)

Press enter to start the server. . .
Client thread created. . .
Starting client thread. . .
Beginning client thread loop. . .
Awaiting connections. . .
Client connected from ('127.0.0.1', 52850).

Output (clnt.py)

Connected successfully!
b'Testamundo.
'

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...