Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can the server use the same socket to send the response to the client? how?

I am using Berkeley sockets (both: Internet domain and Unix domain) and I was wondering if the server can use the same sockets for reading the request and writing a response to the client. Or should the client create an other socket to wait for the replay and the server connect to it after processing the message received.

By the way, I am talking about connection oriented sockets (stream sockets, TCP, ...).

This is the simplified server code (I ommit error checking on system calls here just for simplicity):

int main() {

    int server_socket, connected_socket;
    struct sockaddr_in server_addr;
    char buf[1024];
    char aux[256];
    int bytes_read;

    server_socket = socket(AF_INET, SOCK_STREAM, 0);    

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(1234);
    bind(server_socket, &server_addr, sizeof(server_addr))

    listen(server_socket, 5)

    connected_sodket = accept(server_socket, 0, 0);
    do {
        bzero(buf, sizeof(buf));
        bytes_read = read(connected_socket, buf, sizeof(buf));        
    } while (bytes_read > 0);          

    /* Here I want to use connected_socket to write the reply, can I? */

    close(connected_socket);       

    close(server_socket);

    return (EXIT_SUCCESS);
}

And this is the simplified client code (I ommit error checking on system calls here just for simplicity):

int main() {

    int client_socket;
    struct sockaddr_in server_addr;

    client_socket = socket(AF_INET, SOCK_STREAM, 0);

    hp = gethostbyname("myhost");
    server_addr.sin_family = AF_INET;
    memcpy(&server_addr.sin_addr, hp->h_addr_list[0], hp->h_length);
    server_addr.sin_port = htons(1234);

    connect(client_socket, &server_addr, sizeof(server_addr));

    write(client_socket, MSG, sizeof(MSG));

    /* Here I want to wait for a response from the server using client_socket, can I? */

    close(client_socket);

    return (EXIT_SUCCESS);
}

Can I use connected_socket in the server and client_socket in the client to pass a response message back? Or should I use the client address I get in the server when in "accept" to connect to a socket in the client?

I have tried by using read/wrint in the client/server where the comment is shown but that way both programs keep blocked, it seems to be a dead-lock.

Thanks ins advance! Regards.

like image 361
mmutilva Avatar asked Jan 21 '09 22:01

mmutilva


People also ask

Can multiple clients connect to same server socket?

A socket that has been established as a server can accept connection requests from multiple clients. The server's original socket does not become part of the connection; instead, accept makes a new socket which participates in the connection.

Can multiple processes use the same socket?

Then both processes could use the same socket, just like two threads of a multithreaded program do. Open files are not per-process objects; any file can be shared between multiple processes.

Can a socket be both server and client?

For a server, you usually create a socket, then bind it to a specific port, and accept connections. For the client, you create a socket, and connect to a specified address (an IP address and port pair for a TCP/IP connection). The same device can run a TCP server and client at the same time.

Can a socket send and receive at the same time?

You can send and receive on the same socket at the same time (via multiple threads). But the send and receive may not actually occur simultaneously, since one operation may block the other from starting until it's done. That is how it's in Winsock.


2 Answers

You should use the same socket!

Your application protocol defines unambiguously when the client and the server should wait for data or send messages to each other; assuming a protocol with only one request from the client and one response from the server, the following should hold:


  • The client establishes a connection with the server;
  • the client sends its request (with send());
  • the client knows, by virtue of the protocol, that the server will reply; therefore it waits for data on the same socket (recv());
  • after validating the response, the client can close the socket.

  • The server accepts a connection from the client;
  • the server knows that the first step is up to the client, hence it waits for data (recv());
  • the server validates the request;
  • the server now knows, from the protocol, that the client is waiting for data; hence it sends its response with send();
  • the server knows, from the protocol, that there are no further steps; hence it can close the socket.
like image 197
Federico A. Ramponi Avatar answered Oct 03 '22 01:10

Federico A. Ramponi


You can use the same socket BUT your program is set up to have the server read EVERYTHING the client sends before attempting to reply. So the loop in the server won't complete until the client closes the write side of its socket so the server gets an EOF (0 bytes read), and thus the server will never send back its response.

There are a couple of ways you can deal with this.

  1. You can break the loop in the server after its seen the whole request, rather than reading until EOF. This requires that the data sent by the client be self-delimiting somehow, so the server can know when its read it all.
  2. You can use a second connection for the reply. Probably not the best.
  3. You can use asymmetric shutdown of the socket. Have the client do shutdown(client_socket, SHUT_WR) to half-close the socket. The server will then see the EOF (and the loop will finish), but the other direction on the socket will still be open for the reply.
like image 26
Chris Dodd Avatar answered Oct 03 '22 00:10

Chris Dodd