Hi i am trying to get some data about a socket client connecting to a mutltythreaded server process in the same machine. The server thread is triggered correctly and the client ip is retreived ok, but i cant seem to be able to send a string through the connection. THE CLIENT
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package solverapplet; import java.io.DataInputStream; import java.io.IOException; import java.io.PrintStream; import java.net.Socket; import java.net.UnknownHostException; import java.util.logging.Level; import java.util.logging.Logger; import java.io.*; /** * * @author me */ public class Solverapplet { /** * @param args the command line arguments */ public static void main(String[] args) { // TODO code application logic here Socket s; try { s = new Socket("IP", 4445); System.out.println(s.getPort()); //DataInputStream in = new DataInputStream (s.getInputStream()); BufferedWriter out = new BufferedWriter( new OutputStreamWriter(s.getOutputStream())); out.write("gamma"); out.newLine(); out.flush(); } catch (UnknownHostException ex) { Logger.getLogger(Solverapplet.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Solverapplet.class.getName()).log(Level.SEVERE, null, ex); } } }
THE SERVER THREAD
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package serversideserver; import java.io.*; import java.net.*; import java.security.*; import java.util.List; import java.sql.*; import com.google.gson.Gson; class doComms implements Runnable { private Socket server; private String line,input,ip; doComms(Socket server, String ip) { this.server=server; this.ip=ip; } public void run () { input=""; try { // Get input from the client BufferedReader in = new BufferedReader( new InputStreamReader(server.getInputStream())); PrintStream out = new PrintStream(server.getOutputStream()); Connection conn = null; try { String userName = "root"; String password = ""; String url = "jdbc:mysql://localhost/test"; Class.forName ("com.mysql.jdbc.Driver").newInstance (); conn = DriverManager.getConnection (url, userName, password); System.out.println ("Database connection established"); // create the java statement Statement st = conn.createStatement(); // ResultSet rs; while((line = in.readLine()) != null && !line.equals(".")) { // Now do the magic. //Data data = new Gson().fromJson(line, Data.class); System.out.println("LINE: " + line); input=line; st.executeUpdate("UPDATE `solvers` SET `online`='1',`ip`='"+ server.getInetAddress().toString().substring(1) +"' WHERE `user`='"+ line +"'"); // input= data.getcmd(); out.println("{"captcha":1,"text":"abc","is_correct":"true"}"); } } catch (Exception e) { System.out.println (e.toString()); } // Now write to the client System.out.println("UPDATE `solvers` SET `online`='1',`ip`='"+ server.getInetAddress() +"' WHERE `user`='"+ input +"'"); //out.println("Overall message is:" + input); server.close(); } catch (IOException ioe) { System.out.println("IOException on socket listen: " + ioe); ioe.printStackTrace(); } } }
The line sent through is empty. CONNECTION ESTABLISHED
package serversideserver; import java.io.*; import java.net.*; import java.security.*; import java.sql.*; /** * Title: Sample Server * Description: This utility will accept input from a socket, posting back to the socket before closing the link. * It is intended as a template for coders to base servers on. Please report bugs to brad at kieser.net * Copyright: Copyright (c) 2002 * Company: Kieser.net * @author B. Kieser * @version 1.0 */ public class Serversideserver { private static int port=4445,portsolver=4445, maxConnections=0; // Listen for incoming connections and handle them public static void main(String[] args) { int i=0; try{ ServerSocket listener = new ServerSocket(port); Socket server; long counter=0; int counter1=0; int id=0; String ip="uninit"; while((i++ < maxConnections) || (maxConnections == 0)){ server = listener.accept(); counter++; doComms conn_c= new doComms(server,ip); Thread t = new Thread(conn_c); t.start(); //System.out.println("counter "+ (counter % id) ); } } catch (IOException ioe) { System.out.println("IOException on socket listen: " + ioe); ioe.printStackTrace(); } } }
Advertisement
Answer
I looks like you’ve got a bit of a timing issue. The following is your code with correct timing. Note that I removed code unnecessary to the issue at hand.
Client: It looks like in the client, you were writing to the socket and immediately terminating the application (causing the connection to close). The doComms class was writing back to the client so I’ve added code to read the response. If, however, you were not expecting a response, you would still want to read in a byte. This will allow you to make sure you got the EOF rather than some data, and it blocks the current thread and keeps the connection alive.
package solverapplet; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.util.logging.Level; import java.util.logging.Logger; import java.io.*; /** * * @author you */ public class Solverapplet { /** * @param args the command line arguments * @throws IOException */ public static void main(String[] args) throws IOException { Socket s = null; try { // make connection s = new Socket("localhost", 4445); // define streams BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); // write data out.write("gamma"); out.newLine(); out.flush(); // read response String returnData = in.readLine(); System.out.println(returnData); } catch (UnknownHostException ex) { Logger.getLogger(Solverapplet.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Solverapplet.class.getName()).log(Level.SEVERE, null, ex); } finally { // close connection s.close(); } } }
Server: I’ve changed the server to allow a maximum number of connections at any given time rather than shutting down after the maximum number of connections has been established. Also, note that I the threads are not daemons. If you want to serve X number clients then shutdown, you need a mechanism to allow the threads to continue executing before shutting down ServerSocket
package serversideserver; import java.io.*; import java.net.*; /** * Title: Sample Server * Description: This utility will accept input from a socket, posting back to the socket before closing the link. * It is intended as a template for coders to base servers on. Please report bugs to brad at kieser.net * Copyright: Copyright (c) 2002 * Company: Kieser.net * @author B. Kieser * @version 1.0 */ public class Serversideserver { private static int port =4445; private static int maxConnections =10; private static int connections = 0; synchronized static void connectionClosed() { connections--; Serversideserver.class.notify(); } /** * The blocking mechanism to only allow <code>maxConnections<code> * @throws InterruptedException * thrown if blocking thread is interupted */ private synchronized static void nextConnection() throws InterruptedException { while(connections>=maxConnections) { Serversideserver.class.wait(); } } public static void main(String[] args) throws InterruptedException { try{ // server socket ServerSocket listener = new ServerSocket(port); // socket Socket socket; // Keep the server alive while(true){ // Blocks if we have reached the max nextConnection(); // Accept connection to client socket = listener.accept(); // define request service doComms conn_c= new doComms(socket,socket.getInetAddress().getCanonicalHostName()); Thread t = new Thread(conn_c); t.setDaemon(false); // run request service t.start(); } } catch (IOException ioe) { System.out.println("IOException on socket listen: " + ioe); ioe.printStackTrace(); } } }
doComms: Not much has changed with this class… I just cleaned it up a bit and removed unnecessary lines of code.
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package serversideserver; import java.io.*; import java.net.*; class doComms implements Runnable { private Socket socket; private String ip; doComms(Socket socket, String ip) { this.socket = socket; this.ip = ip; } public void run () { try { // Define input/output BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream out = new PrintStream(socket.getOutputStream()); // Process requests until the EOF is found String line; while((line = in.readLine()) != null && !line.equals(".")) { // print input System.out.println("LINE: " + line); // print process line System.out.println("UPDATE `solvers` SET `online`='1',`ip`='"+ ip +"' WHERE `user`='"+ line +"'"); // write response out.println("{"captcha":1,"text":"abc","is_correct":"true"}"); } socket.close(); } catch (IOException ioe) { System.out.println("IOException on socket listen: " + ioe); ioe.printStackTrace(); } finally { Serversideserver.connectionClosed(); } } }
Hope this helps 🙂