Socket not receiving or sending message from/to server - java

I'm implementing a Java multi threaded server that receive messages from a client and broadcast them to the other clients, but it's not working. The server receives the client messages only when the client application closes (the client socket closes). The application is divided in two modules: client and the server. The code is a little bit long, I know that is annoying to read all, but please help me to solve this problem.
Here is the GitHub application link to facilitate the reading. Please checkout the test branch.
The server module classes:
GameServer.java
/*
* This file contains the application core server responsible to wait and accept clients connections requests.
* */
package server;
import com.sun.istack.internal.NotNull;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* #author Michael Pacheco <b>pacheco#decom.ufop.br</b>
* #version 1.0
*
* This class is responsible to receive clients connections and send messages to them.
* */
public class GameServer implements Runnable {
/**
* The port number used to start the server.
* */
private int port;
/**
* The socket used to accept clients connections.
* */
private ServerSocket serverSocket;
/**
* A {#link Logger} used to print messages for debug purpose.
* */
private final static Logger LOGGER = Logger.getLogger(GameServer.class.getName());
/**
* A hash set to store the clients sockets
* */
private HashSet<Socket> clientsSockets;
private GameServer() {
clientsSockets = new HashSet<>();
}
/**
* Instantiates a new {#link GameServer} with a given port number.
* #param port the port number used to start the server.
* */
public GameServer(int port) {
this();
this.port = port;
}
/**
* Override method from Runnable. This method is called when an attempt to close the application occur.
* */
#Override
public void run() {
Scanner s = new Scanner(System.in);
while (s.hasNext()) s.nextLine();
shutdown();
}
/**
* Start the server and listen for clients connections requests.
* */
public void start () {
try {
LOGGER.log(Level.INFO, "Trying to start the server...\n");
serverSocket = new ServerSocket(this.port);
final String ip = InetAddress.getLocalHost().getHostAddress();
LOGGER.log(Level.INFO, "Server started!\n\tPort: {0}\n\t IP: {1}\n", new Object[] {port, ip});
LOGGER.log(Level.INFO, "Press Ctrl-D to shutdown the server!\n");
waitForConnections();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Failed to initialize the server! {0}\n", e.getMessage());
e.printStackTrace();
}
}
/**
* Wait for clients connections requests
* */
private void waitForConnections() {
new Thread(this).start();
try {
//noinspection InfiniteLoopStatement
while (true) {
Socket clientSocket = serverSocket.accept();
LOGGER.log(Level.INFO, "New client connected! {0}\n", clientSocket);
clientSocket.getOutputStream().write("You're now connected to the server\n".getBytes());
clientSocket.getOutputStream().flush();
allocateClient(clientSocket);
}
} catch (IOException e) {
// No need for printing stacktrace if the serverSocket was closed by the shutdown method
if (!serverSocket.isClosed())
e.printStackTrace();
}
}
/**
* This method is responsible to delegate the communication with the client to the {#link ClientListener}.
* #param clientSocket the client socket to delegate.
* */
private void allocateClient(#NotNull Socket clientSocket) {
clientsSockets.add(clientSocket);
new Thread(new ClientListener(clientSocket, this)).start();
}
/**
* Shutdown the server
* */
private void shutdown () {
try {
LOGGER.log(Level.INFO, "Trying to shutdown the server...\n");
// TODO Clear resources
for (Socket soc : clientsSockets) removeClient(soc);
serverSocket.close();
LOGGER.log(Level.INFO, "Server successfully shut down!\n");
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Failed to shutdown the server! {0}\n", e.getMessage());
e.printStackTrace();
}
}
/**
* Send a message to a single client.
* #param message the message to be sent.
* #param clientSocket the socket of the client that will receive the message
* */
private void sendMessage (#NotNull Object message, #NotNull Socket clientSocket) {
try (PrintWriter writer = new PrintWriter(clientSocket.getOutputStream(), true)) {
writer.println(message);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Send a message to all clients except the given one.
* #param message the message to be sent.
* #param excludedClient the client that won't receive the message.
* */
void broadcast (#NotNull Object message, #NotNull Socket excludedClient) {
for (Socket client : clientsSockets) {
if (excludedClient == client)
continue;
sendMessage(message, client);
}
}
/**
* Remove the given client from server.
* #param clientSocket the client to be removed.
* */
void removeClient (#NotNull Socket clientSocket) {
try {
clientSocket.close();
clientsSockets.remove(clientSocket);
LOGGER.log(Level.INFO, "Client removed! {0}\n", clientSocket);
// TODO broadcast the client disconnection
} catch (IOException e) {
e.printStackTrace();
}
}
}
ClientListener.java
package server;
import com.sun.istack.internal.NotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* #author Michael Pacheco <b>pacheco#decom.ufop.br</b>
* #version 1.0
*
* This class is responsible to listen messages of a single client and send them to the server and then to the other clients.
* */
public class ClientListener implements Runnable {
/**
* The socket used to communicate with the delegated client.
* */
private Socket clientSocket;
/**
* A reference to the {#link GameServer} used to call the {#link GameServer} broadcast method.
* #see GameServer
* */
private GameServer server;
/**
* A {#link Logger} used to print messages for debug purpose.
* */
private final static Logger LOGGER = Logger.getLogger(ClientListener.class.getName());
/**
* Instantiate a new {#link ClientListener} with a given client socket.
*
* #param clientSocket the socket of the delegated client.
* #param server the server reference used to call the broadcast method.
* */
ClientListener(#NotNull Socket clientSocket, #NotNull GameServer server) {
this.clientSocket = clientSocket;
this.server = server;
}
/**
* Listen for client messages and send it to the server.
* */
#Override
public void run() {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
String message;
while ((message = reader.readLine()) != null) {
// send received message to the server
LOGGER.log(Level.INFO, "Message received!\n\t From: {0}\n\tMessage: {1}\n",
new Object[]{clientSocket, message});
server.broadcast(message, clientSocket);
}
} catch (IOException e) {
if (!clientSocket.isClosed())
e.printStackTrace();
} finally {
// send the client to server to be disconnected
server.removeClient(clientSocket);
}
}
}
The client module classes:
GameClient.java
package client;
import java.io.IOException;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class GameClient {
public static void main(String[] args) {
final String serverAddress = args.length == 2 ? args[0] : "localhost";
final int port = args.length == 2 ? Integer.parseInt(args[1]) : 5000;
final Logger LOGGER = Logger.getLogger(GameClient.class.getName());
try {
Socket serverSocket = new Socket(serverAddress, port);
LOGGER.log(Level.INFO, "Connection successful! {0}\n", serverSocket);
new Thread(new ClientWriterThread(serverSocket)).start();
new Thread(new ClientReaderThread(serverSocket)).start();
} catch (IOException e) {
LOGGER.log(Level.SEVERE,"Failed to connect with the server\n", e);
e.printStackTrace();
}
}
}
ClientWriterThread.java
package client;
import com.sun.istack.internal.NotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* #author Michael Pacheco
* #version 1.0
* This class is responsible to read client messages and send it to the server.
* */
public class ClientWriterThread implements Runnable {
/**
* The socket used to send messages to the server.
* */
private Socket serverSocket;
/**
* Instantiate a new {#link ClientReaderThread} with a given server socket.
* #param serverSocket the socket used to send messages to the server.
* */
ClientWriterThread(#NotNull Socket serverSocket) {
this.serverSocket = serverSocket;
}
/**
* Read messages typed by the client and send it to the server.
* */
#Override
public void run() {
try {Thread.sleep(1000);}
catch (InterruptedException e) {e.printStackTrace();}
BufferedReader keyboardReader = null;
try (PrintWriter socketWriter = new PrintWriter(serverSocket.getOutputStream(), true)) {
keyboardReader = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = keyboardReader.readLine()) != null) socketWriter.write(line);
} catch (IOException e) {
if (!serverSocket.isClosed())
e.printStackTrace();
} finally {
try {
if (keyboardReader != null) keyboardReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ClientReaderThread.java
package client;
import com.sun.istack.internal.NotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* #author Michael Pacheco
* #version 1.0
* This class is responsible to read messages sent by the server and show them to the client.
*/
public class ClientReaderThread implements Runnable {
/**
* The socket used to read messages sent by the server.
*/
private Socket serverSocket;
ClientReaderThread(#NotNull Socket serverSocket) {
this.serverSocket = serverSocket;
}
/**
* Read messages sent by the server.
* */
#Override
public void run() {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()))) {
String message;
while ((message = reader.readLine()) != null) System.out.println(message);
} catch (IOException e) {
if (!serverSocket.isClosed())
e.printStackTrace();
}
}
}

Be sure to PrintWriter.flush() the messages you send after each write() in ClientWriterThread.java.
As a side note, in order to make the code clearer change your serverSocket variable name to clientSocket in the appropriate classes (GameClient.java and ClientWriterThread.java).

You use PrintWriter with autoflush, but you don't use println(...) or format(...). The .write() is not subject to the autoflush.
FYI, clientsSockets is not thread safe, you add/remove on distinct threads. Not necessarily the bug, but careful. Also, spinning non-daemon threads without keeping a reference is risky; always keep threads under control and don't count too much on interrupt()/InterruptedException/InterruptedIOException...

Related

How to properly use class methods in a thread?

I'm working on this:
//
// Application: Golf App Server
// Author: Andres Martinez
// Year: 2016
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
package com.andress.golfappserver.listener;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import com.andress.golfappserver.beans.Client;
import com.andress.golfappserver.client.ClientHandler;
import com.andress.golfappserver.client.ClientStatus;
/**
* This class has two main goals. First, start to listening the server in a certain port and
* second, accepting incoming connections from clients. It runs as a Thread. The server
* Administrator should provide the number of the port. When the Listener object is initialized
* the ServerSocket will be listening to the port provided. To start to accept new connections
* the Thread should be started. The Listener will create a new Client object every time when accepts
* a new connection. The new Client will have the Socket accepted and a ClientStatus by default of
* Connected. Then, a ClientHandler will be created with the Client as an argument.
* The ClientController will be notified every time a new ClientHandler Thread is created.
*/
public class Listener implements Runnable {
private final int port;
private final ServerSocket serverSocket;
/**
* The Listener is instantiated and initialized with a port number
* supplied by the Server Administrator. Then, the constructor
* creates a new SeverSocket with this port ready to start to listen
* for new connections.
* #param port Integer to identify port.
*/
public Listener(final int port) {
this.port = port;
this.serverSocket = listen();
}
public int getPort() {
return port;
}
public ServerSocket getServerSocket() {
return serverSocket;
}
/**
* Creates Client objects for accepted connections and spawns
* a new ClientHandler for each of the new Client connections.
*/
#Override
public void run() {
Client client = createClient(accept(this.serverSocket));
ClientHandler clientHandler = new ClientHandler(client);
//clientHandler.start();
}
/**
* Binds the port provided by the Server Administrator to a new
* ServerSocket.
* #return ServerSocket listening to the port provided.
*/
private final ServerSocket listen() {
try (ServerSocket serverSocket = new ServerSocket(port)) {
return serverSocket;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Starts to listen for connections to the port specified.
* #param serverSocket ServerSocket to listen for.
* #return Socket of the accepted connection.
*/
private final Socket accept(final ServerSocket serverSocket) {
try (Socket clientSocket = serverSocket.accept()) {
return clientSocket;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Creates a new Client Bean with ClientStatus by default
* of Connected and the Socket of the new connection.
* #param clientSocket Socket for the new connection.
* #return Client object with ClientStatus of Connected by default.
*/
private final Client createClient(final Socket clientSocket) {
Client client = new Client();
client.setSocket(clientSocket);
client.setStatus(ClientStatus.CONNECTED);
return client;
}
}
I'm having an error with the socket but, I'm not interested in this particular error. What I would like to know if a thread always need the code to be executed inside the run() method or is there a way to do it like I'm attempting to do it?
Error:
Exception in thread "Thread-0" java.lang.RuntimeException: java.net.SocketException: Socket is closed
at com.andress.golfappserver.listener.Listener.accept(Listener.java:85)
at com.andress.golfappserver.listener.Listener.run(Listener.java:58)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.SocketException: Socket is closed
at java.net.ServerSocket.accept(ServerSocket.java:509)
at com.andress.golfappserver.listener.Listener.accept(Listener.java:82)
... 2 more
Process finished with exit code 0
a thread always need the code to be executed inside the run() method
Yes. That's what a Java Thread does.
or is there a way to do it like I'm attempting to do it?
You're actually calling some methods inside run(), so it should work altogether.
UPDATE
In accept() method:
private final Socket accept(final ServerSocket serverSocket) {
try (Socket clientSocket = serverSocket.accept()) {
return clientSocket;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
You are accepting the socket in a try-with-resources construction. It means that as soon as this method ends, the socket closes. I bet that's not what you want to be done. Try this instead:
private final Socket accept(final ServerSocket serverSocket) {
try {
return serverSocket.accept();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

Multi-Threading Client-Server Chat application in java

When I close client it gives me error on server side
Like : java.net.SocketException: Connection reset at
java.net.SocketInputStream.read(SocketInputStream.java:196) at
java.net.SocketInputStream.read(SocketInputStream.java:122) at
java.net.SocketInputStream.read(SocketInputStream.java:210) at
java.io.DataInputStream.readLine(DataInputStream.java:513) at
HServer.run(HServer.java:28)
Checkout the code and please tell me how can I send one message of client to all other clients using threads please help me guys :)
ClientDemo.java
import java.io.*;
import java.net.Socket;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author zain-mughal
*/
public class ClientDemo extends javax.swing.JFrame {
DataInputStream input;
PrintWriter output;
public void Connect(){
try {
Socket s = new Socket("127.0.0.1", 2111);
input=new DataInputStream(s.getInputStream());
output=new PrintWriter(s.getOutputStream());
boolean more_data=true;
while(more_data){
String in=input.readLine();
if(in==null){
more_data=false;
}
else{
System.out.println(in);
}
}
s.close();
input.close();
output.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String args[]){
ClientDemo obj=new ClientDemo();
obj.Connect();
}
}
HServer.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author zain-mughal
*/
public class HServer extends Thread {
Socket AcceptReQ;
public HServer(Socket reqAccept) {
this.AcceptReQ=reqAccept;
}
#Override
public void run(){
try {
DataInputStream input = new DataInputStream(AcceptReQ.getInputStream());
PrintWriter output = new PrintWriter(AcceptReQ.getOutputStream());
String in=null;
while((in=input.readLine())!=null){
System.out.println(in);
}
AcceptReQ.close();
input.close();
output.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String args[]){
try {
ServerSocket req = new ServerSocket(2111);
while(true){
Socket reqAccept=req.accept();
Thread t=new HServer(reqAccept);
t.start();
}
} catch (Exception ex) {
Logger.getLogger(HServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Try this:
Build a robust Java server
Building a basic Echo Server and A ChatServer
I used this as base for my own server.
It's a little bit old and many Java features are not used but it works great.
Take some time to comprehend it.

Java Sockets - send data from server to client

I have a technogical question regarding Java Sockets.
For example lets assume I have one Java Sockets Server and n multiple clients.
Is it possible to send data from the Server to any or all Clients in nearly realtime?
More precisely:
Is there kind of Listener which can be implemented in a Sockets Client?
or do I need a loop in the client code where I ask every x milliseconds if there is a task for me?
Can somebody tell me what approach would be the best one?
And in addition if somebody has a code example I would be happy too.
Thanks!
You can establish a Thread in your client which listens to the socket and waits. It will continue when it gets data from the server.
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
public class ResponseThread extends Thread {
private final Socket socket;
/**
* Client is a selfmade interface which has no direct connection to socket communication.
* i build it to provide start(), stop() and isRunning() methods.
*/
private final Client client;
/**
* #param client encapsulated methods to check and manage the client status itself.
* #param socket the socket which is connected to the server.
*/
public ResponseThread(final Client client, final Socket socket) {
this.client = client;
this.socket = socket;
}
#Override
public void run() {
ObjectInputStream reader = null;
try(ObjectInputStream reader = new ObjectInputStream(socket.getInputStream())) {
while (client.isRunning()) {
try {
// The thread will wait here until the server sends data.
final String line = (String) reader.readObject();
if (null == line || line.isEmpty()) {
client.stop();
} else {
System.out.println(line);
}
} catch (IOException | ClassNotFoundException e) {
client.stop();
}
}
} catch (IOException ex) {
System.out.println("ERROR Abort reading. Could not establish InputStream from Socket.");
} finally {
try {
reader.close();
} catch (IOException ex) {
System.out.println("FATAL Could not close Socket.InputStream.");
}
}
}
public Socket getSocket() {
return socket;
}
}

Issue posting to multiple clients

Hey guys i've just recently been getting a hang of sockets but ran into an issue with posting to multiple clients. Ive made it multithreaded to handle this and am attempting to hold all client data the server needs to send to in a hashmap, however when cycling and adding to the hashmap. it seems to only ever add one person. Heres the code..
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
public class HostMain extends Thread {
/**
* The set of all names of clients in the chat room. Maintained
* so that we can check that new clients are not registering name
* already in use.
*/
private static HashMap<String, ConnectedUsers> users = new HashMap<String, ConnectedUsers>();
public HostMain() throws IOException
{
}
public void run()
{
try
{
System.err.println("SERVER:The chat server is running.");
ServerSocket listener = new ServerSocket(PORT);
System.err.println("SERVER:socket created");
Constants.getInstance().getStatusLabel().setText("Server is running. Join when ready");
try {
while (true) {
System.err.println("SERVER:New handler being created");
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
catch(Exception e)
{
Constants.getInstance().getStatusLabel().setText("SERVER:A HOST IS ALREADY RUNNING ON THIS PORT!");
System.err.println("SERVER:A HOST IS ALREADY RUNNING ON THIS PORT!");
}
}
/**
* The port that the server listens on.
*/
private static final int PORT = 1337;
/**
* The appplication main method, which just listens on a port and
* spawns handler threads.
*/
/**
* A handler thread class. Handlers are spawned from the listening
* loop and are responsible for a dealing with a single client
* and broadcasting its messages.
*/
private static class Handler extends Thread {
private String name;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private ObjectInputStream oin;
private ObjectOutputStream oout;
/**
* Constructs a handler thread, squirreling away the socket.
* All the interesting work is done in the run method.
*/
public Handler(Socket socket) {
this.socket = socket;
}
/**
* Services this thread's client by repeatedly requesting a
* screen name until a unique one has been submitted, then
* acknowledges the name and registers the output stream for
* the client in a global set, then repeatedly gets inputs and
* broadcasts them.
*/
public void run() {
try {
// Create object streams for the socket.
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
oin = new ObjectInputStream(socket.getInputStream());
oout = new ObjectOutputStream(socket.getOutputStream());
//add socket to a list
users.put(name,new ConnectedUsers(name,oout));
System.err.println(users.size());
// Accept messages from this client and broadcast them.
// Ignore other clients that cannot be broadcasted to.
while (true) {
Object obj = oin.readObject();
Messages message = (Messages)obj;
if(obj.getClass().equals(Messages.class))
{
for(Map.Entry<String, ConnectedUsers> entry:users.entrySet())
{
ConnectedUsers user = entry.getValue();
user.objectWriter.writeObject(message);
}
}
}
} catch (IOException | ClassNotFoundException e) {
System.out.println(e);
} finally {
// This client is going down! Remove its name and its print
// writer from the sets, and close its socket.
if (name != null) {
users.remove(name);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
name seems to be always null so you keep using the same key (null) which would explain why there is only one user in your map.
Also note that HashMap is not thread safe - unless you add some form of synchronization when accessing the map from your threads it could yield surprising results.
You could instead use a thread safe map, for example a ConcurrentHashMap.

Java socket client/server

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();
}
}
}
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 :)
Your question is seriously vague, but if you're wondering why the server can't reply to your client, it's because the client never reads from the socket.

Categories