Problem with tcp communication in blender python

I am trying to run a Human Armature using the data which i receive from tcp communication.
This is my client side code :

import socket

a=0
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024
MESSAGE = b'1'
while(a<8):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((TCP_IP, TCP_PORT))
    s.send(MESSAGE)
    data = s.recv(BUFFER_SIZE)
    s.close()
    a=a+1
    print "received data:", data

and this my server side code which i’m running in blender python:


import socket
import GameLogic
from math import radians as r
arm=GameLogic.getCurrentController().owner

x=0
arm.channels['Upperarm.Right'].rotation_mode=1
TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 20 # Normally 1024, but we want fast response

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)



while 1:
    print ('waiting for a connection')
    conn, addr = s.accept()
    try:
        print ('Client coinnected:', addr)
        def main():
            while True:
                data = conn.recv(BUFFER_SIZE)
                if data:                
                    print ("received data:", data)
                    if (data == b'1'):
                        x = x+10
                        arm.channels['Upperarm.Right'].rotation_euler=[-r(x),r(26.639),r(0.576)]
                        arm.update() 
                    elif (data == b'2'):
                        x= x-10   
                        arm.channels['Upperarm.Right'].rotation_euler=[-r(x),r(26.639),r(0.576)]
                        arm.update()                   
                    else :
                        continue 
                else :
                    break
    finally:
        print('client disconnected:',addr)
        conn.close()
        break



i’m running the module main() in the python controller

But i’m getting errors like

 
Traceback (most recent call last):
File "/home/jayakrishna/tcp1.py", line 26, in main
    data = conn.recv(BUFFER_SIZE)
OSError: [Errno 9] Bad file descriptor


in the server side.

also on the client side :

Traceback (most recent call last):
  File "/home/jayakrishna/spam.py", line 12, in <module>
    data = s.recv(BUFFER_SIZE)
error: [Errno 104] Connection reset by peer

plz help me out!:frowning:

At the first look this has great potential for a lock. There are way to many potential endless loops in there. Lucky you it did not want to connect.

The second look shows that your client is closing the connection after receiving some data.

You define an nested function main() [what is it supposed to do?] I might miss something but it seems it is not called anywhere.

To be brief and clear my aim is to rotate the arm by +10degrees if i receive b’1’ from the client and if i receive b’2’ i want it to rotate -10 degrees. And that is what i wanted to do in main() function.

This does not help you with your current problem, but I strongly recommend to separate communication code from “business” code.

Separate concerns
This way you can focus on one of the aspects. Just now you want to focus on communication. So this separation can support you with your issue.

Refactoring your code it could look like this:


...
...

while 1:
    print ('waiting for a connection')
    conn, addr = s.accept()
    try:
        print ('Client coinnected:', addr)
        def main():
            while True:
                data = conn.recv(BUFFER_SIZE)
                if data:                
                    doMyBusiness(data)
                else :
                    break
    finally:
        print('client disconnected:',addr)
        conn.close()
        break

The extracted business code can look like this:


def doMyBusiness(data):
	print ("received data:", data)
	if (data == b'1'):
	    x = x+10
	    arm.channels['Upperarm.Right'].rotation_euler=[-r(x),r(26.639),r(0.576)]
	    arm.update() 
	elif (data == b'2'):
	    x= x-10   
	    arm.channels['Upperarm.Right'].rotation_euler=[-r(x),r(26.639),r(0.576)]
	    arm.update()                   
	else :
	    continue       

Or in case you just want to print the received data:


def doMyBusiness(data):
	print ("received data:", data)

Defining a function
Now back to your “def main()”.
This statement defines a function (that’s why it is abbreviated with “def”). It does not run the function.

To run the function you have to explicitly call it (the function needs to be known at that time).

Naming a function
While others think “main” is very obvious in the meaning, I strongly suggest to give it a meaningful name. In this case it is supposed to receive data from a connection and forward it to business layer. I think “processIncommingData(connection)” would be a sufficient name. You can choose whatever you like.

the code can now look like this:


...
while 1:
    print ('waiting for a connection')
    connection, addr = s.accept()
    try:
        print ('Client coinnected:', addr)
        def processIncommingData(connection):
     finally:
        print('client disconnected:',addr)
        conn.close()
        break

You see it is much smaller and less confusing.

You need an implementation of the called function too:


def processIncommingData(connection):
    while True:
        data = connection.recv(BUFFER_SIZE)
        if data:                
            doMyBusiness(data)
        else:
            return

Complexity
But you do not even need this function. I mean it is good to have it as it makes the outside and inside code less complex (I hope you see it above). Unfortunately the original code used it as nested function, which increases
complexity. So either do not have this function at all or place it somewhere else.

Communication protocol
Now back to your problem.

Your server is not sending data, but the client expects some. Your server suddenly closes the connection (exactly what the error is saying). This means they do not follow the same protocol (send/receive/send/receive/…).

The good news is, that it looks like the data was successfully send by the client. As explained in the other post, your code is not doing anything with it, it just closes the connection.

Endless loop
As said in the other post, if you code would not disconnect after the first transition, it would be captured in endless loops until you kill the communication (e.g by killing one participating process).

Thank you very much sir…it was an awesome description from you!

surely helps me alot! :slight_smile:

TCP/IP programming in general can be tricky because there is so much that can go wrong when you try to send data over a network connection. An extra problem is that when you use it with the BGE, you have to make sure that your network code works with the BGE game loop correctly so that it does not freeze the BGE.

Check out the attached ZIP file. It shows one way to setup TCP/IP communication between a client/server and process the data in non-blocking mode. The code was designed to be as minimal as possible while still showing how to get non-blocking communication to work and having a server that supports multiple clients connected at the same time.

bgeServer.zip (68.1 KB)

Hello! Why don’t you use UDP protocol? It’s faster:

http://wiki.labomedia.org/index.php/Communication_en_UDP_entre_un_script_python_et_Blender_Game_Engine#Script_python_2.6_Server