Socket module causing BGE to freeze

hi, long story, but i am trying to use one computer to control another in BGE

basic idea is that i want to have someone hit the spacebar on computer 1 and it starts a top spinning on computer 2, and then makes it spin faster and faster with every press of the spacebar

problem is that the code on computer 2 (the top) causes it to freeze every time i hit ‘p’ to start BGE

it freezes both on windows and mac os x, so i’m pretty sure i’m doing something that python doesn’t like
(this is a real freeze - it’s not like waiting for something to happen and nothing’s happening - on mac, i quickly get the spinning pinwheel of death - on windows, i immediately get the grayed-out screen with ‘not responding’)

so, here’s the code on computer 2 (the top):


import bge
import socket

cont = bge.logic.getCurrentController()
own = cont.owner
spin = cont.actuators[“spin”]
spin.useLocalAngV = True

host = ‘’ # that is two single quotes, by the way, not one double quote
port = 50001
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(1)
spinSpeed = 0

while 1:
client, address = s.accept()
data = client.recv(size)
if data == “spaceBar”:
spinSpeed = spinSpeed + 1
spin.angV = [0, 0, spinSpeed]
cont.activate(spin)


although i don’t think it matters, just in case, here is the code on computer 1 (the computer where you press the spacebar):


import bge
import socket

cont = bge.logic.getCurrentController()
own = cont.owner
hitSpacebar = cont.sensors[“spaceBar”] # this is a spacebar-triggered sensor brick attached to the python controller

host = ‘localHost’
port = 50001
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))

if hitSpacebar.positive:
s.send(“spaceBar”)


any thoughts why computer 2 is always freezing when i hit ‘p’?

if it helps, i have found that it does not freeze when i delete the s.listen(1) line, but it doesn’t work either, i just get this error:

Python script error - object ‘Top’, controller ‘Python’:
Traceback (most recent call last):
File “spin.py”, line 73, in <module>
File “/Applications/Blender/blender.app/Contents/MacOS/2.70/python/lib/python3.3/socket.py”, line 135, in accept
fd, addr = self._accept()
OSError: [Errno 22] Invalid argument

Please use [noparse]


[/noparse] tags.

To help you on your problem: read your code again. Then read it sgain and read it … Again … until 1 is not 1 anymore.

You need a timeout. If I remember correctly, it gets locked in a while loop somewhere in the socket library. And so without a timeout it will “lock up” blender. I think the function that you need is something along the lines of socket.timout() or socket.setTimeout()


while 1: 
   client, address = s.accept() 
   data = client.recv(size) 
   if data == "spaceBar":
     spinSpeed = spinSpeed + 1
    spin.angV = [0, 0, spinSpeed]
    cont.activate(spin) 

How do you escape the while loop?
The game waits for you to exit the script.

Scripts run inside a single frame, so ports need to be non-blocking and infinote loops aren’t what you want.

Use asyncio


help(__import__("asyncio"))

thanks. i haven’t tried asyncio yet, but i have modified the code as follows to get rid of the ‘while 1’ loop and to use non-blocking —


import bge
import socket
cont = bge.logic.getCurrentController()
own = cont.owner
spin = cont.actuators["spin"] 
spin.useLocalAngV = True

host = '' # that is two single quotes, by the way, not one double quote
port = 50001  
size = 1024 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind((host,port)) 
s.listen(1)
s.settimeout(0) # this ensures non-blocking

spinSpeed = 0

client, address = s.accept() 
data = client.recv(size) 
if data == "spaceBar":
        spinSpeed = spinSpeed + 1
        spin.angV = [0, 0, spinSpeed]
        cont.activate(spin)

so, i run this and hooray, it doesn’t freeze, but . . . i keep getting this error:


Python script error - object 'Top', controller 'Python':
Traceback (most recent call last):
  File "spin.py", line 73, in &lt;module&gt;
  File "/Applications/Blender/blender.app/Contents/MacOS/2.71/python/lib/python3.4/socket.py", line 184, in accept
    fd, addr = self._accept()
BlockingIOError: [Errno 35] Resource temporarily unavailable

any thoughts on ‘resource temporarily unavailable’? thanks.

You’ve got two things holding up your script. The most obvious is the while loop since it’ll never finish. The second being the .accept call:
client, address = s.accept()
This will block the script until you get an incoming connection, which keep Blender frozen too.

I would suggest initializing the socket (‘s’) into a GameLogic variable (maybe GameLogic.socket). Then, create a function with your while loop and spawn it into a new thread. This function will take any network input and append it to a different GameLogic variable (something like GameLogic.socket_input). Then have a pulsing script that’ll check that GameLogic variable and do things if it finds any data.

[moderation]reopened for further contribution.

Please be aware this thread is originated from 2014!

Thanks monster. I believe I have a solution to the second problem - this error:

Python script error - object 'Top', controller 'Python':
Traceback (most recent call last):
  File "spin.py", line 73, in &lt;module&gt;
  File "/Applications/Blender/blender.app/Contents/MacOS/2.71/python/lib/python3.4/socket.py", line 184, in accept
    fd, addr = self._accept()
BlockingIOError: [Errno 35] Resource temporarily unavailable

Can be resolved by making the socket async (either using .settimeout(0), as theOtherHolmes did, or using .setblocking(0)), wrapping your .listen() in a try-except, and appending each new connection to a list like so:

try:
    newconnection=s.accept()
    connections.append(newconnection)
except:
    pass

Then iterate over all connections later -

for i in connections:
    do something for each player...

or something similar.

I also found when testing this that sometimes, when running two tests, one right after the other, the port I was using would still be allocated to the previous instance of the program, and I had to wait ~10sec for the OS to free it up again. I would get an error “Address already allocated” or something. To fix this, call .shutdown() on the port before the program closes.

You should avoid using a bare except clause, as you will catch potentially unintended errors.