Search code examples
javamultithreadingsocketstcpserversocket

Socket Server Client Thread, Java


I was asking before this Question...

I want to test the TCP Socket Behaviour in my Network, beacuse I need to test my Java Applications...

I created a Server Client Model Example, using Threads...

Here the ConsumerServer

  public class ConsumerServer extends Thread {
    private ServerSocket SrvrScktConsumer;
    Socket clientSocket = null;
    private boolean isConsumerRunning = false;

    public ConsumerServer(int ConsPort) {
      try {
        SrvrScktConsumer = new ServerSocket(ConsPort);
        System.out.println(NL + "ConsumerServer Listening on port number: " + ConsPort);
      } catch (IOException e) { }
    }

    @Override public void run() {
      try {
        clientSocket = SrvrScktConsumer.accept();
        InputStream input;
        byte[] innerBytes = new byte[1024];
        try {
          input  = clientSocket.getInputStream();
          Integer iRemotePort = clientSocket.getPort();
          String sRemoteHost = clientSocket.getInetAddress().getHostAddress();
          System.out.println("ConsumerServer: Remote Connection\n\tPort:" + iRemotePort+ " Host:" + sRemoteHost);
          isConsumerRunning = true;
          while (isConsumerRunning) {
            try {
              byte[] incomingBytes = Arrays.copyOf(innerBytes, input.read(innerBytes));
              jtaMessages.append(NL + "Consumer GET " + new String(incomingBytes));
              jtfLastReceived.setText(new String(incomingBytes));
            } catch (IOException | NegativeArraySizeException | IndexOutOfBoundsException e) {
              isConsumerRunning = false;
            }
          }
          System.out.println(NL + "ConsumerClient closing from Host " + sRemoteHost + " Port " + iRemotePort);
          try {  if (input != null) input.close(); } catch (IOException e) { }
        } catch (IOException e) {
          System.out.println(NL + "Error Creating ConsumerClient\n\t:" + e.toString());
        }
      } catch (IOException | NullPointerException e) {
          System.out.println(NL + "ConsumerServer Stopped: " + e.toString()) ;
      }
      System.out.println(NL + "Exiting ConsumerServer...");
    }

    public void stopServer() {
      try {
        SrvrScktConsumer.close();
      } catch (IOException | NullPointerException e) { }
      try {
        clientSocket.close();
      } catch (IOException | NullPointerException e) { }
      isConsumerRunning = false;
    }
  };

Here the ProducerClient

  public class ProducerClient extends Thread {
    private Socket clientSocket = null;
    private OutputStream output = null;
    private boolean isProducerRunning = false;

    public ProducerClient(String ConsHost , int ConsPort) {
      try {
        clientSocket = new Socket(ConsHost, ConsPort);
        output = clientSocket.getOutputStream();
        System.out.println(NL + "ProducerClient Connected to port number: " + ConsPort);
      }
      catch (IOException e) { }
    }

    @Override public void run() {
      if (!(clientSocket == null)) {
        Integer iLocalPort = clientSocket.getLocalPort();
        String sLocalHost = clientSocket.getLocalAddress().getHostAddress();
        System.out.println("ConsumerServer: Local Connection\n\tPort:" + iLocalPort+ " Host:" + sLocalHost);
        int ctrlPrintOut = 0, ctrlPrintIn = 0;
        isProducerRunning = true;
        while (isProducerRunning) {
          try {
            if (bProducerReady) {
              bProducerReady = false;
              output.write(jtfSendMessage.getText().getBytes());
              jtaMessages.append(NL + "Producer PUT " + jtfSendMessage.getText());
              jtfSendMessage.setText("");
            }
//            // Ini Code Block to delete
//            else {
//              try {
//                Thread.sleep(1);
//              } catch (InterruptedException ex) { }
//              if (ctrlPrintOut == 1000000 /*Integer.MAX_VALUE*/) {
//                if (ctrlPrintIn == 2) {
//                  System.out.println("ProducerClient Waiting!");
//                  ctrlPrintIn = 0;
//                }
//                ctrlPrintIn++; ctrlPrintOut = 0;
//              }
//              ctrlPrintOut++;
//            }
//            // End Code Block to delete
          } catch (IOException e) {
            System.out.println("ProducerClient: " + e.toString());
            isProducerRunning = false;
          }
        }
        try { output.close(); } catch (IOException e) { }
        try { clientSocket.close(); } catch (IOException e) { }
        System.out.println(NL + "Exiting ProducerClient...");
      }
    }

    public void stopClient() {
      try {
        clientSocket.close();
      } catch (IOException | NullPointerException e) { }
      isProducerRunning = false;
    }
  };

I want to remove the indicated block code, but when I remove.. My Test doesn't work properly.

Here the Class using before Classes

public class ClientServerShort extends JFrame {

  private JButton jbSendMessage = new JButton("Send Message");
  private JLabel jlLastReceived = new JLabel("Last Received");
  private JTextArea jtaMessages = new JTextArea(5,20);
  private JScrollPane jspMessages = new JScrollPane(jtaMessages);
  private JToggleButton jtbConsumer = new JToggleButton("Launch Consumer Server");
  private JToggleButton jtbProducer = new JToggleButton("Launch Producer Client");
  private JTextField jtfLastReceived = new JTextField();
  private JTextField jtfSendMessage = new JTextField();

  static boolean bProducerReady = false;
  static final String NL = System.getProperty("line.separator");
  ConsumerServer thrdConsumerServer = null;
  ProducerClient thrdProducerClient = null;

  public ClientServerShort() {
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

    jbSendMessage.addActionListener((ActionEvent evt) -> {
      if (!jtfSendMessage.getText().isEmpty()) {
        bProducerReady = true;
      }
    });

    jlLastReceived.setBorder(BorderFactory.createEtchedBorder());
    jlLastReceived.setHorizontalAlignment(SwingConstants.CENTER);

    jtbConsumer.addActionListener((ActionEvent evt) -> {
      if (jtbConsumer.isSelected()) {
        if (thrdConsumerServer == null) {
          thrdConsumerServer = new ConsumerServer(1027);
          thrdConsumerServer.start();
        }
      } else {
        if (thrdConsumerServer != null) {
          thrdConsumerServer.stopServer();
          thrdConsumerServer = null;
        }
      }
    });
    jtbProducer.addActionListener((ActionEvent evt) -> {
      if (jtbProducer.isSelected()) {
        if (thrdProducerClient == null) {
          thrdProducerClient = new ProducerClient("192.168.0.49", 1027);
          thrdProducerClient.start();
        }
      } else {
        if (thrdProducerClient != null) {
          thrdProducerClient.stopClient();
          thrdProducerClient = null;
        }
      }
    });

    jtfLastReceived.setEditable(false);

    JPanel jpMessagesUp = new JPanel();
    jpMessagesUp.setLayout(new GridLayout(2, 2, 6, 6));
    jpMessagesUp.add(jbSendMessage);
    jpMessagesUp.add(jtfSendMessage);
    jpMessagesUp.add(jlLastReceived);
    jpMessagesUp.add(jtfLastReceived);

    getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
    add(jtbProducer);
    add(jtbConsumer);
    add(jpMessagesUp);
    add(jspMessages);
    pack();
  }

  public static void main(String args[]) {
    EventQueue.invokeLater(() -> {
      new ClientServerShort().setVisible(true);
    });
  }

}

Question:

What is the reason, why I remove the indicate snippet code (in ProducerClient), my Single App doesn't work?


Solution

  • The reason is exactly what I told you in your other question. bProducerReady needs to be volatile, as you are reading and writing it from different threads. Your strange delay code accomplishes the same memory flush just via elapse of time.

    NB It does not need to be static.

    Why you reposted this answered question remains a mystery.