0

I am trying to send and receive data using TCP connection using Python. My server and client are in the same file, defined and used as follows.

In the constructor, I define the server as:

self.sock_in = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock_in.bind((self.host_ip, self.host_port))
self.sock_in.listen(1)

Do not worry about the host_ip and host_port variables, they are all fine.

In a function, I am trying to send data as follows:

 sock_out = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP Connection
 sock_out.connect((self.remote_ip, self.remote_port))
 sock_out.send(self.navigation_data.get_message())
 sock_out.close()

And this is my main:

def main(self):
    rospy.logwarn("Starting...")
    while not rospy.is_shutdown():
        conn = self.sock_in.accept()
        try:
            recv_buffer = conn.recv(BUFFERSIZE_IN)
            if recv_buffer != "":
                msg = recv_buffer.decode('utf-8')
                msg_type = msg[:msg.find(',')]
                if msg_type == self.pilot_control.MESSAGE_ID:
                    self.pilot_control_handler(msg, self.pilot_control_publisher)
                else:
                    rospy.logwarn("Received an unimplemented message type '%s'", msg_type)
        except socket.error as socket_error:
            rospy.logerr("SocketError: %s", str(socket_error))

And the error I get is:

 line 230, in send_83b_package
        sock_out.connect((self.remote_ip, self.remote_port))
      File "/usr/lib/python2.7/socket.py", line 224, in meth
        return getattr(self._sock,name)(*args)
    error: [Errno 111] Connection refused

I put some print commands to see where it collapses, and apparently it does not run the accept command. Until there I can see the print commands working, but after the accept method nothing is printed, which means it collapses there.

I suspect the problem is about synchronization. That is, the server does not start fast enough.

Any thoughts?

EDIT: One of the suggestions was to run the server on a separate thread, which I tried as follows:

def my_tcp_server(self):

        # Establish a TCP Connection
        self.sock_in = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock_in.bind((self.host_ip, self.host_port))
        self.sock_in.listen(1)
        rospy.logwarn("ready")

        while not rospy.is_shutdown():
            rospy.logwarn("before accept")
            conn, address = self.sock_in.accept()
            rospy.logwarn("after accept")
            try:
                recv_buffer = conn.recv(BUFFERSIZE_IN)
                rospy.logwarn("recv works!")
                if recv_buffer != "":
                    msg = recv_buffer.decode('utf-8')
                    msg_type = msg[:msg.find(',')]
                    if msg_type == self.pilot_control.MESSAGE_ID:
                        self.pilot_control_handler(msg, self.pilot_control_publisher)
                    else:
                        rospy.logwarn("Received an unimplemented message type '%s'", msg_type)
            except socket.error as socket_error:
                rospy.logerr("SocketError: %s", str(socket_error))
        conn.close()    

def main(self):
            rospy.logwarn("Starting..")
            threading.Thread(target=self.my_tcp_server).start()

And in my constructor, the order of calls are as follows:

self.main()
self.sendDataFunction()

Which should be okay. However, the accept function is still not working, hence there is no connection.

  • Are you sure it's even getting into the `while` block? Try stepping through the code with `pdb`. – Cyphase Aug 17 '15 at 10:26
  • 1
    If your client and server are in the same file, unless you're using threading/multiprocessing it isn't going to work because your python script can only be doing one thing at a time - when it tries to connect, the script is doing the connect, i.e. it can't do the accept, so the connection is refused. To fix it, put the server code in its own thread. – DisappointedByUnaccountableMod Aug 17 '15 at 10:33
  • @Cyphase Yes it does go into the while block, I put a print there. It prints only once though, then it collapses, which means accept method is causing a problem which prevents the program running. –  Aug 17 '15 at 10:41
  • @barny Thanks, couldn't we put an if-else connection to make it wait until it starts? –  Aug 17 '15 at 10:42
  • 1
    Err, no. You will have to make the client and server run in separate threads. See http://stackoverflow.com/questions/8020287/how-to-put-tcp-server-on-another-thread-in-python – DisappointedByUnaccountableMod Aug 17 '15 at 10:43
  • @barny The thing is, when I do it with UDP it works. Again both in the same file. However with TCP there is this problem which it always refuses to connect. –  Aug 17 '15 at 10:44
  • 1
    UDP is connectionless, so no problem with unthreaded. TCP requires the client and the server to synchronize, so both ends have to be 'running' python code at the same time, so each needs its own thread of execution. See the example I found in my previous comment. See the accepted answer for a simple example. – DisappointedByUnaccountableMod Aug 17 '15 at 10:48
  • @barny Oh, I see. Thanks, going to try that now. –  Aug 17 '15 at 10:49
  • It's the code example you should look at, not the stuff about creating a daemon. – DisappointedByUnaccountableMod Aug 17 '15 at 10:52
  • @barny I did as that user told but the accept function still is not working. Nothing is printed after accept, I mean this line `conn, address = self.sock_in.accept()`. I edited the question and put the latest code. –  Aug 17 '15 at 11:17

1 Answers1

1

As you didn't provide a complete executable code example I took your snippet and removed the class declaration aspects, added definitions for ip/port etc. Also added socket timeout. Anywayt this code works for me on Windows 7x64 with 32-bit Python 2.7.8:

import threading
import socket

is_shutdown = False
BUFFERSIZE_IN = 32768

def my_tcp_server():

    # Establish a TCP Connection
    sock_in = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock_in.bind((host_ip, host_port))
    sock_in.settimeout(10000)
    sock_in.listen(1)
    print "ready"

    while not is_shutdown:
        print "before accept"
        conn, address = sock_in.accept()
        print "after accept"
        try:
            recv_buffer = conn.recv(BUFFERSIZE_IN)
            print "recv works!"
            if recv_buffer != "":
                msg = recv_buffer.decode('utf-8')
                print "Received",msg
        except socket.error as socket_error:
            print  "SocketError: %s", str(socket_error)
        conn.close()    
    print "Shutting down server"
    sock_in.close()


def main():
    print "Starting.."
    threading.Thread(target=my_tcp_server).start()
def sendData():
    sock_out = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP Connection
    sock_out.connect((remote_ip, remote_port))
    sock_out.send("ASD")
    sock_out.close()

host_ip="127.0.0.1"
remote_ip = host_ip
host_port = 8073
remote_port = host_port

main()
print "Sending"
sendData()

print "Completed"
is_shutdown = True

The output is:

Starting..
Sending
ready
before accept
 Completedafter accept

recv works!
Received ASD
Shutting down server

I guess there is something in your class/constructor/something I can't see which is making your code not work.

HTH barny

  • Thanks. Yes, it was the order of the execution. Now it worked for me too. –  Aug 17 '15 at 13:46