back-and-forth unix domain sockets lock
Question: I am writing two programs one in c++ and the other in Python to communicate
with each other using unix domain sockets. What I am trying to do is have c++
code send a number to the python code, which in turn send another number back
to c++. This goes on till c++ code runs out of numbers to send and the
execution stops. Below are my codes. I can't seem to run them past the first
iteration of the loop.

I run Python first:  
_python code.py /tmp/1 /tmp/2_

Then I run the c++ code:  
_./code /tmp/1 /tmp/2_  

Here is the output:

## C++ output:

sent 0  
Listening  
Connection successful  
received 5  
sent 1  
Listening  

  
  

## Python output:

listening ...  
received (0,)  
>5  
sent 5  
listening ...  

## C++ Code:

    
    
    static int connFd;
    
    int main(int argc, char* argv[])
    {
    
       int recv_sock, 
       send_sock;
    
       struct sockaddr_un server, client;
    
       ///////////////////////////////////////////
       //                                       
       // setup send             
       //                                       
       ///////////////////////////////////////////
    
       /* Create socket on which to send. */
       send_sock = socket(AF_UNIX, SOCK_STREAM, 0);
       if (send_sock < 0) 
       {
         perror("opening unix socket");
         exit(1);
       }
    
       /* Construct name of socket to send to. */
       client.sun_family = AF_UNIX;
    
       strcpy(client.sun_path, argv[1]);
    
       if (connect(send_sock, (struct sockaddr *) &client, sizeof(struct sockaddr_un)) < 0) 
       {
         close(send_sock);   
         perror("connecting stream socket");
         exit(1);
       }
    
    
       ///////////////////////////////////////////
       //                                       
       // setup recv 
       //                                       
       ///////////////////////////////////////////
    
       recv_sock = socket(AF_UNIX, SOCK_STREAM, 0);
    
       if(recv_sock< 0)
       {
         cerr << "Cannot open socket" << endl;
         return 0;
       }
    
       bzero((char*) &server, sizeof(server));
    
       server.sun_family = AF_UNIX; 
       strcpy(server.sun_path,  argv[2]);
    
      //bind socket
      if(bind(recv_sock, (struct sockaddr *)&server, sizeof(server)) < 0)
      {
        cerr << "Cannot bind" << endl;
        return 0;
      }
    
      listen(recv_sock, 10);
    
      int X;
      for (int i = 0; i < 10; i++)
      {
        write(send_sock, &i, sizeof(i));
        cout << "sent " << i << endl;
        cout << "Listening" << endl;
        connFd = accept(recv_sock, 0, 0);
        if (connFd < 0)
        {
            cerr << "Cannot accept connection" << endl;
            return 0;
        }
        else
        {
           cout << "Connection successful" << endl;
           read(connFd, &X, sizeof(X));
           cout << "received " << X << endl;
        }
    
        usleep(2000000);
    
     }
    
    
     close(send_sock);
     close(recv_sock);
     unlink(argv[2]);
     unlink(argv[1]);
    
    
     return 0;
    
    }
    

## Python Code:

    
    
    import socket,os,struct, glob, sys
    import random
    
    send_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    recv_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    try:
        os.remove(sys.argv[1])
    except OSError:
        pass
    
    recv_socket.bind(sys.argv[1])
    
    
    
    recv_socket.listen(10)
    while 1:
       print "listening ..."
       conn, addr = recv_socket.accept()
       data = conn.recv(4)
    
    
       p = struct.unpack('i',data)
       print 'received ', p
    
       if p is '9':
          break
    
    
       l = int(raw_input(">"))
       a = struct.pack('i', l) 
       send_socket.connect(sys.argv[2])
       send_socket.sendall(a)
       print 'sent ', l
    
    send_socket.close()
    conn.close()
    recv_socket.close()
    

What am I doing wrong in this approach? Do I need to use threads?

Thanks


Answer: You handle differently the send and receive sockets in your C++ code: the send
socket is bound once at the start of the program whereas the receive socket
accepts a new connection at each iteration.

Your current Python implementation accepts a new connection on `recv_socket`
and connects `send_socket` at each iteration which explains the issue that you
are facing.

The most efficient fix would be to connect each socket once prior to the loop
unless you have a good reason to open a new connection at each iteration. Here
are the corresponding code listings:

# C++

    
    
    static int connFd;
    
    int main(int argc, char *argv[]) {
    
      int recv_sock, send_sock;
    
      struct sockaddr_un server, client;
    
      ///////////////////////////////////////////
      //
      // setup send
      //
      ///////////////////////////////////////////
    
      /* Create socket on which to send. */
      send_sock = socket(AF_UNIX, SOCK_STREAM, 0);
      if (send_sock < 0) {
        perror("opening unix socket");
        exit(1);
      }
    
      /* Construct name of socket to send to. */
      client.sun_family = AF_UNIX;
    
      strcpy(client.sun_path, argv[1]);
    
      if (connect(send_sock, (struct sockaddr *)&client,
                  sizeof(struct sockaddr_un)) < 0) {
        close(send_sock);
        perror("connecting stream socket");
        exit(1);
      }
    
      ///////////////////////////////////////////
      //
      // setup recv
      //
      ///////////////////////////////////////////
    
      recv_sock = socket(AF_UNIX, SOCK_STREAM, 0);
    
      if (recv_sock < 0) {
        cerr << "Cannot open socket" << endl;
        return 0;
      }
    
      bzero((char *)&server, sizeof(server));
    
      server.sun_family = AF_UNIX;
      strcpy(server.sun_path, argv[2]);
    
      // bind socket
      if (::bind(recv_sock, (struct sockaddr *)&server, sizeof(server)) < 0) {
        cerr << "Cannot bind" << endl;
        return 0;
      }
    
      listen(recv_sock, 10);
      connFd = accept(recv_sock, 0, 0);
      if (connFd < 0) {
        cerr << "Cannot accept connection" << endl;
        return 0;
      } else {
        cout << "Connection successful" << endl;
      }
    
      int X;
      for (int i = 0; i < 10; i++) {
        write(send_sock, &i, sizeof(i));
        cout << "sent " << i << endl;
        cout << "Listening" << endl;
        read(connFd, &X, sizeof(X));
        cout << "received " << X << endl;
        usleep(2000000);
      }
    
      close(send_sock);
      close(recv_sock);
      unlink(argv[2]);
      unlink(argv[1]);
    
      return 0;
    }
    

# Python

    
    
    recv_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    send_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    try:
        os.remove(sys.argv[1])
    except OSError:
        pass
    
    recv_socket.bind(sys.argv[1])
    
    recv_socket.listen(10)
    conn, addr = recv_socket.accept()
    
    send_socket.connect(sys.argv[2])
    
    while 1:
       print "listening ..."
       data = conn.recv(4)
       p = struct.unpack('i',data)
       print 'received ', p
    
       if p is '9':
          break
    
    
       l = int(raw_input(">"))
       a = struct.pack('i', l)
       send_socket.sendall(a)
       print 'sent ', l
    
    send_socket.close()
    conn.close()
    recv_socket.close()
    

