The app gets stuck in serverSocket.accept () and gives the address of the binding exception which is already used in the second call to the thread

I have two problems with an application I created for socket communication, first I will try to explain what the application does and then I will go into the details of these two problems. First, I click a button that starts a thread that sends the multicast address over a UDP socket. As soon as any of the devices receive the massage, they will send a response over the TCP socket and my device will act as a server to the one that sent the response. So after debugging, I found that the first problem clientSocket = serverSocket.accept();

sometimes gets stuck and the application will block everything and keep doing it, which can happen because the udp massage may never reach its destination, which means there is no client for tcp which I created.

First question: is there a way to make it serverSocket.accept();

non-blocking or set a timeout? I tried the method serverSocket.setTimeSoOut()

but it didn't work. Maybe this issue is coming from something other than the UDP message?

The second problem is that if I click a button that calls the thread twice, it will throw the already used BindException address: what happens because of the repeated execution serverSocket.bind(new InetSocketAddress(4125));

. Is there a way to fix / avoid this?

These are the themes I use: This call is called after the button is clicked:

 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 call 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();
         }
        }


       }

      }



     }

      

+3


source to share


2 answers


These are two problems with the message. I will answer two in reverse order.

  • The button you are talking about creates a ServerSocket and binds it to a specific port. In your case, port is 4125. From looking at your code, you don't seem to be shutting down that backend server anywhere. When you click the button a second time, the second ServerSocket instance tries to bind to the same port, but that port is still in use by the first ServerSocket. In this case, you get a bind exception. One port cannot be used by more than one server. The solution would be to close the existing ServerSocket before creating a new one withserverSocket.close();

  • If you're reading the documentation , it clearly states what ServerSocket.accept () does: "[...] Method blocks until connected." This is the "stuck" you described. The thread that executes this code is placed in a pending position and continues only when a connection is created, and then returns that new connection. The classic approach is to start a new thread waiting for incoming connections so that your main thread continues to run and your entire application does not hang. Another approach would be a non-blocking framework that encapsulates whatever is overhead from you, one of which is Apache MINA .



I'd really like to take a look at small sample projects that deal with basic client / server behavior, as you will most likely be handling themes here.

+1


source


First problem: it is very likely that your application is not receiving UDP packets. If serverSocket.accept () does not receive any clients, it will wait indefinitely for someone to connect. You can avoid this by using another thread that just accepts connections so that your application doesn't freeze. Another way would be to use Java NIO classes, which provide non-blocking IO for pretty much anything. This will require you to use ServerSocketChannel and related classes. (A quick googling also gave me this tutorial , which seems pretty simple to follow).



Second problem: you need to close your ServerSocket when you're done with it. Otherwise, the port will never be available again for use by another server. Alternatively, you can just leave the Socket open and remember that you are already opening it (for example with a boolean field of your class).

0


source







All Articles