Hot questions for Using Transmission Control Protocol in exception

Question:

I have two problems with an app that i have built for socket communication, first I'll try to explain what the app does and then I'll go into the details of those two problems. First I click on a button, which starts a thread, which sends a multicast massage "group address" through a UDP socket. Once any of the devices receive the massage, they will send a response through TCP socket and my device will act as a server to the one that sent the response. So after debugging I found out the first problem which is clientSocket = serverSocket.accept(); sometimes gets stuck and the app will block everything and keep executing it, which might happen because the udp massage might never arrive at the destination which means there is no client for the tcp server that I've created.

First question: Is there any way to make the serverSocket.accept(); non-blocking or set a time out? I've tried serverSocket.setTimeSoOut() method, but that didn't work. Maybe this problem comes from something other than the UDP message?

The second problem is that if I press the button that calls the thread twice it will throw a BindException address already in use: Which will happen because of the re execution of serverSocket.bind(new InetSocketAddress(4125));. Is there any way to fix/avoid that?

Here are the threads that I'm using: This one is called after I press the button:

 private class ChatClientThread extends Thread {

     DatagramSocket socket;
     String sentence;
     String modifiedSentence;
     BufferedReader inFromUser;

     DataOutputStream outToServer;
     BufferedReader inFromServer;
     Socket clientSocket;
     ServerSocket serverSocket;
      @Override
      public void run() {
       /*Socket socket = null;
       DataOutputStream dataOutputStream = null;
       DataInputStream dataInputStream=null;*/
          clientSocket=null;


       try {
           String data="NewTask_"+EmpPhoneNumber;

           serverSocket=new ServerSocket();
           serverSocket.setReuseAddress(true);
            serverSocket.bind(new InetSocketAddress(4125));
           socket = new DatagramSocket(52276);
           socket.setBroadcast(true);
           InetAddress group = InetAddress.getByName(
                   "224.0.1.2");
           DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(),
               group, 52276);

           socket.send(packet);

              while(true){
               clientSocket = serverSocket.accept();

              ConnectThread ct=new ConnectThread(clientSocket);
              ct.start();
              }

       } catch (UnknownHostException e) {
        e.printStackTrace();
        final String eString = e.toString();
        TicketDetails.this.runOnUiThread(new Runnable() {

         @Override
         public void run() {
          Toast.makeText(TicketDetails.this, eString, Toast.LENGTH_LONG).show();
         }

        });
       } catch (IOException e) {
        e.printStackTrace();
        final String eString = e.toString();
        TicketDetails.this.runOnUiThread(new Runnable() {

         @Override
         public void run() {
          Toast.makeText(TicketDetails.this, eString, Toast.LENGTH_LONG).show();
         }

        });
       }  finally {






        TicketDetails.this.runOnUiThread(new Runnable() {

         @Override
         public void run() {

         }

        });
       }

      }


     }

this one is called from the above thread as you can see:

private class ConnectThread extends Thread {

      Socket socket;
      String sentence;
         String modifiedSentence;
         BufferedReader inFromUser;

         DataOutputStream outToServer;
         BufferedReader inFromServer;
      ConnectThread(Socket socket){

       this.socket= socket;

      }

      @Override
      public void run() {
       DataInputStream dataInputStream = null;
       DataOutputStream dataOutputStream = null;
       Socket socket2 = null;
       DataOutputStream dataOutputStream2= null;
       DataInputStream dataInputStream2=null;

       try {
           while(true){


               inFromUser = new BufferedReader( new InputStreamReader(System.in));
               outToServer = new DataOutputStream(socket.getOutputStream());
               inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
               sentence = inFromUser.readLine();


               modifiedSentence = inFromServer.readLine();
               socket2 = new Socket(socket.getInetAddress().getHostAddress(), 4125);
                dataOutputStream2 = new DataOutputStream(
                  socket2.getOutputStream());

                String[] parts = modifiedSentence.split("_");
                String partGive = parts[0].substring(4); // 004
                String partEmpId = parts[1];
               if(partGive.equals("GiveMeATask")&&Integer.parseInt(partEmpId)==empId){

                   dataOutputStream2.writeUTF("  "+"SolveProblemOrder_2");
                    dataOutputStream2.flush();
               }



               System.out.println("FROM SERVER: " + modifiedSentence);


               if(modifiedSentence!=null) break;}

           outToServer.close();
           inFromServer.close();


       } catch (IOException e) {
        e.printStackTrace();
       } finally {
        if (dataInputStream != null) {
         try {
          dataInputStream.close();
         } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
         }
        }

        if (dataOutputStream != null) {
         try {
          dataOutputStream.close();
         } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
         }
        }


       }

      }



     }

Answer:

Those are two very commmon problems. I'll answer the two in reverse order.

  1. The button you are talking about is creating a ServerSocket and binding it to a specific port. In your case, the port is 4125. From looking at your code, you don't seem to be closing that serversocket anywhere. When you click the button a second time, a second instance of ServerSocket tries to bind to the same port - but that port is still in use by the first ServerSocket. In that case, you get a bind exception. One port cannot be used by more than one ServerSocket. The solution would be to close the existing ServerSocket before creating a new one using serverSocket.close();

  2. If you read the documentation, it clearly states what ServerSocket.accept() does: "[...] The method blocks until a connection is made." This is the "getting stuck" that you described. The thread that executes that code is put into a waiting position and continues only when a connection is made, then returns that new connection. The classic approach is to start a new thread that waits for incoming connections so that your main thread continues to execute and your whole application does not "freeze". Another approach would be a non-blocking framework that encapsulates all that overhead away from you, one of those is Apache MINA.

I would highly suggest to look into small example projects that deal with basic client/server behaviour as you will most likely deal with threads here.

Question:

How do I find out , what exception occurred in spring integration, when I send a message to a server via TCP client. So , there is an <int-ip:tcp-connection-factory> ( client ! ), and it has an error channel. When a connection created between client and server and after few seconds the server closes the connection there is an exception.It's OK, and I able to catch it, the exception is : "Read timed out". But when the connection dosn't create , because the server doesn't listen the specified port, I don't cache any exception via error channel. Therefore, I'am trying to cache exceptions in that way :

try{
  success = gateway.send(adaptor);
  } catch ( MessagingException exc){
    System.out.println("Exception occurred : Timed out waiting for response");
}

But - at this point - I cache

Timed out waiting for response

exception for any reason. ( for example, when the server close the connection, or the the connection doesn't occurre ) A can't take difference between exceptions. Therefore , I listen both this catching mechanism and the error channel at once.

My not elegant solution is :

Main service class :
success = 0;
try{
  success = gateway.send(adaptor); // this will be return 1, if there aren't any exception
return "Success";
} catch ( MessagingException exc){
  try {
    Thread.sleep(1000); // I have to wait for the error channel's message, this portion not elegant !
  } catch (InterruptedException e) {
    return "ERROR";
}
if ( success == 2){
  return "The server closed the connection";
} else {                
  return "There is no connection with server";
}

The error handler snippet is :

public void onException(TcpConnectionExceptionEvent event){
  mainService.setSuccess(2);
}

Is there any simple, and more elegant solution ?

Correction: I use Spring integration 4.04 and here are my client pipe's beans :

<!-- Client side -->

    <int:gateway id="gw"
        service-interface="hu.gmxdev.climaxreplica.service.SimpleGateway"
        default-request-channel="outputchannel" />

    <int-ip:tcp-connection-factory id="client"
        type="client" host="localhost" port="10001" single-use="true"
        so-timeout="5000"
        />

    <int:channel id="outputchannel" />

    <int-ip:tcp-outbound-gateway id="outGateway"
        request-channel="outputchannel" reply-channel="replychannel"
        connection-factory="client" request-timeout="5000" reply-timeout="5000" />

    <int:service-activator input-channel="replychannel"
        method="reply" ref="echoService" id="serviceactivator">
    </int:service-activator>
    <int:channel id="replychannel"></int:channel>

    <int-ip:tcp-connection-event-inbound-channel-adapter id="event"
        event-types="org.springframework.integration.ip.tcp.connection.TcpConnectionExceptionEvent"
        channel="errorChannel" />
    <int:channel id="errorChannel"></int:channel>

    <int:service-activator ref="tcpErrorHandler" method="onException"
        input-channel="errorChannel">
    </int:service-activator>

I add a track trace. This one is, when the server closes an established connection, or the server doesn't answer to the client within the expected time. The track trace are same in both case. :

org.springframework.integration.MessageTimeoutException: Timed out waiting for response
    at org.springframework.integration.ip.tcp.TcpOutboundGateway.handleRequestMessage(TcpOutboundGateway.java:132)
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:170)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:109)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:144)
    at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:44)
    at org.springframework.messaging.core.AbstractMessagingTemplate.sendAndReceive(AbstractMessagingTemplate.java:75)
    at org.springframework.messaging.core.AbstractMessagingTemplate.convertSendAndReceive(AbstractMessagingTemplate.java:125)
    at org.springframework.messaging.core.AbstractMessagingTemplate.convertSendAndReceive(AbstractMessagingTemplate.java:103)
    at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:241)
    at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceive(MessagingGatewaySupport.java:220)
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.java:341)
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.doInvoke(GatewayProxyFactoryBean.java:304)
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invoke(GatewayProxyFactoryBean.java:295)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy115.send(Unknown Source)
    at hu.gmxdev.climaxreplica.service.MainService.senddata(MainService.java:88)
    at hu.gmxdev.climaxreplica.controller.MainController.senddata(MainController.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:724)

Answer:

A MessagingException is thrown under both circumstances...

11:58:08.068 ERROR [main][org.springframework.integration.ip.tcp.TcpOutboundGateway] Tcp Gateway exception
org.springframework.integration.MessageTimeoutException: Timed out waiting for response

and

12:00:34.859 WARN  [main][org.springframework.integration.gateway.GatewayProxyFactoryBean$MethodInvocationGateway] failure occurred in gateway sendAndReceive
org.springframework.messaging.MessagingException: org.springframework.messaging.MessagingException: Failed to send or receive

You won't get a TcpConnectionExceptionEvent in the second case - that event is for exceptions on a specific established connection. Since we didn't actually establish a connection, there's no connection to report an exception for.

In order to determine the actual exception, you should traverse the cause tree; something like:

if (e.getCause() != null) {
    if (e.getCause().getCause() instanceof ConnectException) {
        ...
    }
}

You can also change your gateway to throw a ConnectException...

int send(Foo adapter) throws ConnectException;

...and the framework will automatically unwrap it for you...

try {
    success = gateway.send(adaptor);
}
catch (MessagingException exc) {
    System.out.println("Exception occurred : " + exc.getMessage());
}
catch (ConnectException e) {
    ...
}

The messaging exception for a timeout (no response) is a MessageTimeoutException (subclass of MessagingException). For errors that occur while waiting for a reply, you should get...

throw new MessagingException("Exception while awaiting reply", (Throwable) reply.getPayload());

Question:

First of all, I know, there were people having the same problem BUT their fixes does not work for me.

So the exception that I get is:

java.net.BindException: bind failed: EACCES (Permission denied) on line "serverSocket = new ServerSocket(port);" and i cant figure out where the problem is. I tryed:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

Answer:

I think you don't really need to check that the INTERNET permission is granted or not. It's always granted if you defined it in MANIFEST. Maybe you are facing a error in testing: Just try uninstalling and installing your app again. I recently wrote a piece of code which runs a TCP server without experiencing that problem.

Question:

I am implementing a server in java which recieves images from an android application. basically it is recieving image from android emulator but not from android device. This all process of recieving an image from android emulator or android device is done on localhost.

here is my code of the server.

public class Server {

private static ServerSocket serverSocket;
private static Socket clientSocket;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
private static byte[] image;

public static void main(String[] args) throws UnknownHostException, IOException {
    try {
        serverSocket = new ServerSocket(4000); // Server socket

    } catch (IOException e) {
        System.out.println("Could not listen on port: 4000");
    }
    System.out.println("Server started. Listening to the port 4000");

    while (true) {
        clientSocket = serverSocket.accept(); // accept the client connection
        inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
        bufferedReader = new BufferedReader(inputStreamReader); // get the client message
        DataInputStream inputFromClient = new DataInputStream(clientSocket.getInputStream());
        int count = inputFromClient.available();
        System.out.println(count);
        image = new byte[count];
        inputFromClient.readFully(image);
        final BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(image));
        ImageIO.write(bufferedImage, "jpg", new File("image.jpg"));
    }
}

Exception

Exception in thread "main" javax.imageio.IIOException: Error reading PNG image data
at com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1308)
at com.sun.imageio.plugins.png.PNGImageReader.read(PNGImageReader.java:1577)
at javax.imageio.ImageIO.read(ImageIO.java:1448)
at javax.imageio.ImageIO.read(ImageIO.java:1352)
at server.Server.main(Server.java:39)

Caused by: java.io.EOFException: Unexpected end of ZLIB input stream
at java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:240)
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at java.io.DataInputStream.readFully(DataInputStream.java:195)
at com.sun.imageio.plugins.png.PNGImageReader.decodePass(PNGImageReader.java:1092)
at com.sun.imageio.plugins.png.PNGImageReader.decodeImage(PNGImageReader.java:1196)
at com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1301)
... 4 more

Java Result: 1

I am getting an exception of javax.imageiio.exception in case of sending an image from android device but for android emulator it is working fine. Kindly help me out plz. Thank You.


Answer:

Your main problem is located in this line:

int count = inputFromClient.available();

It returns the number of bytes that are already received at that time. However there may be more bytes waiting to be transferred on the server side. Therefore the transmitted image is truncated/incomplete when you try to load it.

You have now two choices:

  1. Before transferring the image data send an integer containing the length of the data

  2. If only one image is transferred close the stream on client side after the image has been written. On server side you now have to read until you reach the end of the stream.

Question:

My code is as follows. When request comes, server creates two threads (producer-consumer pattern):

...
while(true) {
    Socket clientSocket = server.accept();
    System.out.println("Got connection!");

    Thread consumerThread = new Thread(new ConsumerThread(sharedQueue, clientSocket));
    Thread producerThread = new Thread(new ProducerThread(sharedQueue, clientSocket));

    consumerThread.start();
    producerThread.start();
}
...

Consumer thread reads what client sent and producer thread responds back. Consumer:

@Override
    public void run() {
        try {
            while (true) {
                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                // read, do actions
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

Producer:

 @Override
    public void run() {
        try {
            out = new PrintStream(clientSocket.getOutputStream(), true);
            // some actions
            out.println("something");

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

But in server I get following error:

java.net.SocketException: Socket closed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:150)
    at java.net.SocketInputStream.read(SocketInputStream.java:121)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at ee.ut.ds.server.ConsumerThread.run(ConsumerThread.java:30)
    at java.lang.Thread.run(Thread.java:745)

What might cause this? I even see that client accepts message correctly. Also, in producer thread I close a socket. I do not understand.


Answer:

You closed the socket and continued to use it.

Don't close the socket, or its output stream, until you have read end of stream from the BufferedReader.

Construct the BufferedReader outside the loop.

You probably don't need two threads per socket.

Question:

I am trying to transfer a file from server to client using Java and TCP, however on the client-side I am getting a socket closed exception, whereas the server has no errors when attempting to transfer the file. I am confused about this error because I did not close the socket before trying to read from it. The server accepts the connection and sends the file, but the client gets that error. Any suggestion?

The error is:

java.net.SocketException: Socket closed

Server thread's run function:

public void run() {
    System.out.println("Service thread running for client at " + socket.getInetAddress() + " on port " + socket.getPort());
    try {
        File file = new File("hank.txt");
        FileInputStream fis = new FileInputStream(file);
        BufferedInputStream bis = new BufferedInputStream(fis);
        OutputStream os = socket.getOutputStream();

        byte[] contents;
        long fileLength = file.length();
        long current = 0;

        long start = System.nanoTime();
        while(current!=fileLength) {
            int size = 1000;
            if(fileLength - current >= size) {
                current += size;
            }
            else {
                size = (int)(fileLength - current);
                current = fileLength;
            }
            contents = new byte[size];
            bis.read(contents,0,size);
            os.write(contents);
            System.out.println("sending file..." + (current*100)/fileLength+"% complete!");
        }
        os.flush();
        this.socket.close();
    }catch(Exception e) {
        e.printStackTrace();
    }
}

Client receiving the file code:

    System.out.println("Going to get the file...");
    socket = new Socket(response.getIP().substring(1), response.getPort());

    byte[] contents = new byte[10000];
    FileOutputStream fos = new FileOutputStream("hank.txt");
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    InputStream in = socket.getInputStream();

    int bytesRead = 0;
    System.out.println("Starting to read file...");
    while((bytesRead = is.read(contents))!=-1) { //the error points to this lin
        bos.write(contents,0,bytesRead);
    }

    bos.flush();
    bos.close();
    in.close();

    //
    socket.close();

Answer:

Input stream for this socket is available in variable in

InputStream in = socket.getInputStream();

So

 Change is.read(contents)) to in.read(contents)) 

Question:

I know there are already several similar questions, but I didn't find a reply that fits my case. Please consider a simple client-server app where I have to set up a TCP connection.

On Server side I wait for TCP connection by the code:

ServerSocket mySS= new ServerSocket(10000);
Socket mySocket_ServerSide= mySS.accept();                

On Client side I request for TCP connection by the code:

Socket mySocket_ClientSide= new Socket(); 
mySocket_ClientSide.setReuseAddress(true);
mySocket_ClientSide.bind(new InetSocketAddress(5555)); //always using the same port
mySocket_ClientSide.connect(new InetSocketAddress(serverIP,10000), myTimeout);

The first time everythink works, I do the job on TCP connection (for example a file transfer) and then I close (on client side) the connection to the server using:

mySocket_ClientSide.close(); 

After some seconds I have to connect again to the server, but I get an "address already in use: connect" exception.

I suppose that the state of the client process is in TIME_WAIT, as I read in several questions of this site. But shouldn't I be able to use this port again because of setReuseAddress(true)?

For some reasons I have to bind always to the same port (in the example 5555). Is there any solution that allows me to bind to the same port? Which mistake am I doing?

Thank you in Advance Fausto


Answer:

Your question embodies mutually inconsistent requirements:

  • You have to use the same source port
  • You have to reconnect within seconds.

As you have guessed, you have run into the TIME_WAIT state. This is a compulsory two-minute gap between successive connections from the same source IP: port to the same target IP:port. The rules of TCP require this gap so as to assure connection integrity.

You can reduce the TIME_WAIT period on some operating systems, but this is not recommended. Instead you should get rid of the requirement to always use the same port. There is no point in this, and it also prevents you from forming multiple connections in parallel.

Question:

Please help me resolve this error when transferring a file through sockets:

java.lang.IndexOutOfBoundsException
    at java.io.FileOutputStream.writeBytes(Native Method)
    at java.io.FileOutputStream.write(FileOutputStream.java:326)
    at Client.getFile(Client.java:18)

I implemented a client server application for transferring a file using the TCP protocol. Server is parallel. It is also necessary to implement transmission control using urgent data. I did not find a solution on Java on the Internet.

Class Server:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    private ServerSocket serverSocket;

    public void start(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        while (true)
            new ClientHandler(serverSocket.accept()).start();
    }

    public void stop() throws IOException{
        serverSocket.close();
    }

    private static class ClientHandler extends Thread {
        private Socket clientSocket;
        private DataOutputStream out;
        private FileInputStream in;

        public ClientHandler(Socket socket) {
            this.clientSocket = socket;
        }

        public void run() {
            try {
                out = new DataOutputStream(clientSocket.getOutputStream());
                out.writeInt((int) Prop.FILE_1.length());
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                in = new FileInputStream(Prop.FILE_1);
            } catch (IOException e) {
                e.printStackTrace();
            }

            while (true) {
                byte buf[] = new byte[512];
                int len = 0;
                try {
                    len = in.read(buf);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if(len == -1) {
                    break;
                }
                try {
                    out.write(buf, 0, len);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    out.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            /*try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }*/

        }
    }
}

Class Client:

import java.io.*;
import java.net.Socket;

public class Client {
    private Socket clientSocket;
    private FileOutputStream out;
    private DataInputStream in;

    public String getFile() throws IOException {
        int i = 0;
        int len;
        byte buf[] = new byte[512];
        Integer fileSize;
        fileSize = in.readInt();
        while (i < fileSize) {
            len = in.read(buf);
            if (len == -1) {
                break;
            }
            i += len;
            out.write(buf, 0, len);
            out.flush();
        }
        out.close();
        return in.readUTF();
    }

    public void startConnection(String ip, int port) throws IOException {
        clientSocket = new Socket(ip, port);
        out = new FileOutputStream(Prop.FILE_2);
        in = new DataInputStream(clientSocket.getInputStream());
    }

    public void stopConnection() throws IOException {
        in.close();
        out.close();
        clientSocket.close();
    }
}

Test

public class TestCS {
    @Test
            // (threadPoolSize = 3, invocationCount = 6, timeOut = 1000)
    public void givenClient1__whenServerResponds__thenCorrect() throws IOException {
        SoftAssert softAssert = new SoftAssert();
        Client client1 = new Client();
        client1.startConnection("127.0.0.1", 555);
        String file = client1.getFile();
        System.out.println(file);
        client1.stopConnection();
        softAssert.assertEquals(file, "First file!!!");
        softAssert.assertAll();
    }
}

Answer:

You are reading InputStream wrongly. The logic you are trying to put there is already available in DataInputStream.read(..) method. All you have to do is to check how many bytes it read from the stream.

Change your while loop in Client like this

while (i < fileSize) {
    // javadoc for below : - https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#read(byte[])
    len = in.read(buf);
    if(len<0) {
        break;
    }
    i += len;
    out.write(buf, 0, len);
    out.flush();
}

Note : I have not checked your logic. All I checked and corrected is the Exception you got.

Also, typically we do not read fileSize upfront. You generally keep on reading stream till you get EOF (-1) from the stream. Please check that logic as well.

Question:

We are using Spring integration 4.1.3.

Implemented the client using tcp-outbound-gateway.

A tcp rset packet was received from the server during the request and an exception occurred. What is the reason? Thank you.

    // interface
    public interface TcpSendGateway {
        public byte[] send(String text);
    } 
    // send
    byte[] response = sendGateway.send(request);




    <int:gateway id="gw"
                 service-interface="com.mainpay.service.TcpSendGateway"
                 default-request-channel="input"
                 default-reply-channel="reply"/>

    <int-tcp:tcp-connection-factory id="client"
                                    type="client"
                                    host="#{prop['app.cultureland.host']}"
                                    port="#{prop['app.cultureland.port']}"
                                    so-timeout="10000"
                                    single-use="false"
                                    so-keep-alive="true"
    />                         
    <int:channel id="input" />
    <int-tcp:tcp-outbound-gateway id="outGateway" 
                                  request-channel="input"
                                  reply-channel="reply"
                                  connection-factory="client"
                                  request-timeout="10000"                                      
                                  reply-timeout="10000"                                                                                                               
                                  />        
    <int:channel id="reply" datatype="java.lang.String" />

ERROR LOG

▶ 17.09.29 17:07:37 [pool-2-thread-2] ERROR o.s.i.i.t.c.TcpNetConnection - Read exception 211.59.10.133:7611:51503:d2ec0199-fd15-49c0-bd99-0d864eb2145b SocketException:Connection reset
▶ 17.09.29 17:07:39 [http-nio-19900-exec-5] ERROR o.s.i.ip.tcp.TcpOutboundGateway - Tcp Gateway exception
org.springframework.messaging.MessagingException: Exception while awaiting reply; nested exception is java.net.SocketException: Connection reset
    at org.springframework.integration.ip.tcp.TcpOutboundGateway$AsyncReply.getReply(TcpOutboundGateway.java:288)

wireshark log enter image description here


Answer:

I think you should be sure that your client and server are agreed with the (de)serialization protocol. See Reference Manual for more info:

TCP is a streaming protocol; this means that some structure has to be provided to data transported over TCP, so the receiver can demarcate the data into discrete messages. Connection factories are configured to use (de)serializers to convert between the message payload and the bits that are sent over TCP.

The default one is the ByteArrayCrLfSerializer which deals with the \r\n message delimiter.

So, your client may receive the package but since it doesn't meet the proper delimiter it fails waiting for the reply.

Question:

I'm trying to create an app (with a game) where the client can send to the Server some int values, and until a certain value is not reached, the client can exchange with the server, that sends values back.

My first class is the Server of the TCP app. Here I have a main() method, that runs until the game is over. a getMoveFromClient() method that runs to get the object from the client, and a sendRequestToClient(Game g, int reponse) that sends the object to the client. Here is the code :

public static void main(String[] args) {
    serverLife = true;
    cm = new ConnectionManagerServer(); // this one instanciates my Server options
    Game g;
    while (serverLife) { // boolean value that allows me to continue over
        g = getMoveFromClient(); // get data from client, here every thing is ok 
        sendRequestToClient(g, 1); // send data to client, here it crashes.
        serverLife = g.life; // the object has a parameter that tells if the value is reached or not. (end of the game)
    }
}

public static Game getMoveFromClient() {
    // this method get data from clients, and works fine.
}

Until here, everything is ok. But with this method, that send data to the client :

private static void sendRequestToClient(Game g, int reponse) {
    try {
        g.setResponse(reponse);
        OutputStream out = cm.socket.getOutputStream();
        try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
            oos.writeObject(g); 
            oos.flush();
            oos.close();
        }
    } catch (IOException ex) {
        System.out.println("OutpuStreamError : " + ex.getMessage());
    }
}

I have the following error : OutpuStreamError : Software caused connection abort: socket write error

On the other side, on the client side I have nearly the same code, that works fine until the object Game should be returned :

public static Game getRequestFromServer() {
    Game g = null;
    try {
        InputStream in = mc.socket.getInputStream();
        ObjectInputStream ois = new ObjectInputStream(in);
        g = (Calcul) ois.readObject();
    } catch (IOException ex) {
        System.out.println("error reception" + ex.getMessage());
    } catch (ClassNotFoundException ex) {
        System.out.println("erreur lecture de l'objet" + ex.getMessage());
    }
    return jeu;
}

I have the following error : error reception : Socket is closed

I have a class for my Game object, and two others to deal with the connection ports and the sockets for the client and the server.

public ConnectionManagerServer() {
    try {

        this.serverPort = 6464;
        this.serverSocket = new ServerSocket(this.serverPort);
        this.socket = this.serverSocket.accept();
    } catch (IOException ex) {
        System.out.println("serverSocket probleme d'initialisation : " + ex.getMessage());
    }
}

and the second one :

 public ConnectionManagerClient() {
    try {
        this.hostAdress = InetAddress.getByName("localhost");             // adresse du serveur 
        this.serverPort = 6464;
        this.socket = new Socket(this.hostAdress, this.serverPort);

    } catch (UnknownHostException ex) {
        System.out.println("Erreur d'initalisation de l'adresse de l'hote : " + ex.getMessage());
    } catch (IOException ex) {
        System.out.println("Erreur d'initalisation de la connexion : " + ex.getMessage());

    }
}

What I don't understand, is that when I try to send from the client to the server, it works fine, and the server is able to read the object content, but when I try to send it from the server to the client, I cannot read the object from the server. Is it because I didn't open the socket ?

EDIT : Do I have to use accept() in my client class to get data from the server ? This is false.


Answer:

Closing the input stream or output stream of a socket closes the socket. Don't close the streams, just flush the object output stream. And use the same streams for the life of the socket, not new ones per message.

Using accept() in a client is a contradiction in terms.

Question:

Following is the (greatly simplified) code used for communicating from a client machine, to a REST server, using Jersey. There is a 5 minute timeout for establishing a connection at the start, and a 2 minute timeout for reading from the underlying socket.

public class JerseyClient {

  private final Map<Action, WebResource> resources;

  public JerseyClient(URI uri) {
    this.resources = new EnumMap<Action, WebResource>(Action.class);
    this.resources.put(Action.Put, getClient().resource(Action.Put.getURI()));
    this.resources.put(Action.Query, getClient().resource(Action.Query.getURI()));
  }

  private String submit(Action action, String input) throws Exception {
    WebResource resource = this.resources.get(action);
    ClientResponse response = null;
    synchronized (resource) {
      try {
          response = resource.accept(MediaType.APPLICATION_JSON_TYPE,
                  MediaType.TEXT_PLAIN_TYPE).type(MediaType.APPLICATION_JSON_TYPE).
                  post(ClientResponse.class, input);
          String responseString = null;
          // Handle the response and produce a response string...
        return responseString;
      } finally {
        if (response != null) {
          response.close();
        }
      }
    }
  }

  private static Client getClient() {
    Client client = Client.create();
    client.setReadTimeout(2*60*1000);
    client.setConnectTimeout(5*60*1000);
    return client;
  }

  private enum Action {
    Put, Query;
    public URI getURI(){
      switch (this) {
        case Put:
          return URI.create("PUT_URI");
        case Query:
          return URI.create("QUERY_URI");
        default:
          throw new InvalidStateException("Illegal action");
      }
    }
  }
}

The above code works as expected, unless the read timeout triggers at the client. In that case, a SocketTimeoutException is thrown and thus the response object in the submit() method of the JerseyClient class above remains null, so the underlying socket is never closed fully.

Apparently there is a partial closure of the socket by the client since, on the other side, the server enters the CLOSE_WAIT state (i.e., it has received a FIN packet from the client, as per the TCP specification). However, since it never gets the final ACK from the client (which should be sent if response.close() was called), it keeps the connection at CLOSE_WAIT (as shown by netstat), so each timed out REST call from the client potentially creates a dangling CLOSE_WAIT on the server.

Is there any way of solving the issue, without completely re-engineering the above code?


Answer:

Your description doesn't make sense. The name of the state is CLOSE_WAIT, not CLOSED_WAIT, and it means what its (correct) name expresses: it is waiting for the local application to close the socket, after receiving a remote close from the peer.

If your server is entering CLOSE_WAIT:

  1. The client has closed the socket.
  2. The server has not closed the socket. This is a bug in the server.
  3. The server will never get a final ACK from the client until it issues a FIN by closing the socket. The ACK is an acknowledgement of the FIN. Until the server issues the FIN there is nothing for the client to ACK.
  4. It is the close that gets it out of CLOSE_WAIT, not the client ACK.
  5. Calling response.close() at the client has nothing to do with the client sending the final ACK.

Question:

Project: I have been working on a wireless mouse app for android that utilizes TCP as the network protocol for transferring mouse movements.

Objective: I decided that implementing a heartbeat TimerTask would be the best way to see if the server has been shutdown. Every 5 seconds that a mouse movement was not made (a mouse movement resets the timer back to 5), a heartbeat of 2 bytes in an array would be sent to the server. Therefore, if the server is shutdown, an IOException (Broken Pipe) should raise once a heartbeat is sent.

My Problem: The heartbeat works fine aside from the fact that it loops around 3 times before it throws an exception. Currently, I have it set to 5 seconds before it sends a heartbeat. It will send three heartbeats (15 seconds instead of 5) after the server is closed before it raises the expected exception.

I could potentially set the heartbeat interval to 2 seconds which in turn should take 6 seconds to raise the exception but I would like to know why it's not working the first time.

Heartbeat code:

 Timer task = new Timer();
                task.scheduleAtFixedRate(new TimerTask() {
                    @Override
                    public void run() {
                        if (heartbeat == 1) {
                            byte buf[] = {-96, -96};
                            try {
                                bos.write(buf); // Buffered output stream
                                bos.flush(); // Exception gets thrown here
                                heartbeat = 5;
                                System.out.println("Testing 3");
                            } catch (IOException e) {
                                System.out.println("Testing 2");
                                launchHomescreen();
                                this.cancel();
                                e.printStackTrace();
                            }
                        } else {
                            System.out.println("Testing 1" + heartbeat);
                            heartbeat--;
                        }
                    }
                }, 1000, 1000);

Log of debug statements:

04-27 00:33:02.339  25410-26259/com.tutorials.jurko.androidmouse I/System.out﹕ Message sending: -99 -99 <-- This is the mouse click that should stop the server
04-27 00:33:03.190  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 15
04-27 00:33:04.201  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 14
04-27 00:33:05.192  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 13
04-27 00:33:06.193  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 12
04-27 00:33:07.203  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 3 <- Should throw the exception here
04-27 00:33:08.194  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 15
04-27 00:33:09.195  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 14
04-27 00:33:10.196  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 13
04-27 00:33:11.187  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 12
04-27 00:33:12.188  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 3
04-27 00:33:13.189  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 15
04-27 00:33:14.190  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 14
04-27 00:33:15.191  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 13
04-27 00:33:16.202  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 12
04-27 00:33:17.193  25410-26264/com.tutorials.jurko.androidmouse I/System.out﹕ Testing 2 <- but doesn't do it till the third heartbeat
04-27 00:33:17.233  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ java.net.SocketException: sendto failed: EPIPE (Broken pipe)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:499)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at libcore.io.IoBridge.sendto(IoBridge.java:468)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at java.net.PlainSocketImpl.write(PlainSocketImpl.java:508)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:46)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:270)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at java.io.BufferedOutputStream.flushInternal(BufferedOutputStream.java:185)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:85)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at com.tutorials.jurko.androidmouse.MainActivity$connectTask$1.run(MainActivity.java:496)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at java.util.Timer$TimerImpl.run(Timer.java:284)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ Caused by: libcore.io.ErrnoException: sendto failed: EPIPE (Broken pipe)
04-27 00:33:17.243  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at libcore.io.Posix.sendtoBytes(Native Method)
04-27 00:33:17.253  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at libcore.io.Posix.sendto(Posix.java:156)
04-27 00:33:17.253  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:177)
04-27 00:33:17.253  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ at libcore.io.IoBridge.sendto(IoBridge.java:466)
04-27 00:33:17.253  25410-26264/com.tutorials.jurko.androidmouse W/System.err﹕ ... 7 more
04-27 00:33:17.453  25410-25410/com.tutorials.jurko.androidmouse W/ApplicationPackageManager﹕ getCSCPackageItemText()
04-27 00:33:33.139  25410-25410/com.tutorials.jurko.androidmouse W/IInputConnectionWrapper﹕ getCursorCapsMode on inactive InputConnection

Answer:

The 'connection reset'/'broken pipe' doesn't happen immediately, because of TCP buffering and asynchronicity. It happens after a write event times out on not receiving an ACK, which can take an appreciable fraction of a minute.

It isn't necessarily related to the number of write attempts, so changing your interval won't necessarily help.

Question:

I'm writing a RabbitMQ interface using spring integration for a TCP legacy service. I'm able to connect to the legacy service and send a XML string message.

The legacy server replies back with a XML message. Upon receiving the message, a custom deserializer reads most of the message until the very last line in the response and then fails with a MessageTimeoutException. I have set break points to verify this is happening. Is there anything obvious that I am doing wrong?

JUnit Test

@RunWith(SpringRunner.class)
@SpringBootTest
public class MaasIntegrationHelloWorld {

    @Autowired
    private TCPGateway gateway;

    @Test
    public void getAnalysisEngineInfo() throws JAXBException, ConnectException {
        //Actual XML message creation and serialization removed for brevity

        String message = "Hello World";

        String result = gateway.send(message);
        assertEquals(" ", result);
    }

}

TCPConfig

@EnableIntegration
@IntegrationComponentScan
@ComponentScan
@Configuration
public class TCPConfig {

    @Value("${legacy.hostname}")
    private String hostname;

    @Value("${legacy.port}")
    private int port;


    @Bean(name="replyChannel")
    public MessageChannel replyChannel() {
        return new DirectChannel();
    }

    @Bean(name="sendChannel")
    public MessageChannel sendChannel() {
        return  new DirectChannel();
    }

    @Bean
    public TcpNetClientConnectionFactory connectionFactory() {
        TcpNetClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory(hostname, port);
        connectionFactory.setDeserializer(new CommandResultDeserializer());

        connectionFactory.setSingleUse(false);
        return connectionFactory;
    }

    @Bean
    @ServiceActivator(inputChannel = "sendChannel")
    public TcpOutboundGateway tcpOutboundGateway() {
        TcpOutboundGateway tcpOutboundGateway = new TcpOutboundGateway();
        tcpOutboundGateway.setConnectionFactory(connectionFactory());
        tcpOutboundGateway.setReplyChannel(this.replyChannel());
        tcpOutboundGateway.setRequiresReply(true);

        return tcpOutboundGateway;
    }

}

Gateway interface

@MessagingGateway(defaultRequestChannel = "sendChannel")
public interface TCPGateway {
    String send(String message) throws ConnectException;  
}

Gateway Listener

@Configuration
@EnableIntegration
@IntegrationComponentScan
@MessageEndpoint
public class TCPGatewayListener {

    @ServiceActivator(inputChannel = "replyChannel")
    public String replyHandler(byte[] b) {
        return new String(b);
    }
}

Deserializer

public String deserialize(InputStream inputStream) throws IOException {
    BufferedReader br = null;
    StringBuilder sb = new StringBuilder();

    String line;

    br = new BufferedReader(new InputStreamReader(inputStream));

    while ((line = br.readLine()) != null) {
        sb.append(line);
    }

    return sb.toString();
}

Stack trace

org.springframework.integration.MessageTimeoutException: Timed out waiting for response
    at org.springframework.integration.ip.tcp.TcpOutboundGateway.handleRequestMessage(TcpOutboundGateway.java:146) ~[spring-integration-ip-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:109) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:425) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:375) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) [spring-messaging-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:150) [spring-messaging-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:45) [spring-messaging-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.messaging.core.AbstractMessagingTemplate.sendAndReceive(AbstractMessagingTemplate.java:42) [spring-messaging-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.integration.core.MessagingTemplate.sendAndReceive(MessagingTemplate.java:97) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.core.MessagingTemplate.sendAndReceive(MessagingTemplate.java:38) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.messaging.core.AbstractMessagingTemplate.convertSendAndReceive(AbstractMessagingTemplate.java:79) [spring-messaging-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.messaging.core.AbstractMessagingTemplate.convertSendAndReceive(AbstractMessagingTemplate.java:70) [spring-messaging-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:449) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceive(MessagingGatewaySupport.java:422) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.java:478) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.doInvoke(GatewayProxyFactoryBean.java:433) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.gateway.GatewayProxyFactoryBean.invoke(GatewayProxyFactoryBean.java:424) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.integration.gateway.GatewayCompletableFutureProxyFactoryBean.invoke(GatewayCompletableFutureProxyFactoryBean.java:65) [spring-integration-core-4.3.12.RELEASE.jar:4.3.12.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) [spring-aop-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at com.sun.proxy.$Proxy107.send(Unknown Source) [na:na]
    at orgl.shelly.maas.MaasIntegrationHelloWorld.getAnalysisEngineInfo(MaasIntegrationHelloWorld.java:49) [test-classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) [junit-4.12.jar:4.12]
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) [junit-4.12.jar:4.12]
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) [spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12]
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) [junit-rt.jar:na]
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) [junit-rt.jar:na]
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) [junit-rt.jar:na]
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) [junit-rt.jar:na]

Answer:

while ((line = br.readLine()) != null) {
    sb.append(line);
}

That's an odd deserializer - how do you know when the response message is complete?

If the server replies with a multi-line response, you need to know when the response is complete somehow; perhaps the last line being zero length, for example.

Or

if (line.equals("</endofdoc>") {
   break;
}

Question:

I have a multithreaded tcp server, that handles multiple clients. Each client has its thread on the serverside that keeps the socket connection. Everything theoretically works fine for many minutes, but at rare occasions, while having multiple clients connected, the following happens: One of the clients sends a tcp packet to the server and the serverside read times out. I have found many questions, that tackle read timeouts on the clientside, but in my case, this never happens. In my case, the server times out on a read when receiving a packet from a client. My question is, why and how can this happen and what can I do to handle this problem?

here is my server listener:

public class GameServerTCP extends Thread {

//TCP
private ServerSocket serverSocket;
public Server server;
public int amountOfTCPConnections = 0;

ClassLoader classLoader = getClass().getClassLoader();
File myFile = new File(classLoader.getResource("Sprites/sprite_sheet.png").getFile());

public GameServerTCP(Server game) {
    this.server = game;

    //TCP
    try {
        serverSocket = new ServerSocket(6336);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void run() {
    while(true) {
        //TCP
        Socket socket = null;

        try {
            socket = serverSocket.accept();
            Toolkit.getDefaultToolkit().beep();
            System.out.println(socket.getRemoteSocketAddress() + " has connected to server."); 
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        new TCPConnection(socket, this);
        amountOfTCPConnections++;

        if (amountOfTCPConnections > 500) {
            System.err.println("Too many clients error! (unsolved)");
            server.frame.dispatchEvent(new WindowEvent(server.frame, WindowEvent.WINDOW_CLOSING));
        }
    }
}

}

here is my server thread that hold each single connection:

public class TCPConnection implements Runnable {

Socket socket;
private Thread thread;
private boolean isRunning = false;
public GameServerTCP serverTCP;
private String gamename = "-1";
public String username;

/**
 * This is the future!
 * Contains an exact imprint of the player of client side.
 * Cheats can be detected here.
 */
private PlayerMP playerMP;

String clientSentence;

TCPConnection(Socket socket, GameServerTCP serverTCP) {
    this.socket = socket;
    this.serverTCP = serverTCP;
    isRunning = true;
    thread = new Thread(this);
    thread.start();
}

public synchronized void closeConnection() {
    if (MasterConnections.connectionsTCP.containsKey(getUniqueConnectionIdentifier())) MasterConnections.connectionsTCP.remove(getUniqueConnectionIdentifier());
    if (this.username != null && MasterConnections.currentlyLoggedOnAccounts.contains(this.username)) MasterConnections.currentlyLoggedOnAccounts.remove(this.username);

    if (this.gamename != null && serverTCP.server.games.containsKey(this.gamename)) {
        Level game = serverTCP.server.games.get(this.gamename);
        for (String p : game.playersInLevel) {
            if (p.equals(getUniqueConnectionIdentifier())) {
                game.playersInLevel.remove(p);
                System.out.println(this.username + " has been been removed from game " + this.gamename + ".");
            }
        }

        PacketTCP02LeaveGame tellOthersPacket = new PacketTCP02LeaveGame(this.gamename, this.username);
        game.writeDataTCPToAllPlayersInThisLevel(tellOthersPacket);
    }

    try {
        this.socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

    System.out.println(socket.getRemoteSocketAddress() + " has been disconnected from server.");
    this.serverTCP.amountOfTCPConnections--;
    this.stop();
}

public String getUniqueConnectionIdentifier() {
    return socket.getInetAddress() + ":" + socket.getPort();
}

public String generateUniqueUDPConnectionIdentifier(InetAddress inetAddess, int udpPort) {
    System.out.println("uuc created: ");
    System.out.println(inetAddess + "/" + udpPort);
    return inetAddess + ":" + udpPort;
}

public void run() {
    //version check first
    PacketTCP00VersionCheck packetVersionCheck = new PacketTCP00VersionCheck(serverTCP.server.getVersion());

    if (MasterConnections.connectionsTCP.containsKey(getUniqueConnectionIdentifier())) {
        this.closeConnection();
    }
    else {
        MasterConnections.connectionsTCP.put(getUniqueConnectionIdentifier(), this);
        packetVersionCheck.writeData(this);
    }

    BufferedReader inFromClient;
    try {
        inFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    } catch (IOException e1) {
        e1.printStackTrace();
        closeConnection();
        return;
    }

    while(isRunning) {
        try {
            clientSentence = inFromClient.readLine();
            if (clientSentence == null) {
                inFromClient.close();
                closeConnection();
            }
            else {
                System.out.println("tcprec -> " + (new Date(System.currentTimeMillis())) + " -> " + this.username + " -> " + clientSentence);
                this.parsePacket(clientSentence.getBytes());
            }
        }
        catch (SocketTimeoutException ste) {
            /**
             * TODO:
             */
            ste.printStackTrace();
            System.err.println("YOU CAN DO SOMETHING HERE!!!!!!!");
            closeConnection();
        }
        catch (Exception e) {
            e.printStackTrace();
            closeConnection();
        }
    }
}

public void stop() {
    isRunning = false;
    try {
        thread.join();
    } 
    catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}

And here is my client:

public class GameClientTCP extends Thread {

public String gamestate = "logged out";

private Game game;
public Socket tcpSocket;
public boolean isRunning = false;
private String serverSentence;
public boolean hasBeenStarted = false;

public int boundUDPPort = -1;

public static String[] characters = new String[5];
public static boolean charactersAreLoaded = false;

private PrintWriter toServer;

public GameClientTCP(Game game, String ipAddress) {
    this.game = game;
}

public boolean tryConnect() {
    try {
        tcpSocket = new Socket();
        tcpSocket.connect(new InetSocketAddress(Settings.SERVER_ADDRESS, 6336), 1000);
        System.out.println("Just connected to " + tcpSocket.getRemoteSocketAddress()); 

        game.getSocketClientUDP().prepareBeforeStart();
        game.getSocketClientUDP().start();

        return true;
    } catch (UnknownHostException e1) {
        try {
            tcpSocket.close();
        } catch (IOException e) {
            GameError.appendToErrorLog(e);
            return false;
        }
        return false;
    } catch (IOException e1) {
        try {
            tcpSocket.close();
        } catch (IOException e) {
            GameError.appendToErrorLog(e);
            return false;
        }
        GameError.appendToErrorLog(e1);
        return false;
    }
}

public void run() { 
    BufferedReader fromServer;
    try {
        fromServer = new BufferedReader(new InputStreamReader(tcpSocket.getInputStream()));
        toServer = new PrintWriter(tcpSocket.getOutputStream(),true);
    } catch (IOException e1) {
        GameError.appendToErrorLog(e1);
        return;
    }

    while(isRunning) {
        try {
            serverSentence = fromServer.readLine();
            //System.out.println("Received: " + serverSentence);
            if (serverSentence != null) this.parsePacket(serverSentence.getBytes());
        }
        catch(UnknownHostException ex) {
            GameError.appendToErrorLog(ex);
        }
        catch(IOException e){
            GameError.appendToErrorLog(e);
        }
        catch(Exception e) {
            GameError.appendToErrorLog(e);
        }
    }
}

public void sendMessageToServer(String message) {
    try {
        toServer.println(message); 
        toServer.flush();
    }
    catch (Exception e) {
        GameError.appendToErrorLog(e);
        System.exit(-1);
    }
}

}

I hope to find out more about this issue, please help! :)

EDIT: It may be important to say, that while my program is running, it can occur, that there are no tcp packets sent over a longer period of time. The timeout always happens, when i dont send any packets for at least 20 or 30 minutes and then when i send one again, another client times out.


Answer:

As it turned out, tcp sockets, that are not used longer than a certain amount of time will be kind of destroyed by peers and therefore lose their connection. I solved my issue, by sending a nearly empty tcp packet every minute to make it clear to all programs and services, that these sockets are alive!

Question:

Basically am a newbie to socket programing. i would like to know about how to close a socket if stays idle for a specified time interval. i searched on net about this ,i found that function which is used to close the socket after the specified interval. but here in my case , i would like to close the socket only when it is stays Idle for more than the specified interval


Answer:

I searched on net about this

Why? The Javadoc exists. No searching necessary.

I found that function which is used to close the socket after the specified interval

There is no such method.

I saw about setSoTimeOut(2000) function which closes the socket after the specifed time interval

No it doesn't. It doesn't close the socket at all, and it causes read methods to throw a SocketTimeoutException if no data arrives within the timeout period.

but I would like to close only if the socket remains idle for the specified interval

Socket.setSoTimeout() is exactly what you need.

the client establishes the connection with the server and then later after sometime it the client close the socket connection at its side after performing the required task and creates a new connection the next time when it pings, where as my server does not close the connection and it keeps on listening to that client

In other words your server is ignoring end of stream on the socket. Don't do that. Close the socket if you get end of stream from a read method.

Question:

I've written a simple asynchronous tcp server with the nio. The server should be able to read and write at the same time for each client. This I've implemented with a simple packet queue.

public class TcpJobHandler {

private BlockingQueue<TcpJob> _packetQueue = new LinkedBlockingQueue<TcpJob>();
private Thread _jobThread;
private final ReentrantLock _lock = new ReentrantLock();

public TcpJobHandler(){
    _jobThread = new Thread(new Runnable() {
        @Override
        public void run() {
            jobLoop();
        }       
    });

    _jobThread.start();
}

private void jobLoop(){
    while(true){
        try {
            _lock.lock();
            TcpJob job = _packetQueue.take();
            if(job == null){
                continue;
            }
            job.execute();
        } catch (Exception e) {
            AppLogger.error("Failed to dequeue packet from job queue.", e);
        }finally{
            _lock.unlock();
        }
    }
}

public void insertJob(TcpJob job){
    try{
        _packetQueue.put(job);
    }catch(InterruptedException e){
        AppLogger.error("Failed to queue packet to the tcp job queue.", e);
    }
}
}

What this code do, is just checking for a new packet. If a new packet is available, this packet will be send to the client. In the class tcp job, there is just the packet to send and a write class whichs writes the packet into the client stream. As you can see, only one thread should be able to write a packet into a client stream.

This is the point, why I dont understand, why I'm getting this error? If I'm right, this exception says, that I try to send data into a stream, but there is already a thread which is writing data into this stream. But why?

//Edit: I'm getting this exception:

19:18:41.468 [ERROR] - [mufisync.server.data.tcp.handler.TcpJobHandler] : Failed to dequeue packet from job queue. Exception: java.nio.channels.WritePendingException
at sun.nio.ch.AsynchronousSocketChannelImpl.write(Unknown Source)
at sun.nio.ch.AsynchronousSocketChannelImpl.write(Unknown Source)
at mufisync.server.data.tcp.stream.OutputStreamAdapter.write(OutputStreamAdapter.java:35)
at mufisync.server.data.tcp.stream.OutputStreamAdapter.write(OutputStreamAdapter.java:26)
at mufisync.server.data.tcp.stream.BinaryWriter.write(BinaryWriter.java:21)
at mufisync.server.data.tcp.TcpJob.execute(TcpJob.java:29)
at mufisync.server.data.tcp.handler.TcpJobHandler.jobLoop(TcpJobHandler.java:40)
at mufisync.server.data.tcp.handler.TcpJobHandler.access$0(TcpJobHandler.java:32)
at mufisync.server.data.tcp.handler.TcpJobHandler$1.run(TcpJobHandler.java:25)
at java.lang.Thread.run(Unknown Source)

The TcpJob looks like this:

public class TcpJob {

private BasePacket _packet;
private BinaryWriter _writer;

public TcpJob(BasePacket packet, BinaryWriter writer){
    _packet = packet;
    _writer = writer;
}

public void execute(){
    try {
        if(_packet == null){
            AppLogger.warn("Tcp job packet is null");
            return;
        }

        _writer.write(_packet.toByteArray());
    } catch (IOException e) {
        AppLogger.error("Failed to write packet into the stream.", e);
    }
}

public BasePacket get_packet() {
    return _packet;
}   
}

The BinaryStream is just coupled to a AsynchronousSocketChannel which calls the write(byte[]) method from the socket channel.


Answer:

You are using asynchronous NIO2. When you use asynchronous IO you cannot call write() until the last write has completed. From the Javadoc

 * @throws  WritePendingException
 *          If a write operation is already in progress on this channel

e.g. if you have used

public abstract Future<Integer> write(ByteBuffer src);

you cannot write again until this Future.get() returns.

If you use

public abstract <A> void write(ByteBuffer src,
                               long timeout,
                               TimeUnit unit,
                               A attachment,
                               CompletionHandler<Integer,? super A> handler);

You cannot write again until the CompletionHandler is called.

Note: you cannot be performing two reads at once either.

In your case you want something like

ByteBuffer lastBuffer = null;
Future<Integer> future = null;

public void execute(){
    try {
        if(_packet == null){
            AppLogger.warn("Tcp job packet is null");
            return;
        }
        // need to wait until the last buffer was written completely.
        while (future != null) {
           future.get();
           if (lastBuffer.remaining() > 0)
              future = _writer.write(lasBuffer);
           else
              break;
        }
        // start another write.
        future = _writer.write(lastBuffer = _packet.toByteArray());
    } catch (IOException e) {
        AppLogger.error("Failed to write packet into the stream.", e);
    }
}

Question:

I am sending TCP packets just few bits each (one line of text or so). I am sending them to remote server via HTTP proxy however for some reason when the connection with the proxy is slow or interrupted to the server arrives just a fragment of the packet and not entire packet and it causes exceptions on the server side, how it that posible ? Is there any way on the client side how to prevent sending fragment of the packet instead of entire packet ?

Example: I am trying to send this packet:

packetHead: id (1-99)
integer: 1
short: 0
byte: 4

And in my case sometimes happens that to the server arrives just packetHead and integer and the rest of the packet is lost somewhere when the connection with the proxy is bad.

I have no access to modify server source code so I need to fix it on the client side.

Thanks for any tips.


Answer:

Please show how you send your data. Everytime I had similar problem it was my fault for not flushing the stream. Especially if the stream is compressed one needs to close/complete on the GZIP or similar object to actually send out everything.

Question:

I am trying to write a service to communicate with a tcp server on www.herbrich.org:2147

But my app keep on crashing every time i run it. Here is my full code from the service class.

ServiceClass:

package org.herbrich.katana;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

import java.util.Random;

/**
 * Created by Administrator on 16.04.2015.
 */
public class LocalService extends Service{
    LocalService()
    {
        new Thread(new ClientThread()).start();
    }

    //JenniferHerbrich Network Ansi Declares
    private Socket socket;
    private static final int SERVERPORT;
    private static final String SERVER_IP;

    static {
        SERVER_IP = "10.141.0.151";
        SERVERPORT = 2147;

    }

    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();
    // Random number generator
    private final Random mGenerator = new Random();

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
            // Return this instance of LocalService so clients can call public method
            return LocalService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /** method for clients */
    public int getRandomNumber() {
        return mGenerator.nextInt(100);
    }
    public String communicateWithEvelin(String EvelinValue)
    {
        try
        {
            BufferedReader input;
            PrintWriter out = new PrintWriter(new BufferedWriter(
                    new OutputStreamWriter(socket.getOutputStream())),
                    true);
            out.println(EvelinValue);
            out.flush();
            input = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
            return input.readLine();
        }
        catch(Exception e)
        {
            return "ERROR";
        }
    }
    class ClientThread implements Runnable {

        @Override
        public void run() {

            try {
                InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

                socket = new Socket(serverAddr, SERVERPORT);

            } catch (IOException e1) {
                e1.printStackTrace();
            }

        }

    }
}

I think i've some problem with the multithreading call inside the constructor method. The debug console gives me illegalAccessExceptions..

LogCat:

04-15 18:52:08.632    9182-9182/org.herbrich.katana E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to instantiate service org.herbrich.katana.LocalService: java.lang.IllegalAccessException: access to constructor not allowed
            at android.app.ActivityThread.handleCreateService(ActivityThread.java:2599)
            at android.app.ActivityThread.access$1700(ActivityThread.java:158)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1384)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:176)
            at android.app.ActivityThread.main(ActivityThread.java:5365)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.IllegalAccessException: access to constructor not allowed
            at java.lang.Class.newInstanceImpl(Native Method)
            at java.lang.Class.newInstance(Class.java:1319)
            at android.app.ActivityThread.handleCreateService(ActivityThread.java:2596)
            at android.app.ActivityThread.access$1700(ActivityThread.java:158)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1384)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:176)
            at android.app.ActivityThread.main(ActivityThread.java:5365)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
            at dalvik.system.NativeStart.main(Native Method)
04-15 18:52:08.640    9182-9197/org.herbrich.katana E/TCP Client﹕ C: Connecting...

Answer:

your ClientThread class must be public, and has a public zero-argument constructor, and that the constructor chains to the superclass' constructor.

Question:

I'm writing a simple TCP Port scanner. Here's my code:

for (int port : portList) {
    Socket socket = new Socket();

    try {
        socket.connect(new InetSocketAddress(targetIP, port), 5000);

        // If we get to this point, port is open
        Log.d(DEBUG_TAG, "Port " + port + " open");

    } catch (Exception e) {
        Log.d(DEBUG_TAG, e.toString());
    } finally {
        // Try to close
        try {
            socket.close();
        } catch (Exception e) {}
    }
}

Here's the debug output. I've run the scan several times and get the exact same output with the same port ECONNREFUSED while others EHOSTUNREACH.

D/TCPSCAN﹕ java.net.SocketException: failed to connect to /192.168.0.10 (port 21) after 5000ms: isConnected failed: EHOSTUNREACH (No route to host)
D/TCPSCAN﹕ java.net.ConnectException: failed to connect to /192.168.0.10 (port 22) after 5000ms: isConnected failed: ECONNREFUSED (Connection refused)
D/TCPSCAN﹕ java.net.SocketException: failed to connect to /192.168.0.10 (port 23) after 5000ms: isConnected failed: EHOSTUNREACH (No route to host)
D/TCPSCAN﹕ java.net.SocketException: failed to connect to /192.168.0.10 (port 80) after 5000ms: isConnected failed: EHOSTUNREACH (No route to host)
D/TCPSCAN﹕ java.net.SocketException: failed to connect to /192.168.0.10 (port 443) after 5000ms: isConnected failed: EHOSTUNREACH (No route to host)

The Android device I'm running on can successfully ping -c 1 -W 1 192.168.0.10. My phone detects the remote host as online, which is why I don't understand why I'm getting EHOSTUNREACH. More curious is the fact that port 22 - which is not open on the target - gets a ECONNREFUSED.

The only port that is actually open on the target is FTP port 21 (confirmed with nmap).

I've read some answers to similar problems. The main fix seems to be restarting the phone's WiFi connection, which didn't work for me.

Note

For the sake of clarity I'm not posting my whole code here but I am checking that the target host 192.168.0.10 is online with:

Process process = runtime.exec("/system/bin/ping -c 1 -W 1 192.168.0.10");
// Wait until the process finishes and check exit code (0 for success)
int exitCode = process.waitFor();
if (exitCode == 0)
    Log.d(DEBUG_TAG, "Online");

The device I'm running on is a Samsung Galaxy S2, I'm targetting my laptop, a Macbook Pro running Fedora. Both devices are on the same WiFi network.

From my laptop I can detect and run an nmap scan on the Android phone (192.168.0.3). It's definitely reachable.


Answer:

Could you please provide more details about your test?

  • What is your source device (android phone)?
  • What destination are you trying to reach and scan? Computer on local or outside network?
  • Are both source and destination devices on the same network (probably WiFi)?

EHOSTUNREACH - no route to host should say it is either

  • ISO/OSI Layer 3 issue (devices on the different private IP networks without routes to each other)

  • destination device is down

  • ICMP protocol/ECHO replies are blocked somewhere in between (or firewall on source or destination device)

ECONNREFUSED - should be even more clear - this particular port is not opened on destination device

Maybe you can split your code logic into two parts:

  1. Check if device is up and running (PING - ICMP protocol)
  2. Then perform port scan
    • if isConnected == TRUE (port is open) else (port is closed)

Output could be:

  1. PING is Successful && isConnected == TRUE (device is UP and port is OPEN)
  2. PING is Successful && isConnected == FALSE (device is UP but port is CLOSED)
  3. PING is Unsuccessful && isConnected == TRUE (probably ICMP protocol/ECHO request is BLOCKED - device is UP and port is OPENED)
  4. PING is Unsuccessful && isConnected == FALSE (device is probably DOWN or ICMP is BLOCKED and port is CLOSED)

Try to give it a try.

Thank you.

Question:

Im getting this error when closing my TCP Server from my form.

java.net.SocketException: Socket closed
    at java.net.PlainSocketImpl.socketAccept(Native Method)
    at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:404)
    at java.net.ServerSocket.implAccept(ServerSocket.java:545)
    at java.net.ServerSocket.accept(ServerSocket.java:513)
    at com.hightekjonathan.HomeServer.Server.Start(Server.java:36)
    at com.hightekjonathan.HomeServer.Form$2.run(Form.java:81)
    at java.lang.Thread.run(Thread.java:745)

Heres the Server.java:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.*;
import java.util.Enumeration;

public class Server {
    private static ServerSocket serverSocket = null;
    private static Socket socket = null;
    private static DataInputStream dataInputStream = null;
    private static DataOutputStream dataOutputStream = null;

    private static int port = 19586;

    private static boolean running = false;

    public void Start() {
        try {
            System.out.println("Starting Server...");

            serverSocket = new ServerSocket(port);

            System.out.println("Server Started");
            System.out.println("IP Address: " + getIpAddress());
            System.out.println("Listening: " + serverSocket.getLocalPort());

            running = true;
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            System.out.println("Attempting to connect to clients...");
            socket = serverSocket.accept();

            dataInputStream = new DataInputStream(socket.getInputStream());
            dataOutputStream = new DataOutputStream(socket.getOutputStream());

            System.out.println("ip: " + socket.getInetAddress());
            System.out.println("message: " + dataInputStream.readUTF());

            dataOutputStream.writeUTF("connected");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void Stop() {
        if (running) {
            if (socket != null) {
                try {
                    socket.close();
                    socket = null;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            if (dataInputStream != null) {
                try {
                    dataInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (dataOutputStream != null) {
                try {
                    dataOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            running = false;
        }
    }

    private String getIpAddress() {
        String ip = "";
        try {
            Enumeration<NetworkInterface> enumNetworkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (enumNetworkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = enumNetworkInterfaces.nextElement();
                Enumeration<InetAddress> enumInetAddress = networkInterface.getInetAddresses();
                while (enumInetAddress.hasMoreElements()) {
                    InetAddress inetAddress = enumInetAddress.nextElement();

                    if (inetAddress.isSiteLocalAddress()) {
                        ip += inetAddress.getHostAddress();
                    }
                }
            }

        } catch (SocketException e) {
            e.printStackTrace();
            ip += "Something Wrong! " + e.toString() + "\n";
        }

        return ip;
    }

    public boolean isRunning() {
        return running;
    }
}

Its started on a new thread from my GUI Form using this function:

button.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent evt) {
         buttonActionPerformed(evt);
    }
);

And then buttonActionPerformed() is this:

private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
    if (!server.isRunning()) {
        Runnable r = new Runnable() {
            public void run() {
                server.Start();
            }
        };
        new Thread(r).start();

        button.setText("Stop Server");
        serverStatus.setText("Server: Started");
    } else {
        server.Stop();

        button.setText("Start Server");
        serverStatus.setText("Server: Stopped");
    }
}

The error only appears when I stop the server when no clients have connected. But when a client connects, then disconnects, I don't get that error. It properly closes it, I just want to make sure that error won't be a serious problem, or if there is an easy way of fixing it.


Answer:

When you start your server, you call serverSocket.accept(). This call blocks thread until a connection is made. And by calling server.stop() you are closing this server socket in another thread. ServerSocket.close() JavaDoc says: Any thread currently blocked in {@link #accept()} will throw a {@link SocketException}.

So thats why you are getting this exception.

I think you can just ignore this exception.

P.S. And you should make your boolean running volatile.

Question:

In spring integration I have a simple tcp client pipe: a gateway, a tcp outbound gateway a service activator plus an error channel. In the tcp-connection-factory there is a simple interceptor. The error channel very simple, I implemented the tcp-connection-event-inbound-channel-adapter with this filter:

  • org.springframework.integration.ip.tcp.connection.TcpConnectionExceptionEvent.

So my error handler very simple,looks like this :

public class TcpErrorHandler {
    public void onException(){
        System.out.println("Exception!!! ");
    } 
}

It works, because when I have a Socket close Exception ( the server side I close the connection ) , the application writes "Exception!!!" to the console, but other hand, it doesn't work, when I have connection time out exception. My questions are : How do I get all most relevant exceptions for me:

  • Runtime Socket close Exception
  • Connection time out exception
  • Other exceptions

Are there any catching mechanism ?

Here is a snipet from my bean config:

<!-- Client side -->

<int:gateway id="gw"
    service-interface="hu.gmxdev.climaxreplica.service.SimpleGateway"
    default-request-channel="outputchannel" />

<int-ip:tcp-connection-factory id="client"
    type="client" host="localhost" port="10001" single-use="true"
    so-timeout="2000" deserializer="climaxDeserializer"
    interceptor-factory-chain="customInterceptorFactoryChain"/>

<int:channel id="outputchannel" />

<int-ip:tcp-outbound-gateway id="outGateway"
    request-channel="outputchannel" reply-channel="replychannel"
    connection-factory="client" request-timeout="2000" reply-timeout="2000" />

<int:service-activator input-channel="replychannel"
    method="reply" ref="echoService" id="serviceactivator">
</int:service-activator>

<int:channel id="replychannel"></int:channel>

<bean id="customInterceptorFactoryChain"
        class="org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactoryChain">
        <property name="interceptors">
            <array>
                <bean class="hu.gmxdev.climaxreplica.service.CustomInterceptorFactory"/>
            </array>
        </property>
</bean>

<!-- Error channel -->

<int-ip:tcp-connection-event-inbound-channel-adapter id="event"
    error-channel="errorChannel"
    event-types="org.springframework.integration.ip.tcp.connection.TcpConnectionExceptionEvent" />

<int:channel id="errorChannel"></int:channel>

<int:service-activator ref="tcpErrorHandler" method="onException"
    input-channel="errorChannel">
</int:service-activator>

And here is my error handler :

public class TcpErrorHandler {
    @Autowired
    private ApplicationContext appContext;

    public void onException(TcpConnectionExceptionEvent event){
        MainService mainService = appContext.getBean(MainService.class);
        mainService.setSuccess(3);
        System.out.println("Exception!!! ");
        System.out.println(event.getCause().getMessage());
    }
}

The interceptor is here :

public class CustomInterceptor extends TcpConnectionInterceptorSupport{

    public CustomInterceptor () {
        System.out.println("catched_constructor1");
    }

    public CustomInterceptor (ApplicationEventPublisher applicationEventPublisher) {
        super(applicationEventPublisher);
        System.out.println("catched_constructor");
    }

    @Override
    public boolean onMessage(Message<?> message) {
        System.out.println("catched_message");
        return super.onMessage(message);
    }


    @Override
    public void send(Message<?> message){
        System.out.println("catched_send");
        MessageHeaders mh = message.getHeaders();
        try {
            super.send(message);
        }
        catch (Exception e) {
            System.out.println("catched_send_exception");
        }
    }

    @Override
    public void close() {
        String id = getConnectionId();
        System.out.println("catched_closed" + id);
        super.close();
    }

}

And my "caller" :

success = gateway.send("fooooooo");

Answer:

You can define an error channel, that you provide to your inbound adapter. Here is an example:

    <int:channel id="error-channel"></int:channel>
    <int-ws:inbound-gateway id="gateway" error-channel="error-channel"
    request-channel="in"  marshaller="marshaller" unmarshaller="marshaller"
    reply-channel="out" />

Now all exception that are thrown downstream will be catched by this error-channel. You can then define a service activator with this error channel as an input:

 <int:service-activator  input-channel="error-channel"
        ref="exceptionHandler" method="handleError" output-channel="outError"></int:service-activator>

And this activator refers to a bean that defines error handling logic.

Question:

I've created a SpringBoot app. that create a Tcp Connection to accept connections using Spring Tool Suite Version: 3.9.1.RELEASE and using Spring Integration because provides Channel Adapters for receiving and sending messages over internet protocols This is the main class:

@SpringBootApplication
public class TelefonicaHandlerApplication {

    public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {

        ConfigurableApplicationContext context = SpringApplication.run(TelefonicaHandlerApplication.class, args);
        Socket socket = SocketFactory.getDefault().createSocket("localhost", 9999);
        socket.getOutputStream().write("foo\r\n".getBytes());
        socket.close();
        Thread.sleep(1000);
        context.close();
    }

    @Bean
    public TcpNetServerConnectionFactory cf() {
        return new TcpNetServerConnectionFactory(9999);
    }

    @Bean
    public TcpReceivingChannelAdapter inbound(AbstractServerConnectionFactory cf) {
        TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
        adapter.setConnectionFactory(cf);
        adapter.setOutputChannel(tcpIn());
        return adapter;
    }

    @Bean
    public MessageChannel tcpIn() {
        return new DirectChannel();
    }

    @Transformer(inputChannel = "tcpIn", outputChannel = "serviceChannel")
    @Bean
    public ObjectToStringTransformer transformer() {
        return new ObjectToStringTransformer();
    }

    @ServiceActivator(inputChannel = "serviceChannel")
    public void service(String in) {
        System.out.println(in);
    }
}

These are the dependencies of the pom.xml file

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

         <dependency>
            <groupId>org.springframework.integration</groupId>
             <artifactId>spring-integration-core</artifactId>
         </dependency>

         <dependency>
                <groupId>org.springframework.integration</groupId>
                <artifactId>spring-integration-ip</artifactId>
            </dependency>

            <dependency>
            <groupId>org.springframework.integration</groupId>
                <artifactId>spring-integration-ws</artifactId>
            </dependency>

            <dependency>
                <groupId>org.springframework.integration</groupId>
                <artifactId>spring-integration-xml</artifactId>
            </dependency>

    </dependencies>

But when I start the app. I got this error:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/integration/context/OrderlyShutdownCapable
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
    at java.lang.Class.getMethod0(Class.java:3018)
    at java.lang.Class.getMethod(Class.java:1784)
    at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: org.springframework.integration.context.OrderlyShutdownCapable
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 19 more

Answer:

The org.springframework.integration.context.OrderlyShutdownCapable is presented in the spring-integration-core and since version 2.2. Since you use Spring Boot I'm pretty sure that it provides for you the proper spring-integration-core dependency anyway.

That might be something wrong with STS - reinstall it. Or indeed that spring-integration-core artifact is broken - you need to clean up your local Maven and redownload all the dependencies.

Question:

Hi everyone thank you for the help beforehand. I wanted to create a simple chat Programm to see how the .net library in java is working. Because I have worked in java only with the javafx interface I decided to use this instead of awt or swt. I'm not sure but maybe the way I give the same controller access to two different .fxml files coud cause the problem.

In the Main.java I load the .fxml files that I use to create the GUI. The logic is mainly in the other classes.

Main.java

package sample;

import TCP.TCP_Server;
import UDP.UDP_Server;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Modality;
import javafx.stage.Stage;

import java.io.IOException;

public class Main extends Application {
    private Stage primaryStage;
    private AnchorPane rootLayout;
    @Override
    public void start(Stage primaryStage) throws Exception{
        this.primaryStage = primaryStage;
        this.primaryStage.setTitle("AddressApp");
        initTest();
    }

    public void initTest()
    {
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(Main.class.getResource("test.fxml"));
            AnchorPane page = (AnchorPane) loader.load();

            Stage dialogStage = new Stage();
            dialogStage.setTitle("Chat Name");
            dialogStage.initModality(Modality.WINDOW_MODAL);
            dialogStage.initOwner(primaryStage);
            Scene scene = new Scene(page);
            dialogStage.setScene(scene);


            Controller controller = loader.getController();
            controller.setStage(primaryStage);
            controller.setMain(this);
//Here I want a Username before someone can send messages or login
            initNamePanel(dialogStage, controller); 

            dialogStage.showAndWait();
            //controller.setServer(server);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//only a panel to enter a chatname
    public void initNamePanel(Stage primaryStage, Controller controller){
        try {
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(Main.class.getResource("ChatNamePanel.fxml"));
            AnchorPane page = (AnchorPane) loader.load();

            Stage dialogStage = new Stage();
            dialogStage.setTitle("Chat Name");
            dialogStage.initModality(Modality.WINDOW_MODAL);
            dialogStage.initOwner(primaryStage);
            Scene scene = new Scene(page);
            dialogStage.setScene(scene);

            Controller crt = controller;
            crt = loader.getController();
            crt.setChatNameStage(dialogStage);

            dialogStage.showAndWait();
        }catch (IOException e){
            e.printStackTrace();
            System.out.print(e);
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}

Controller.java

package sample;

import TCP.TCP_Client;
import TCP.TCP_Server;
import UDP.UDP_Client;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import sample.Main;

import java.net.SocketException;

public class Controller {
    @FXML
    private Label nameLable;
    @FXML
    private TextArea txtArea;
    @FXML
    private TextField inputField;
    @FXML
    private TextField chatnameField;

    private Stage chatNameStage;
    private Stage stage;
    private TCP_Server server;

    private TCP_Client client;

    private Main main;

    public Controller(){}

    public void setStage(Stage stage){this.stage = stage;}
    public void setChatNameStage(Stage stage){this.chatNameStage = stage;}

    @FXML
    public void OKbutton()
    {
        String msg = inputField.getText();
        if(msg != "" || msg != null) {
            client.SendToServer(msg);
//empty the input Field 
            inputField.setText("");
        }
    }

    @FXML
    public void closeButton(){
        client.close();
        stage.close();
    }

    @FXML
    public void setChatName(){
        String name = chatnameField.getText();


        client = new TCP_Client();
        client.setController(this);
        if(name != null || name != "") {
            client.setChatName(name);
            (client).start();
            chatNameStage.close();
        }
        else
            System.out.print("Enter a Name");
    }
    @FXML
    public void closeNamePannel(){
        chatNameStage.close();
        stage.close();
    }

    public void setRecivedMessage(String serverMassege){
        txtArea.appendText(serverMassege); //the exception occures here but the massege was send with the correct login massege so serverMassege is not null

    }


    public void setMain(Main main){
        this.main = main;
    }
//newClient is not in use anymore but I dont want to delete it because of reasons
    @FXML
    public void newClient() {
        main.initTest();
    }

}

TCP_Client.java

package TCP;

import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
import sample.Controller;

import java.net.*;
import java.io.*;


public class TCP_Client  extends Thread{
    private static int serverPort = 4711;
    private static String host = "localhost";
    private Socket myClient;
    private BufferedReader input;
    private BufferedWriter output;
    private Controller controller;
    private boolean wait = true;

    private String chatName;

    public void setChatName(String chatName){
        this.chatName = chatName;
    }

    public TCP_Client(){
        try {
            myClient = new Socket(host, serverPort);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setController(Controller newController){
        controller = newController;
    }
    public void run(){
        createSocketStream();
        login(chatName);
        RecieveFromServer();
    }

    private void createSocketStream()
    {
        try {
            output = new BufferedWriter(new OutputStreamWriter(myClient.getOutputStream()));
            input = new BufferedReader(new InputStreamReader(myClient.getInputStream()));
        } catch (UnknownHostException e) {
            e.printStackTrace();
            System.out.print("Don't know abot host: "+host);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(e);
        }

    }

//is called when I press the OK Button 
    public void SendToServer(String msg){
        try {
            if (msg == null || msg == "")
                return;

            System.out.print(msg);
            output.write(msg);
            output.newLine();
            output.flush();
        }catch (IOException e){
            System.out.println(e);
        }
    }

    //needs to run in a seperate thread so I need to put this in the run methode as I understand it
    private void RecieveFromServer(){
        try {
            String response;
            while (wait) {
                response = input.readLine();
                controller.setRecivedMessage(response);
                if(response == "Quit")
                    break;
            }
        }catch (IOException e){
            System.out.println(e);
        }
    }

    public void close(){
        try {
            wait = false;
          //  System.out.print("Log out");
            output.write("--QUIT");
            output.newLine();
            output.flush();
            output.close();
            input.close();
            myClient.close();
        }
        catch (IOException e)
        {
            System.out.println(e);
        }
    }

    private void login(String name){
        try {
           // System.out.print("Sending: " + name);
            //  output.writeChars(msg);
            output.write("--NAME"+name);
            output.newLine();
            output.flush();
        }catch (IOException e){
            System.out.println(e);
        }
    }
}

TCP_Server.java

package TCP;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;

public class TCP_Server extends Thread{
    private String line;
    private LinkedList<BufferedWriter> outList;
    private LinkedList<Socket> clientList;
    private LinkedList<String> usernameList;
    Socket actClient;
    private BufferedWriter out;
    private BufferedReader in;

    public final static int port = 4711;

    public static void main(String[] args) {
        ServerSocket sSocket;
        LinkedList<BufferedWriter> outs = new LinkedList<BufferedWriter>();
        LinkedList<Socket> clients = new LinkedList<Socket>();
        LinkedList<String> userNames = new LinkedList<String>();

        boolean runServer = true;
        try {
            sSocket = new ServerSocket(port);
            //runServer
            while (System.in.available()==0){
                Socket clientSocket = sSocket.accept();
                (new TCP_Server(outs, clients, userNames, clientSocket)).start();
            }

        }catch (IOException e){
            e.printStackTrace();
            System.out.print(e);
        }

    }

    private TCP_Server(LinkedList<BufferedWriter> outs,  LinkedList<Socket> clients,
                       LinkedList<String> userNames, Socket clientSocket){
        outList = outs;
        clientList = clients;
        usernameList = userNames;
        actClient = clientSocket;
    }
    public void run(){
        try {
            out = new BufferedWriter(new OutputStreamWriter(actClient.getOutputStream()));
            in = new BufferedReader(new InputStreamReader(actClient.getInputStream()));
            line = in.readLine();
            //check if name is allready used
            for(String s : usernameList){
                if(s.equals(line.substring(6)) || line.substring(6).length()<=1){
                    System.out.print("Name schon vergeben oder zu kurz");
                    return;
                }
            }
            //the registration
            if(line.startsWith("--NAME")){
                synchronized (clientList) {
                    for (BufferedWriter o : outList) {
                        //I need the name of the user after the --NAME
                        o.write(line.substring(6) + " hase joint the chat");
                        o.newLine();
                        o.flush();
                    }
                }
                usernameList.add(line.substring(6));
                outList.add(out);
                clientList.add(actClient);
            }
            //when --Quit is send checkout the user
            while ((line =in.readLine()).startsWith("--QUIT") == false){
                if(line != "" || line != null) {
//tell everyone that the user hase left the chat
                    synchronized (clientList) {
                        for (BufferedWriter o : outList) {
                            o.write(line);
                            o.newLine();
                            o.flush();
                        }
                    }
                }
            }
            //chekout
            outList.remove(out);
            clientList.remove(actClient);
            synchronized (clientList) {
                for (BufferedWriter o : outList) {
                    o.write(line.substring(6) + "hase left the chat");
                    o.newLine();
                    o.flush();
                }
            }
            actClient.close();

        }catch (IOException e){
            System.out.print(e);
        }
    }
}

The other clients recive the message that I send over the server but I cannot append the text to the TextArea. Following Exceptions are thrown from the client that recives the message:

Exception in thread "Thread-4" java.lang.NullPointerException
    at sample.Controller.setRecivedMessage(Controller.java:88)
    at TCP.TCP_Client.RecieveFromServer(TCP_Client.java:87)
    at TCP.TCP_Client.run(TCP_Client.java:43)

I know where the error is but how can I solve it? The Code hase some other flaws but I want to deal with it when I solved the problem here described.


Answer:

As James_D allready suggested in a comment the use of the same controller for two different .fxml files caused the problem. The only thing I did was to create a new ChatNameController class and the only thing this class does is checking if the chatname is correct and give this information (String) to the Controller class.

Question:

What is the Safest way to close a socket connection from client side. Shutdown inputs first or close() the connection straight away?


Answer:

If your protocol (top of TCP) does not contain any message/handshake for closing a session, then you must do it by closing TCP connection.

There are two ways to close a TCP connection:

  • graceful: uses TCP SYN, all undelivered data is transferred (tried). read() of InputStream returns -1;
  • ungraceful: uses TCP RST, all undelivered data is discarded. read() of InputStream throws an exception.

Both can be done in java with close() function of Socket. Graceful is the default. Ungraceful, if setsolinger(true,0); is done before the close().

Question:

When I call the REST API request I'm getting the following error message:

java.net.SocketException: socket failed: EPERM (Operation not permitted)

Answer:

this happened due to some uncleared memory or cache of emulator. uninstall and rerun the program, this was fixed. also the rest api url must be https.