Link to home
Start Free TrialLog in
Avatar of James Hancock
James HancockFlag for United States of America

asked on

python - Why is my first crack at this datagram server a flop?

Hi
Many of you know about my server woes.
I have Python ready to go on my machines now to do this properly, but in Python.

I can get simple stuff to work, but not the class infrastructure for my Server class.
What I have so far has "unexpected indents," and I can't see where. Does my program begin at the end ( like a main?)
    import threading

    class Server(Threading.Thread):
        def_init_(self, numclients):
            print('Server constructor: ')
            self.numClients=numclients
            print(numClients)
            print(' clients')

        def run(self):
            print('Server run()')


    serverThread=Server(2)

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of gelonida
gelonida
Flag of France image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of James Hancock

ASKER

Thanks

I made the changes, but now the error is

"Invalid syntax"

What is wrong?
How can Python be considered a cutting edge language, if it doesn't have a debugger?

My new code is :
import threading

class Server(Threading.Thread):
    def_init_(self, numclients):
        print('Server constructor: ')
        self.numClients=numclients
        print(numClients)
        print(' clients')
        
    def run(self):
        print('Server run()')

    


serverThread=Server(2)
srverThraad.start()

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks, I've put the Shell error messages in this code block below
>>> ================================ RESTART ================================
>>> 
Server constructor: 
2
 clients
Traceback (most recent call last):
  File "/Users/jameshancock/Desktop/deep red wars/DRWpython/Server.py", line 17, in <module>
    serverThread.start()
AttributeError: 'Server' object has no attribute '_initialized'

Open in new window


must I specify that  "_initialized" attribute? Is that like a boolean?

start() is failing. It never enters the run area

Ideas?
Thanks

My present code is below   ( The space after 1: is not my space, it is a space that Expert Exchange puts into its text boxes after the line number)
import threading

class Server(threading.Thread):
    def __init__(self, numclients):
        print('Server constructor: ')
        self.numClients=numclients
        print(self.numClients)
        print(' clients')
        
    def run(self):
        print('Server run()')

    


serverThread=Server(2)
serverThread.start()

Open in new window

Again ;)
 ( The space after 1: is not my space, it is a space that Expert Exchange puts into its text boxes after the line number)
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Outstanding!

I also made an attempt at the Client, and again got syntax errors I don't know how to specify my server's IP address?

Can you see a problem? Are syntax errors a constant confounder in Python?
Thanks

import threading, socket

class Client(threading.Thread):
    def __init__(self, serveraddress, clientNumber):
        
        threading.Thread.__init__(self)  #  call parent class __init__

        serverAddress=serveraddress

        clientNumber=clientnumber

        host=serveraddress
        port=8081

    def run(self):
       print('Client constructor client # ', clientNumber)

       s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
       s.bind(("",0))
       sendto((  ?? , (host,port))  #how do I specify my server's address?




clientThread=Client(("192.168.1.113",port),0)
clientThread.start()
                         
                         
    


        


        


        

        

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Are global variables declared in the init? if not, how?
Thanks
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Excellent, thanks

A client first needs to send a MSG_HELO to the server.
How do I construct this bytearray, to be an array of 512 or 1024 bytes?
so, data = will be this bytearray, sent, and the server will analyze it in a setup loop.
Then, client will wait for a message from the server that all clients have joined, and it will exit the setup loop and begin the in-game loop. setup messages can be small, but in-game messages from client to server can also be small, but game-state messages from server to clients must be big, say - 4096 bytes? Or if I only send positional deltas and new unit arrivals, it can be smaller.
Should I be sending the updated game state / deltas at regular intervals, like  a clock? (Thread)

Thanks
Outstanding, thanks

I have code working that
Server - a join loop that waits for HELO message from clients.
Client -  a start up message to the server is sent

I'd like to know if this is on the right track. - attached,
thanks
Have I left out anything that might be crucial in an RTS?

Note that the server will soon do an - "if all clients joined" - " do an in-game server-loop"
I havent considered structures that will house the game state.
The client will soon do its own "in-game" loop

I read that one professionally done network game is fully in Python, so I must shelve my hesitancy and apprehension in committing to Python for this project.
Aren't properly done network games - millions of lines of code?
Server.py
Client.py
Included are my server and client below. No In Game Loop has been done, just the join.
Is this on the right track?

Please check them out. Thanks

Server:
import threading, socket

class Server(threading.Thread):

    MSG_JOIN = 0
    
    def intToBytes(self, n):
        print ("_________intToBytes___________")
        b = bytearray([0, 0, 0, 0])   # init
        b[3] = n & 0xFF
        n >>= 8
        b[2] = n & 0xFF
        n >>= 8
        b[1] = n & 0xFF
        n >>= 8
        b[0] = n & 0xFF    
    
        # Return the result or as bytearray
        return b

    
    
    def bytesToInt(self, b, offset):
        n = (b[offset+0]<<24) + (b[offset+1]<<16) + (b[offset+2]<<8) + b[offset+3]
        return n



    
    def __init__(self, numclients):
        threading.Thread.__init__(self) # call parent class's __init__ 
        print('Server constructor: ')
        self.expectedClientCount=numclients
        print(self.expectedClientCount, " clients expected")
        

    
        
    def run(self):
        
        print('Server run() . . . client join:')

        
        B = self.intToBytes(15976) #test convert and print
       
        print(B[0])
        print(" . ")
        print(B[1])
        print(" . ")
        print(B[2])
        print(" . ")
        print(B[3])
        print(" . ")
        print(self.bytesToInt(B,0))

        clientJoinMode=True
        
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        port = 1024
        bufferSize = 1024
        s.bind(("", port))
        joinedClientCount=0

        
        while clientJoinMode :   # CLIENT JOIN LOOP 

            
            print ('JOIN waiting on port: ', port, ' ',joinedClientCount,' /  ', self.expectedClientCount,' joined')   
            data, addr = s.recvfrom(bufferSize)
            msgType=data[0]

            
            cliNumBA = self.intToBytes(0) #create holder for client number bytes
            cliNumBA[0]=data[1]
            cliNumBA[1]=data[2]
            cliNumBA[2]=data[3]
            cliNumBA[3]=data[4]
            cliNum = self.bytesToInt(cliNumBA,0)
            #if msgType = 0:
            print ('joinloop JOIN from address ', addr, ': ', "client - ",cliNum)
            joinedClientCount+=1
          
        


serverThread=Server(3)
serverThread.start()

Open in new window


Client:

import threading, socket

class Client(threading.Thread):

    serverIP = "x.y.z.q"  # put the server's IP address here


    
    def intToBytes(self, n):
        print ("_________intToBytes___________")
        b = bytearray([0, 0, 0, 0])   # init
        b[3] = n & 0xFF
        n >>= 8
        b[2] = n & 0xFF
        n >>= 8
        b[1] = n & 0xFF
        n >>= 8
        b[0] = n & 0xFF    
    
        # Return the result or as bytearray  
        return b

    
    
    def bytesToInt(self, b, offset):
        n = (b[offset+0]<<24) + (b[offset+1]<<16) + (b[offset+2]<<8) + b[offset+3]
        return n



    
    def __init__(self, clientnumber):
        threading.Thread.__init__(self) # call parent class's __init__ 
        print(' Client number ', clientnumber, ' Constructor:' )
        self.clientNumber=clientnumber
        
        

    
        
    def run(self):

        print('Client run() . . . client # ', self.clientNumber)

        
        
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
        bufferSize = 1024
        clientPort=1024+self.clientNumber
        serverPort = 1024
        sock.bind(("", clientPort))
        clientNumberBytesArray=self.intToBytes(self.clientNumber)
        
        sendBytes = bytearray(512) # create a byte[] holder for the JOIN message
        sendBytes[0]=0 #message type JOIN
        sendBytes[1]=clientNumberBytesArray[0]
        sendBytes[2]=clientNumberBytesArray[1]
        sendBytes[3]=clientNumberBytesArray[2]
        sendBytes[4]=clientNumberBytesArray[3]

        
         
        sock.sendto(sendBytes, (self.serverIP, serverPort))

        

        
       
          
        


clientThread0=Client(0)
clientThread0.start()

clientThread1=Client(1)
clientThread1.start()
clientThread2=Client(2)
clientThread2.start()

Open in new window

Hi,

I've decided to try and do this in Java again, as I am more comfortable in Java. - for a possible porting to Python down the road. My other question determined that Java is a better choice for an RTS. - than a scripting language.
It is going well and I'd like to ask a Java RTS question about clock management.
Does anyone have an objection to me closing this question at this point?
I'm thinking I'll accept Gelonida's answers above.