Listening on multiple sockets (InputStreamReader) - java

I'm having a problem with a little game I'm designing in my class.
The problem is that I got two clients connected to a server. (client1 and client2) They are each running a game, which in the end, closes the window. As the game window is a JDialog, it will then, when it's closed, send a message, through a socket, to the server, telling it that it's done. I want the server to know which of the two clients were completed first. They are reporting through a PrintWriter on the sockets' OutputStream.
What I did was this:
in1 = new BufferedReader(new InputStreamReader(client.getInputStream()));
in2 = new BufferedReader(new InputStreamReader(client2.getInputStream()));
try {
in1.readLine();
} catch (IOException ex) {
Logger.getLogger(gameServer.class.getName()).log(Level.SEVERE, null, ex);
}
try {
in2.readLine();
} catch (IOException ex) {
Logger.getLogger(gameServer.class.getName()).log(Level.SEVERE, null, ex);
}
Problem is that it waits for the first input, before it even starts listening on the second. How can I make it listen on both at the same time? Or solve my problem some other way.
Thanks!

Server connection should work like this:
Server gameServer = new Server();
ServerSocket server;
try {
server = new ServerSocket(10100);
// .. server setting should be done here
} catch (IOException e) {
System.out.println("Could not start server!");
return ;
}
while (true) {
Socket client = null;
try {
client = server.accept();
gameServer.handleConnection(client);
} catch (IOException e) {
e.printStackTrace();
}
}
In hanleConnection() you start a new thread and run the communication for this client in the created thread. Then the server can accept a new connection (in the old thread).
public class Server {
private ExecutorService executor = Executors.newCachedThreadPool();
public void handleConnection(Socket client) throws IOException {
PlayerConnection newPlayer = new PlayerConnection(this, client);
this.executor.execute(newPlayer);
}
// add methods to handle requests from PlayerConnection
}
The PlayerConnection class:
public class PlayerConnection implements Runnable {
private Server parent;
private Socket socket;
private DataOutputStream out;
private DataInputStream in;
protected PlayerConnection(Server parent, Socket socket) throws IOException {
try {
socket.setSoTimeout(0);
socket.setKeepAlive(true);
} catch (SocketException e) {}
this.parent = parent;
this.socket = socket;
this.out = new DataOutputStream(socket.getOutputStream());;
this.in = new DataInputStream(socket.getInputStream());
}
#Override
public void run() {
while(!this.socket.isClosed()) {
try {
int nextEvent = this.in.readInt();
switch (nextEvent) {
// handle event and inform Server
}
} catch (IOException e) {}
}
try {
this.closeConnection();
} catch (IOException e) {}
}
}

Related

Java chat application only picking up some sent messages

I'm writing an all-in-one java chat program which will either act as a client or a server. I'm currently having this problem where, after the connection is established, the program only successfully recieves (or sends?) some of the messages. I've used a loop to spam through a load of junk and I've seen that the other end will only pick up some of the messages. I've never got a message to send manually.
Here is the code:
public class ConnectionThread implements Runnable {
private Connection c = Connection.getInstance();
private ChatInterface chatInterface;
private static ConnectionThread serverThread;
private ServerSocket serverSocket;
private Socket socket;
private ObjectInputStream dataIn;
private ObjectOutputStream dataOut;
public ConnectionThread() {}
public static synchronized ConnectionThread getInstance() {
if (serverThread == null) {
serverThread = new ConnectionThread();
}
return serverThread;
}
public void run() {
// If the programs role is server, set up the server
if (c.getRole() == ConnectionRole.SERVER) {
try {
setupServer();
waitForConnection();
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
do {
try {
chatInterface.addToChatHistory(dataIn.readUTF());
} catch (IOException e) {
e.printStackTrace();
}
} while (c.getRole() == ConnectionRole.SERVER);
}
// If the programs role is client, set up a connection to the server
if (c.getRole() == ConnectionRole.CLIENT) {
try {
setupClient();
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
do {
try {
chatInterface.addToChatHistory(dataIn.readUTF());
} catch (IOException e) {
e.printStackTrace();
}
} while (c.getRole() == ConnectionRole.CLIENT);
}
}
private void setupClient() throws IOException {
System.out.println("ATTEMPTING TO CONNECT...");
socket = new Socket("127.0.0.1", 8080);
System.out.println("CONNECTED!");
}
private void setupServer() throws IOException {
System.out.println("SETTING UP SERVER..");
serverSocket = new ServerSocket(8080, 1);
System.out.println("SERVER SETUP");
}
private void waitForConnection() throws IOException {
System.out.println("WAITING FOR A CONNECTION...");
socket = serverSocket.accept();
System.out.println("CONNECTION RECIEVED");
}
private void setupStreams() throws IOException {
System.out.println("SETTING UP STREAMS...");
dataOut = new ObjectOutputStream(socket.getOutputStream());
dataIn = new ObjectInputStream(socket.getInputStream());
chatInterface = ChatInterface.getInstance();
System.out.println("STREAMS SETUP");
}
public void sendMessage(String message) throws IOException {
System.out.println("SENDING MESSAGE...");
dataOut.writeUTF(message);
chatInterface.addToChatHistory(message);
System.out.println("MESSAGE SENT!");
}
}
Can anyone tell me why not all messages are being sent/picked up properly? I've been playing with it for quite a while now and I can't figure out why.
I found out after following EJP's recommendation to switch to DataInput/OutputStreams which worked straight away. Although I did need to be using ObjectInput/OutputStreams so I switched back. I found that I got the same issue again, until I switched to write/readObject instead of write/readUTF. If I cast the readObject to (String) it would then manage to receive every message.
So if anyone is having the same problem with ObjectInput/OutputStreams using write/readUTF try using write/readObject instead.

How to write A ServerSocket which accept multiple clicent Socket?

I am working on Socket programming. I have build such a server which should accept multiple Clients. Here I have particular num of clients , clients keeps on sending msg to Server every 10sec , Server has to process it.The problem I am having is I am unable to connect multiple Server and here a single client is a continuous running programm in while(true) So if one client Sends a request another client can not connect . Here is my Program.
Server
public class SimpleServer extends Thread {
private ServerSocket serverSocket = null;
private Socket s1 = null;
SimpleServer() {
try {
serverSocket = new ServerSocket(1231);
this.start();
} catch (IOException ex) {
System.out.println("Exception on new ServerSocket: " + ex);
}
}
public void run() {
while (true) {
try {
System.out.println("Waiting for connect to client");
s1 = serverSocket.accept();
System.out.println("Connection received from " + s1.getInetAddress().getHostName());
InputStream s1In = s1.getInputStream();
DataInputStream dis = new DataInputStream(s1In);
String st = dis.readUTF();
System.out.println(st);
s1In.close();
dis.close();
s1.close();
// throw new ArithmeticException();
} catch (IOException ex) {
Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex);
}
catch (Exception e) {
System.out.println("Exceptiopn: "+e);
}
}
}
public static void main(String args[]) throws IOException {
new SimpleServer();
}
}
Server is working fine but I am not able to write Client program which shoud run in while(true) loop for sending msg to Server and allow other client also connect to Server.
but for a single client I write like this ,
public class SimClient extends Thread {
private Socket s1 = null;
SimClient() {
//this.start();
}
public void run() {
int i=0;
try {
s1 = new Socket("localhost", 1231);
} catch (IOException ex) {
Logger.getLogger(SimClient.class.getName()).log(Level.SEVERE, null, ex);
}
// while (i<10) {
try {
// Open your connection to a server, at port dfg1231
OutputStream s1out = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream(s1out);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter Data from Client:");
String s = br.readLine();
dos.writeUTF(s);
dos.flush();
s1out.close();
dos.close();
// s1.close();
i++;
} catch (IOException ex) {
//ex.printStackTrace();
System.out.println("Exception in While: "+ex.getMessage());
}
//}
}
public static void main(String args[]) throws IOException {
SimClient s= new SimClient();
s.start();
}
}
So can any one help me to write client program. its a great help for me.
just as you have a Thread for the ServerSocket, you need to create a Thread for every Socket returned by serverSocket.accept() , then it loops back around immediately to block and wait to accept another Socket. Make a class called SocketHander which extends Thread and accepts a Socket in the constructor.
public class SocketHandler extends Thread {
private Socket socket;
public SocketHandler(Socket socket) {
this.socket = socket;
}
public void run() {
// use the socket here
}
}
and back in the ServerSocket handler...
for (;;) {
SocketHandler socketHander = new SocketHandler(serverSocket.accept());
socketHander.start();
}
It is generally a good idea to use a Fixed Size Thread Pool because creating Threads in a ad-hoc manner may cause the Server to run out of Threads if the requests are high.
public class SimpleServer extends Thread {
private ServerSocket serverSocket = null;
private static ExecutorService executor = Executors.newFixedThreadPool(100);
SimpleServer() {
try {
serverSocket = new ServerSocket(1231);
this.start();
} catch (IOException ex) {
System.out.println("Exception on new ServerSocket: " + ex);
}
}
public void run() {
while (true) {
try {
System.out.println("Waiting for connect to client");
final Socket s1 = serverSocket.accept();
executor.execute(new Runnable() {
public void run() {
try {
System.out.println("Connection received from " + s1.getInetAddress().getHostName());
InputStream s1In = s1.getInputStream();
DataInputStream dis = new DataInputStream(s1In);
String st = dis.readUTF();
System.out.println(st);
s1In.close();
dis.close();
s1.close();
} catch(Exception e) {
System.out.println("Exceptiopn: "+e);
}
// throw new ArithmeticException();
}});
} catch (IOException ex) {
Logger.getLogger(SimpleServer.class.getName()).log(Level.SEVERE, null, ex);
} catch (Exception e) {
System.out.println("Exceptiopn: "+e);
}
}
}
public static void main(String args[]) throws IOException {
new SimpleServer();
}
}

Multithreading Socket communication Client/Server

I finished writing a Client/Server Socket communication program that works fine. Now I'm trying to figure out how to make it so that I can have multiple Client connections to the Server at once. I've looked around and there seems to be more than a couple of different ways to do this. so I've come here to ask you guys for help/suggestions.
My Server:
public class Server {
private ServerSocket serverSocket = null;
private Socket clientSocket = null;
public Server() {
try {
serverSocket = new ServerSocket(7003);
} catch (IOException e) {
System.err.println("Could not listen on port: 7003");
System.exit(1);
}
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed");
System.exit(1);
}
}
public void startServer() throws IOException {
PrintWriter output = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine, outputLine;
outputLine = "Connected to Server";
output.println(outputLine);
while ((inputLine = input.readLine()) != null) {
// This just determines users input and server ruturns output based on that
outputLine = this.getServerOutput(inputLine);
output.println(outputLine);
if (outputLine.equals("Bye"))
break;
}
output.close();
input.close();
clientSocket.close();
serverSocket.close();
}
}
Would I need to make my constructor create threads and startServer() or would be my run method?
You should use ExecutorService. Your client request processing would be the run() of a Runnable and after each accept you can call ExecutorService.submit(runnableTask) to asynchronously service the client.
A sample using ExecutorService.
public class MyServer {
private static MyServer server;
private ServerSocket serverSocket;
/**
* This executor service has 10 threads.
* So it means your server can process max 10 concurrent requests.
*/
private ExecutorService executorService = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws IOException {
server = new MyServer();
server.runServer();
}
private void runServer() {
int serverPort = 8085;
try {
System.out.println("Starting Server");
serverSocket = new ServerSocket(serverPort);
while(true) {
System.out.println("Waiting for request");
try {
Socket s = serverSocket.accept();
System.out.println("Processing request");
executorService.submit(new ServiceRequest(s));
} catch(IOException ioe) {
System.out.println("Error accepting connection");
ioe.printStackTrace();
}
}
}catch(IOException e) {
System.out.println("Error starting Server on "+serverPort);
e.printStackTrace();
}
}
//Call the method when you want to stop your server
private void stopServer() {
//Stop the executor service.
executorService.shutdownNow();
try {
//Stop accepting requests.
serverSocket.close();
} catch (IOException e) {
System.out.println("Error in server shutdown");
e.printStackTrace();
}
System.exit(0);
}
class ServiceRequest implements Runnable {
private Socket socket;
public ServiceRequest(Socket connection) {
this.socket = connection;
}
public void run() {
//Do your logic here. You have the `socket` available to read/write data.
//Make sure to close
try {
socket.close();
}catch(IOException ioe) {
System.out.println("Error closing client connection");
}
}
}
}
how to make it so that I can have multiple Client connections to the Server at once
Right now you are starting your server and immediately waiting for a single client to connect in the constructor.
clientSocket = serverSocket.accept();
Then you handle that single socket connection inside of your startServer() method. This means that no other clients will be handled.
public void startServer() throws IOException {
PrintWriter output = new PrintWriter(clientSocket.getOutputStream(), true);
...
Typically with a server pattern like this, you would do something like the following:
Setup your server socket in the constructor.
Create an acceptClients() method which would loop waiting for a client to be accepted. This could fork a thread to accept the clients in a thread of its own in the background.
For each client, either fork a thread to handle the connection, passing the thread the clients socket. Better would be to, as #basiljames shows, use an ExecutorService to manage the threads for you.
Here's some sample code:
public class Server {
private ServerSocket serverSocket = null;
public Server(int portNumber) throws IOException {
serverSocket = new ServerSocket(portNumber);
}
// this could be run in a thread in the background
public void acceptClients() throws IOException {
// create an open ended thread-pool
ExecutorService threadPool = Executors.newCachedThreadPool();
try {
while (!Thread.currentThread().isInterrupted()) {
// wait for a client to connect
Socket clientSocket = serverSocket.accept();
// create a new client handler object for that socket,
// and fork it in a background thread
threadPool.submit(new ClientHandler(clientSocket));
}
} finally {
// we _have_ to shutdown the thread-pool when we are done
threadPool.shutdown();
}
}
// if server is running in background, you stop it by killing the socket
public void stop() throws IOException {
serverSocket.close();
}
// this class handles each client connection
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
public ClientHandler(Socket clientSocket) {
this.clientSocket = clientSocket;
}
public void run() {
// use the client socket to handle the client connection
...
}
}
}
Using the ExecutorService thread-pools is recommended for just about all Thread implementations like this. If, however, you are stuck to using raw Thread for some reason, you can do the following instead in your acceptClients() method:
public void acceptClients() throws IOException {
while (!Thread.currentThread().isInterrupted()) {
// wait for a client to connect
Socket clientSocket = serverSocket.accept();
// fork a background client thread
new Thread(new ClientHandler(clientSocket)).start();
}
}
Change this: public void startServer() throws IOException
To this: public void startServer(Socket clientSocket) throws IOException
Then all you need to do is:
public Server()
{
try
{
serverSocket = new ServerSocket(7003);
}
catch (IOException e)
{
System.err.println("Could not listen on port: 7003");
System.exit(1);
}
try
{
while(true) {
final Socket socket = serverSocket.accept();
new Thread(new Runnable() {
public void run() {
try {
startServer(socket);
} catch(IOException e) {e.printStackTrace();}
}
}).start();
}
}
catch(IOException e)
{
System.err.println("Accept failed");
System.exit(1);
}
}
And lastly, you can remove private Socket clientSocket = null;
That should get you there. Or at least pretty close.
private static final int SERVER_PORT = 35706;
private ServerSocket serverSocket;
private final ArrayList<ClientThread> activeClients = new ArrayList<>();
public void startServer() {
try {
serverSocket = new ServerSocket(SERVER_PORT);
final ExecutorService clientPool = Executors.newCachedThreadPool();
while (!serverSocket.isClosed()) {
try {
Future<Socket> future = clientPool.submit(() -> {
Socket socket = serverSocket.accept();
ClientThread clientThread= new ClientThread(socket);
return (socket);
});
activeClients.add(future.get());
} catch (IOException e) {
clientPool.shutdownNow();
System.out.println(e.getMessage());
} catch (InterruptedException | ExecutionException e) {
System.out.println(e.getMessage());
}
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
public void stopServer() {
try {
serverSocket.close();
activeClients.forEach(socket -> {
try {
socket.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
});
} catch (IOException ex) {
System.out.println(e.getMessage());
}
}
private static class ClientThread implements Runnable{
private final Socket socket;
public ClientThread(Socket socket) throws IOException {
this.socket = socket;
}
#Override
public void run() {
/* Your implementation */
}
}

Java - Listening to a socket with ObjectInputStream

Ok so , i have a thread class called 'Client' every time the server accepts a connection it creates a new Client....The run method listens for messages from the client and i am useing ObjectInputStream ..
do {
ObjectInputStream in = null;
try {
in = new ObjectInputStream(socket.getInputStream());
String message = (String) in.readObject();
System.out.println(message);
}
catch (ClassNotFoundException ex) {
isConnected = false;
System.out.println("Progoramming Error");
}
catch (IOException ex) {
isConnected = false;
System.out.println("Server ShutDown");
System.exit(0);
}
} while(isConnected);
The Problem i have is that why do i have to create a new ObjectInputStream every time it loops...and if i close the input stream at the end of the loop and it loops again for another message i will get a error...Please some one help
Only create the ObjectInputStream once (outside the loop) for a client connection, then put the readObject method into the loop.
Here's a working test class:
public class TestPrg {
public static void main(String... args) throws IOException {
ServerListener server = new ServerListener();
server.start();
Socket socketToServer = new Socket("localhost", 15000);
ObjectOutputStream outStream = new ObjectOutputStream(socketToServer.getOutputStream());
for (int i=1; i<10; i++) {
try {
Thread.sleep((long) (Math.random()*3000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Sending object to server ...");
outStream.writeObject("test message #"+i);
}
System.exit(0);
}
static class ServerListener extends Thread {
private ServerSocket serverSocket;
ServerListener() throws IOException {
serverSocket = ServerSocketFactory.getDefault().createServerSocket(15000);
}
#Override
public void run() {
while (true) {
try {
final Socket socketToClient = serverSocket.accept();
ClientHandler clientHandler = new ClientHandler(socketToClient);
clientHandler.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
static class ClientHandler extends Thread{
private Socket socket;
ObjectInputStream inputStream;
ClientHandler(Socket socket) throws IOException {
this.socket = socket;
inputStream = new ObjectInputStream(socket.getInputStream());
}
#Override
public void run() {
while (true) {
try {
Object o = inputStream.readObject();
System.out.println("Read object: "+o);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
In this example Strings are sent trough the ObjectStream. If you get the ClassNotFoundException (http://download.oracle.com/javase/6/docs/api/java/io/ObjectInputStream.html#readObject()) and are using an independent client and server program than you might check if both the client and the server have the class of the object to send in their class paths.
The problem i personally had with Sockets and ObjectIOStream, is that it remembers all your object addresses, so each time you send and recive them on the client, if the address of sent object is not changed it will be copied from buffer. So
So
or create new objects each time you send them ( this is not a bad idiea, because ObjectIOStream seems to has limits on this buffer)
or use another Stream for these perpouse

Java, problem sending a message with socket connection

I have a problem with my Java program. It has a socket connection between a server and many client. Here is the server (the part which concerns the problem):
private static ArrayList<ParallelServer> clientConnected = new ArrayList<ParallelServer>();
public Server(int port) {
this.port = port;
if (!startServer())
JOptionPane.showMessageDialog(new JFrame(""),
"Error!", "ERROR!",
JOptionPane.ERROR_MESSAGE);
}
private boolean startServer() {
try {
server = new ServerSocket(port);
loadDatabase();
} catch (IOException ex) {
ex.printStackTrace();
return false;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return true;
}
public void runServer() {
while (true) {
try {
client = server.accept();
ParallelServer pServer = new ParallelServer(client);
clientConnected.add(pServer);
Thread thread = new Thread(pServer);
thread.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
public static void sendBroadcast(String username) throws IOException {
for(int i = 0; i < clientConnected.size(); i++)
clientConnected.get(i).sendAnswer("#change," + username);
}
The parallel server is:
private Socket client;
private InputStreamReader inputstreamreader;
private BufferedReader bufferedreader;
private PrintWriter printwriter;
public ParallelServer(Socket client) {
this.client = client;
}
public void run() {
try {
inputstreamreader = new InputStreamReader(client.getInputStream());
bufferedreader = new BufferedReader(inputstreamreader);
printwriter = new PrintWriter(client.getOutputStream(), true);
String lineread = "";
while (client.isConnected()) {
lineread = bufferedreader.readLine();
doCommand(lineread);
}
} catch (UnknownHostException unhe) {
} catch (InterruptedIOException intioe) {
} catch (IOException ioe) {
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void sendAnswer(String answer) throws IOException {
printwriter = new PrintWriter(client.getOutputStream(), true);
printwriter.println(answer);
printwriter.flush();
}
And here is the client:
private String serverurl = "localhost";
private int serverport = 7777;
private PrintWriter printwriter;
private InputStreamReader inputstreamreader;
private BufferedReader bufferedreader;
private Socket server;
public Client() {
server = null;
try {
server = new Socket(serverurl, serverport);
server.setSoTimeout(5000);
} catch (UnknownHostException unhe) {
System.out.println("UnknownHostException: " + unhe.getMessage());
} catch (InterruptedIOException intioe) {
System.out.println("Timeout while attempting to establish socket connection.");
} catch (IOException ioe) {
JOptionPane.showMessageDialog(new JFrame(),"Unable to reach the server!","ERROE!",JOptionPane.ERROR_MESSAGE);
}
}
public String sendCommand(String command) throws IOException {
if(server == null) {
try {
server = new Socket(serverurl, serverport);
server.setSoTimeout(5000);
} catch (UnknownHostException unhe) {
System.out.println("UnknownHostException: " + unhe.getMessage());
} catch (InterruptedIOException intioe) {
System.out.println("Timeout while attempting to establish socket connection.");
} catch (IOException ioe) {
JOptionPane.showMessageDialog(new JFrame(),"Unable to reach the server!","ERROR!",JOptionPane.ERROR_MESSAGE);
}
}
if(server != null) {
printwriter = new PrintWriter(server.getOutputStream(), true);
printwriter.println(command);
printwriter.flush();
inputstreamreader = new InputStreamReader(server.getInputStream());
bufferedreader = new BufferedReader(inputstreamreader);
return bufferedreader.readLine();
}
else
return "#serverProblem";
}
The program is a simple online game with turns. Players' turns are created with a queue and when a player passes his turn, the server send a broadcast message which say "Now it is 'Player 1' turn." (for instance). My problem is that when a client receive the message, its like it add the answer "Now it is 'Player 1' turn." to the next message it will receive. In my case: when a player passes his turn, he sends "#passTurn,username". The ParallelServer class polls it from the queue, puts it at the bottom of the queue, sends the client "#ok" to tell it that the turn has changed successfully and tells the Server class to send the broadcast message. Then, when the same client will try do do a further action, it will consider "Now it is 'Player 1' turn." as the answer the server has given to it. Instead, I would like that the server and the clients work as always and when the broadcast message is cought, the client is notified without any collateral effect.
What can I do?
Thanks.
Your bi-directional message passing mechanism should look something like this:
Server:
Wait on any client InputStream
if (broadcast)
broadcast_message()
else
process_message()
Client:
Receiving Thread:
Wait on server broadcast
Sending Thread:
Wait on messages to be sent to server from the User Input
This should do the trick :)
Hope it helps. Cheers!

Categories

Resources