1

I am trying to build a sample TCP Forwarder. Here is the functionality in brief:

  1. The forwarder will listen at a given port.
  2. It contains a map of clients to servers
  3. Clients will connect to the forwarder and the forwarder will lookup the map and create a 2-way-forwarding-connection.
  4. To achieve this, it creates two threads per client.
  5. Thread 1: reads from the client and writes to the target server
  6. Thread 2: reads from the target server and write to the client.

All this is written in C. The Client and Target servers can be written in any language, right now its Java.

When I run a client for the first time, it works as expected. However, if I kill the client and restart it, the server never receives the new connection.

Here is my server code which I suspect is fault.

Socket clientSocket = serverSocket.accept();
InputStream inputStream = clientSocket.getInputStream();
OutputStream outputStream = clientSocket.getOutputStream();

while (true) {
    byte[] bArray = new byte[2048];
    try {
        System.out.println(String.format("SERVER:%s: Attempting to read", this.name));
        inputStream.read(bArray);
        System.out.println(String.format("SERVER:%s: Received %s", this.name, new String(bArray)));
        byte[] bytes = (name + ":" + counter).getBytes();
        counter++;
        outputStream.write(bytes);
        System.out.println(String.format("SERVER:%s: Sent %s", this.name, new String(bytes)));
    } catch (IOException e) {
        System.out.println(String.format("SERVER:%s: Client Disconnected ", this.name));
        clientSocket = serverSocket.accept();
        inputStream = clientSocket.getInputStream();
    }
}

In the C program, I detect the disconnection and close the socket as shown below:

LOGINFO("Reading from Client Socket.");
iResult = read(readSocket, buff, recvbuflen);
if (iResult <= 0) {
    LOGERROR("Receiving failed");
    close(readSocket);          
    break;
}
dharam
  • 7,882
  • 15
  • 65
  • 93
  • Possible duplicate of [Knowing How to Detect a Disconnection when Reading Socket Data (InputStream)](https://stackoverflow.com/questions/11909336/knowing-how-to-detect-a-disconnection-when-reading-socket-data-inputstream) – Steffen Ullrich May 09 '18 at 13:11
  • how is your `serverSocket` and `readSocket` configured? – Ruslan Akhundov May 09 '18 at 13:13

2 Answers2

1

Try to modify your server logic by using concurrency to manage each request. In this way, server will be able to handle each client separately in a thread. Reading and writing data must be performed in the related thread. A pool thread paradigm is often used to avoid thread overhead[1].

For example:

ExecutorService threadPool = Executors.newFixedThreadPool(n);
ServerSocket serverSocket = null;

//...

while(!isStopped()){
   Socket clientSocket = null;
   try {
       clientSocket = this.serverSocket.accept();
       threadPool.execute(new WorkerRunnable(clientSocket));
       // Process data in the WorkerRunnable class
   } catch (IOException e) {
       if(isStopped()) {
           System.err.println("Server Stopped.") ;
           break;
       }
       throw new RuntimeException("Error accepting client connection", e);
   } 
}

A well designed example can be found here: http://tutorials.jenkov.com/java-multithreaded-servers/thread-pooled-server.html

Gaulthier
  • 320
  • 7
  • 16
  • but it doesn't solve initial problem with reconnection. if you have a requirement, that you always have just one connection, its completely ok to do it in the same thread. – Ruslan Akhundov May 09 '18 at 14:20
1

You should use

   shutdown(socket_fd, SHUT_WR);

instead of close(socket_fd) in order to properly close socket.

If you use SHUT_WR, a FIN packet will be sent to another side to inform them we don't have more data to send.

Ruslan Akhundov
  • 2,178
  • 4
  • 20
  • 38