4 Replies Latest reply: Jun 6, 2013 3:17 PM by jsmith RSS

    Initialising a connection to a socket server

    abg
      Hi
      I am developing an application that is an on-line temperature & humidity monitoring system. A customer has the
      requirement for data to be sent to his socketServer every hour. The code below works fine as long as the
      serverSocket program is running but crashes on the new Socket instruction if the interconnection is not there.

      The uploadToSocket method is called from a timeline every hour or from a button to test the system.

      I have tried to make sense of the literature on the subject but there seems to be a number of different
      solutions all with examples that are more complex than I need and are difficult to follow. I seem to have to
      run in a different thread and words like tasks and servers are used although one tutorial used listeners. Does
      anyone have a simple solution to this.
         // socket for connection to server
         static private Socket socket = null ;
      
          // for writing to the server
         static PrintWriter out = null;
      
          static boolean initSocket(){
              boolean bOK = true ;
              try {
                  socket = new Socket(sSocket, Integer.parseInt(sPort));
      //            socket = new Socket("192.168.1.102", 4444);
                  out    = new PrintWriter(socket.getOutputStream(),true);
                  Ecowand3.lSocket.setText("Socket");  // to say socket is active
              }
              catch (Exception ex) { ex.printStackTrace();
                  Ecowand3.lSocket.setText("Socket not found"); 
                  System.err.println("no socket");
                  bOK = false ;
              }
             return bOK ;
               
          }
          
          static void uploadToSocket(boolean demoMode){
              if (!demoMode){
                  boolean bSocketOK = initSocket();
      System.out.println("In upload " + bSocketOK);
                  if (bSocketOK){
                  try (BufferedReader br = new BufferedReader(new FileReader("socketdata.csv")))
              {
      System.out.println("Trying  upload");
                  String sCurrentLine ;
                  while ((sCurrentLine = br.readLine()) != null){
                      System.out.println(sCurrentLine + " upload");
                      out.println(sCurrentLine);
                  }
                  br.close();
                  socket.close();
                  out.close();
                  File f = new File("socketdata.csv");
                  boolean bD = f.delete();
      System.out.println("file deleted = " + bD);
              }
              catch(IOException e) { System.err.println("Eco-wand - error with Reading Socket File");}
      
              }  
              }
          }
      Thanks

      ABG
        • 1. Re: Initialising a connection to a socket server
          EJP
          crashes
          No it doesn't. It gets an IOException and prints it. There are some strange things about this code, such as making the socket static, but I can't see that it crashes.
          • 2. Re: Initialising a connection to a socket server
            abg
            Sorry, I used the wrong word there. It doesn't actually crash, it goes back to the start of the program

            abg
            • 3. Re: Initialising a connection to a socket server
              EJP
              So what's your question?

              EDIT: I would certainly get rid of the static variables. Do it all in one method with local variables for the socket and the streams, and get rid of all the OK's and 'did' and 'didn't' status variables. Use the exceptions to tell you whether you succeeded. Just create the socket, get the streams, do the copy, all in the same block, and put a catch handler after the whole thing whose only job is logging and closing the socket.
              • 4. Re: Initialising a connection to a socket server
                jsmith
                Here is one way to do this. The code below neither crashes nor throws an exception for me. Perhaps you could study the code below and apply some of the concepts to your case.
                import java.io.IOException;
                import java.net.ConnectException;
                import java.net.InetSocketAddress;
                import java.nio.*;
                import java.nio.channels.*;
                import java.nio.charset.*;
                import java.text.*;
                import java.util.*;
                import javafx.application.Application;
                import static javafx.application.Application.launch;
                import javafx.scene.Scene;
                import javafx.scene.control.*;
                import javafx.stage.*;
                import java.util.Timer;
                import java.util.logging.*;
                import javafx.event.*;
                import javafx.geometry.Pos;
                import javafx.scene.layout.VBox;
                
                public class PingApp extends Application {
                  private static final DateFormat TIMESTAMP_FORMAT = new SimpleDateFormat("HH:mm:ss.SSS");
                  
                  private static final int PORT = 8442;
                  
                  private Client client = new Client("localhost", PORT);
                  private Server server = new Server("localhost", PORT);
                  
                  @Override public void start(Stage stage) {
                    server.start();
                    
                    Button pingButton = new Button("Ping Now");
                    pingButton.setOnAction(new EventHandler<ActionEvent>() {
                      @Override public void handle(ActionEvent event) {
                        client.pingNow();
                      }
                    });
                    
                    Button startServer = new Button("StartServer");
                    startServer.setOnAction(new EventHandler<ActionEvent>() {
                      @Override public void handle(ActionEvent event) {
                        server.start();
                      }
                    });
                    
                    Button stopServer = new Button("StopServer");
                    stopServer.setOnAction(new EventHandler<ActionEvent>() {
                      @Override public void handle(ActionEvent event) {
                        server.stop();
                      }
                    });
                
                    VBox layout = new VBox(10);
                    layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10px;");
                    layout.setAlignment(Pos.CENTER);
                    layout.getChildren().setAll(
                      startServer,
                      stopServer,
                      pingButton
                    );
                    
                    stage.setScene(new Scene(layout));
                    
                    stage.show();
                  }
                  
                  class Client {
                    private final CharsetEncoder encoder = Charset.forName("US-ASCII").newEncoder();
                    private final InetSocketAddress address;
                    
                    private static final int MILLISECONDS_PER_PING = 5 * 1000;
                
                    public Client(String hostname, int port) {
                      address = new InetSocketAddress(hostname, port);
                      new Timer("sched-comm").scheduleAtFixedRate(pingTask, 0, MILLISECONDS_PER_PING);
                    }
                    
                    public void pingNow() {
                      Thread thread = new Thread(pingTask, "adhoc-comm");
                      thread.setDaemon(true);
                      thread.start();
                    }
                    
                    private final TimerTask pingTask = new TimerTask() {
                      private int nCalls = 0;
                      
                      @Override public void run() {
                        doPing();
                      }
                
                      private synchronized void doPing() {
                        try (SocketChannel channel = SocketChannel.open()) {
                          String msg = createLogMessage("Ping " + nCalls++);
                          channel.connect(address);
                          System.out.println(createLogMessage("send => '" + msg + "'"));
                          channel.write(encoder.encode(CharBuffer.wrap(msg)));
                        } catch (ConnectException c) {
                          System.out.println(createLogMessage("ping failed => 'Unable to Connect to " + address + "'"));
                        } catch (IOException ex) {
                          Logger.getLogger(PingApp.class.getName()).log(Level.SEVERE, null, ex);
                        }
                      }
                    };
                  }
                  
                  class Server {
                    private final CharsetDecoder decoder = Charset.forName("US-ASCII").newDecoder();
                    
                    private final InetSocketAddress address;
                    private Thread thread;
                    private boolean shuttingDown = false;
                    
                    private final Runnable serverTask = new Runnable() {
                      @Override public void run() {
                        ServerSocketChannel server;
                        try {
                          server = ServerSocketChannel.open();
                          server.socket().bind(address);
                        } catch (IOException ex) {
                          Logger.getLogger(PingApp.class.getName()).log(Level.SEVERE, null, ex);
                          return;
                        }
                
                        ByteBuffer incoming = ByteBuffer.allocateDirect(1024);
                        incoming.clear();
                        while (true) { 
                          try (SocketChannel channel = server.accept()) {
                            if (Thread.currentThread().isInterrupted()) {
                              return;
                            }
                            channel.read(incoming);
                            incoming.flip();
                            CharBuffer charBuffer = decoder.decode(incoming);
                            System.out.println(createLogMessage("received => '" + charBuffer.toString() + "'"));
                            incoming.compact();
                          } catch (ClosedByInterruptException ie) {
                            return;
                          } catch (IOException ex) {
                            Logger.getLogger(PingApp.class.getName()).log(Level.SEVERE, null, ex);
                          }
                        }
                      }
                    };
                
                    public Server(String hostname, int port) {
                      address = new InetSocketAddress(hostname, port);
                    }
                
                    synchronized private void start() {
                      System.out.println("Server started");
                      if (thread == null) {
                        thread = new Thread(serverTask, "server");
                        thread.start();
                      }
                    }
                
                    synchronized private void stop() {
                      System.out.println("Server shutting down");
                      if (thread != null && !shuttingDown) {
                        shuttingDown = true;
                        thread.interrupt();
                        Thread shutdownWaiter = new Thread(new Runnable() {
                          @Override
                          public void run() {
                            try {
                              thread.join();
                              thread = null;
                              shuttingDown = false;
                            } catch (InterruptedException ex) {
                              // no action required.
                            }
                            System.out.println("Server shutdown");
                          }
                        }, "shutdown waiter");
                        shutdownWaiter.setDaemon(true);
                        shutdownWaiter.start();
                      }
                    }
                  }
                 
                  private String createLogMessage(String message) {
                    return
                      TIMESTAMP_FORMAT.format(new Date()) + " " +
                      Thread.currentThread().getName() + 
                      " " +
                      message;
                  }
                  
                  public static void main(String[] args) { launch(args); }
                }