java client server multithreaded, works for only one connection - java

I did my client-server application but at the moment only one user can use it. Could you help me how to make it working for more than one user. I have the following functionality: On every two minutes counter is starting to decrease. Every user have 30 seconds to connect to the application. Every connected user should see same result with which he should make some other actions. I made it by this way at the moment. The code in the different cases is not so important. I need an advice how to make it working as a structure of the code. Thanks in advance!
import java.net.*;
import java.io.*;
public class MultiServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(-1);
}
while (listening)
new MultiServerThread(serverSocket.accept()).start();
serverSocket.close();
}
}
import java.net.*;
import java.io.*;
import java.util.HashMap;
public class MultiServerThread extends Thread {
private Socket socket = null;
public MultiServerThread(Socket socket) {
super("MultiServerThread");
this.socket = socket;
}
public void run() {
try {
ObjectOutputStream toServer = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream fromServer = new ObjectInputStream(socket.getInputStream());
int userProcess = 0;
Object data = 11111;
boolean listening = true;
CountDown c = new CountDown();
int timeRemaining = 900;
while (listening) {
boolean send = true;
Object ob;
try {
ob = fromServer.readObject();
userProcess = Integer.parseInt(ob.toString());
HashMap<String,Integer> finalScores = new HashMap<String,Integer>();
if(userProcess == 0) {
timeRemaining = c.getRemainingTime();
int temp = 999;
while(timeRemaining-110>0) {
timeRemaining = c.getRemainingTime();
if(temp != timeRemaining) {
toServer.writeObject(timeRemaining-110);
toServer.flush();
temp = timeRemaining;
}
}
}
if(userProcess == 0 && timeRemaining-110 < 0) {
c = new CountDown();
send = false;
}
if(userProcess == 1) {
BoardGeneraor board = new BoardGeneraor();
data = board.getBoard();
}
if(userProcess == 2) {
int score = (Integer)fromServer.readObject();
String username = (String)fromServer.readObject();
finalScores.put(username, score);
data = finalScores;
c = new CountDown();
}
if(send) {
toServer.writeObject(data);
toServer.flush();
} else {
toServer.writeObject("quit");
toServer.flush();
}
} catch (ClassNotFoundException e) {
System.out.println(e);
}
}
fromServer.close();
toServer.close();
socket.close();
} catch(IOException e) {
System.out.println(e);
}
}
}

I think your problem is that you have confused the server and client and have put the client and server code within the same Java file. It looks like you intend MultiServerThread to be the client, since it interprets the socket's output stream as going "to server" and the socket's input stream as coming "from server." But when you create a MultiServerThread with serverSocket.accept(), you're giving it a socket that represents the server's side of the connection to one client. Thus the output stream returned by socket.getOutputStream() represents a stream from the server to the client. What MultiServerThread should actually represent is one instance of the server talking to a client, not one instance of a client connecting to the server.
In order to have clients connect to your server, you'll need a separate Java file, say Client.java, containing a separate class with a separate main method. This class should open a connection to the server with the Socket(String host, int port) constructor, and treat the input stream of that socket as a stream of input from the server. Here's a simple example:
public class Client {
public static void main(String[] args) {
Socket serverConnection = null;
try {
serverConnection = new Socket("localhost", 4444);
} catch(IOException e) {
System.err.println("Could not connect to server");
System.exit(-1);
}
try {
ObjecttInputStream fromServer = new ObjectInputStream(serverConnection.getInputStream());
Object ob = fromServer.readObject();
} catch(IOException e) {
System.err.println("Error reading from server");
}
}
}
Once you've started your server by running the MultiServer.class file, you can start a client by running the Client.class file (in a separate window, while the server is still running).

Related

Java - Getting error "Socket is closed" when my Client class connects on my Server class

I made two classes in Java named Server.java and Client.java. The Server is listening to a port and is waiting for a Client to connect (using sockets). When the client connects he can type a pair of numbers separated by "space" and if that pair exists in my edge_list.txt file the Server returns "1" to the client, if not it returns "0". After I completed my initial project I wanted to also use Threads so that it can handle multiple users at once, but when the Client connects I get -> java.net.SocketException: Socket is closed.
I reviewed my code and try using flush() instead of close(). Also, I thought I was closing the socket before the user can read the file, but it didn't seem that was the case. Below I will have the Server.java code block and not the Client.java, cause it doesn't seem to be the problem.
Server.java
import java.io.*;
import java.net.*;
import java.util.*;
public class Server {
private static final int PORT = 9999;
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
System.out.println("Server is listening on port " + PORT);
while (true) {
try (Socket socket = serverSocket.accept()) {
System.out.println("Client connected: " + socket);
new ClientHandler(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static class ClientHandler extends Thread {
private Socket socket;
ClientHandler(Socket socket){
this.socket = socket;
}
#Override
public void run() {
try {
//Creating Sockets and Streams
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(output));
while (socket.isConnected() && !socket.isClosed()) {
//Reading what the Client types
String request = reader.readLine();
//Split the values with "space" and store them in an array,
//then parse those values to two integers
String[] values = request.split(" ");
int A = Integer.parseInt(values[0]);
int B = Integer.parseInt(values[1]);
//Check if the pair in the file exists using checkPairInFile() method
boolean exists = checkPairInFile(A, B);
//if it does print 1 else 0
writer.println(exists ? "1" : "0");
//Flush the output to send the response back to the client
writer.flush();
}
//Print the disconnected user
System.out.println("Client disconnected: " + socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static boolean checkPairInFile(int A, int B) {
try (Scanner scanner = new Scanner(new File("edge_list.txt"))) {
//Scanning the file lines
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
//Split the values with "space"
String[] values = line.split(" ");
//Parse the values from String -> Int
int a = Integer.parseInt(values[0]);
int b = Integer.parseInt(values[1]);
//if both exist return true
if (A == a && B == b) {
return true;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return false;
}
}
P.S. Thanks in advance for your help, in case this is problem with my Client.java file I will update the post.
This part:
try (Socket socket = serverSocket.accept()) {
System.out.println("Client connected: " + socket);
new ClientHandler(socket).start();
}
accepts a socket, then prints a message, then starts a new thread, then closes the socket. At some point later the new thread finishes starting up and tries to use the socket and realizes it was already closed.
try (...) {...} (officially called try-with-resources) always closes the things when it gets to the }. That's the point of it. If you don't want to close the socket at the } then you shouldn't use this type of statement.

Sending a Message to Multiple Clients from One Server Simultaneously?

I am currently working on a TCP Sockets program in Java in which two or more separate clients connect to a single server, and that server will send a message to both of these connected clients simultaneously.
I've tried to work through the code multiple times, but I can't quite seem to be able to have one message be sent to both clients.
Below is a reduced version of my entire code, condensed down to just the issue I'm having.
I've also included a video, just to save you the effort of having to copy and run my code!
[STREAMABLE LINK]
When one client is connected, I just have to write one message in the server, press send, and it shows up in the client.
When two clients are connected, I have to write two messages in the server and press send twice, and one message goes to one client and the other to the next client.
How can I make it so I only send one message from the server that goes to all clients?
I greatly appreciate any and all help.
SERVER CODE:
import java.io.*;
import java.net.*;
import java.util.*;
// Server class
class Server {
public class countLogic {
public static int client_count = 0;
}
public static void main(String[] args) {
System.out.println("[SERVER]");
ServerSocket server = null;
try {
server = new ServerSocket(1234);
server.setReuseAddress(true);
while (true) {
Socket client = server.accept();
countLogic.client_count++;
System.out.println("Client ("+countLogic.client_count+") connected: " + client.getInetAddress().getHostAddress());
ClientHandler clientSock = new ClientHandler(client);
new Thread(clientSock).start();
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
if (server != null) {
try {
server.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
// ClientHandler class
private static class ClientHandler implements Runnable {
private final Socket clientSocket;
public ClientHandler(Socket socket)
{
this.clientSocket = socket;
}
public void run()
{
PrintWriter out = null;
BufferedReader in = null;
try {
Scanner sc = new Scanner(System.in);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
while (true) {
line = sc.nextLine();
out.println(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
clientSocket.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
CLIENT CODE:
import java.io.*;
import java.net.*;
import java.util.*;
// Client class
class Client {
// driver code
public static void main(String[] args)
{
System.out.println("[CLIENT 1]");
try (Socket socket = new Socket("localhost", 1234)) {
PrintWriter out = new PrintWriter(
socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Scanner sc = new Scanner(System.in);
String line = null;
while (!"exit".equalsIgnoreCase(line)) {
System.out.println("Server: "+ in.readLine());
}
// closing the scanner object
sc.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}

Java Server producing inconsistent output

I want to integrate a server with multiple clients for a blackjack game I created, and thus I began practicing with servers in java. I create a thread, that when ran, forces the server to listen for input and produce an output. Then I added a feature to stop the server. However, the server randomly produces the correct output, and sometimes fails to connect. Here is the code for when the user hosts a server:
st = new ServerThread(); //this is a field of type ServerThread
st.start(); //this runs the server concurrently as a new thread
Here is the code for when they close a server:
st.stopThread();
Finally, here is the source for the serverThread:
public class ServerThread extends Thread {
private volatile boolean isRunning = true;
private Socket socket;
private static final int PORTNUM = 1342;
#Override
public void run() {
while (isRunning) { //should run only when the
try {
ServerSocket serverSocket = new ServerSocket(PORTNUM); //uses the same port number, which I made a constant
//Reading the an object of type Information from the client
socket = serverSocket.accept();
ObjectInputStream serverInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream serverOutputStream = new ObjectOutputStream(socket.getOutputStream());
Information i = (Information) serverInputStream.readObject();
//arbitrarily changes the data stored in the information object to verify connection with server
i.setI(100);
i.setS("new string");
i.setD(4.4);
//sends the modified object back to the client
serverOutputStream.writeObject(i);
serverInputStream.close();
serverOutputStream.close();
socket.close();
} catch (IOException e) {
//System.out.println("IOException");
//e.printStackTrace();
} catch (ClassNotFoundException e) {
//System.out.println("ClassNotFoundException");
//e.printStackTrace();
} finally {
try {
if (socket != null) { //avoid null pointer if no connections have been established
socket.close();
}
} catch (IOException ex) {
//Logger.getLogger(ServerThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public void stopThread() {
isRunning = false;
}
}
Any suggestions on edits to make my code perform correctly and consistently would be welcome. Thanks.
I would move the socket definition away from being an instance variable i.e,
while (isRunning) {
Socket socket = null;
try {
...

Getting "connection to host lost" in Java Socket Client-Server

For the server I have to alter the provided code into a multi-threaded server. For the client I have alter to it to make it read data from a text file.
So far I've managed to compile but when running on the client side it not only gives odd symbols but in the end it says "connection host lost". I've tried changing the socket number the same problem persists.
So this is what it looks like:
¼Ýsr♥Car´3▼3çw3û☻♦DmileageLmodelt↕Ljava/lang/String;Lownerq~☺L
registrationq~☺xp#
"Honda Civic""John S"q~sq~##t-sq~#Òêt
"Vokswagen"t "Maria B"q~
Connection to host lost.
This is my code for server:
//a simple client/server application: car registration
//a SERVER program that uses a stream socket connection to exchange objects
import java.net.*;
import java.io.*;
public class CarsServer {
public static void main(String[] args) throws IOException{
ServerSocket serverSocket = null;; // TCP socket used for listening
try {
/* step 1: create a server socket port number: 8000 */
serverSocket = new ServerSocket(5200);
int i = 0;
for(;;){
/* setp 2: listen for a connection and create a socket */
System.out.println("*** this server is going to register the cars ***");
System.out.println("listening for a connection...");
Socket clientSocket = serverSocket.accept();
System.out.println("Spawning " + i++);
new CarsClient(clientSocket, i).start();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
/* step 5: close the connection to the client */
System.out.println("*** the server is going to stop running ***");
serverSocket.close();
}
}
}
And for Client
//a simple client/server application that exchanges OBJECTS
//a CLIENT program that uses a stream socket connection to exchange objects
import java.net.*;
import java.io.*;
class CarsClient extends Thread{
private Socket incoming;
private int client;
public CarsClient(Socket i, int c){
this.client = c;
this.incoming = i;
}
public void run(){
try {
/*
* step 2: connect input and output streams to the socket
*/
BufferedReader oisFromServer = new BufferedReader(new FileReader("Cars.txt"));
ObjectOutputStream oosToServer = new ObjectOutputStream(incoming.getOutputStream());
System.out.println("I/O streams connected to the socket");
/*
* step 3: communicate with the server
*/
Car[] cars = new Car[3];
int n = 0;
String[] l;
String line;
while((line = oisFromServer.readLine()) != null){
l = line.split(", ");
try {
// receive an object from the server
cars[n] = new Car(l[0], l[1], Integer.parseInt(l[2])); // casting!
// send an object to the server
oosToServer.writeObject(cars[n]);
//oosToServer.flush();
System.out.println("\n### send this car to the server for registration:\n" + cars[n]);
System.out.println("\t###### the car returned by the server:\n"+ cars[n]);
n++;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
} catch (EOFException eof) {
System.out.println("The server has terminated connection!");
} catch (IOException e) {
e.printStackTrace();
}
}
/*
* step 4: close the connection to the server
*/
System.out.println("\nClient: closing the connection...");
oosToServer.close();
oisFromServer.close();
incoming.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
System.out.println("the client is going to stop runing...");
} // end run
}
I'm new to programming so please help me out.
It appears that your issue is here:
while((line = oisFromServer.readLine()) != null){
You are consuming all the lines of text, and once that's done, oisFromServer is going to return null.
To solve this, I recommend you use the raw InputStream and InputStream.read() from the socket. Also, once upon a time I wrote a utility class for this kind of blocking reading. See DataFetcher, and its dependencies in the same project package

ask about deliver message between client to client

hi i writ acode for client and for server and now i want to deliver the message between clint one to clint two and i dont succees to do this on server side i want to construct array for name and id and after i send message from the client side i can choose where or Which name the server deliver the message pleas help me to writ this
so this is the clint side
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class client {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("127.0.0.1", 7777);
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
BufferedReader readerFromCommandLine = new BufferedReader(new InputStreamReader(System.in));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while(true) {
System.out.println("Say something:");
String userInput = readerFromCommandLine.readLine();
writer.println(userInput);
writer.flush();
String input = reader.readLine();
System.out.println("Got from server: "+input);
if (userInput.equalsIgnoreCase("bye")) {
break;
}
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
}
catch (Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
}
so now my code shuold by look like this ?
becaus i not yet can send from one client to client two
import java.awt.List;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class server {
public static void main(String[] args) {
ArrayList<Channel> my_clients = new ArrayList<Channel>();
ServerSocket ss = null;
try {
ss = new ServerSocket(7777);
while (true) {
//wait for a new client call - once got it, get the socket for
//that channel
System.out.println("Waiting for an incoming call");
Socket client = ss.accept();
Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();
//once the call has started read the client data
for(Channel my_client : my_clients) {
if(my_client.getName() == "Me") {
//my_client.writer("HELLO!");
}
}
//System.out.println("Accepted a new call");
//new Channel(client).start();
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (ss != null) {
try {
ss.close();
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
public static class Channel extends Thread {
private static int clientIndex = 0;
private int index;
private Socket socket = null;
public Channel(Socket socket) {
clientIndex++;
index = clientIndex;
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter writer = new PrintWriter(socket.getOutputStream());
while (true) {
String input = reader.readLine();
System.out.println("Got from client "+index+": "+input);
//bye bye
if (input.equalsIgnoreCase("bye")) {
break;
}
writer.println("Gotcha");
writer.flush();
}
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
finally {
if (socket != null) {
try {
socket.close();
}
catch(Exception e) {
System.err.println(e);
e.printStackTrace();
}
}
}
}
}
}
String userInput = readerFromCommandLine.readLine();
BufferedReader.readLine() is a problem here. It is going to block your thread until input is received. This means communication can only ever go in one direction at a time, and can potentially get totally blocked if both clients are waiting.
DataFetcher can fix this problem; you can use it to listen in a separate Thread
http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/
You half way there.
You created a Threaded Server were each connection from a client opens a thread. This thread then loops and waits for messages.
Think of these threads as you connected clients with their own objects / properties and their streams to write to and read from them.
So each time a clients connections you want to create their thread add it to some kind of list and start their thread. For example:
At the top of the class
List<Channel> my_clients = new List<Channel>();
In your while loop
Channel my_new_client = new Channel(client);
my_clients.add(my_new_client);
my_new_client.start();
Then when you want to send a message to a certain clients. You can loop all the Threads and look for one that has some kind of name or Unique Indentifier. For example:
for(Channel my_client : my_clients) {
if(my_client.getName() == "Me") {
my_client.write("HELLO!");
}
}
or in the same breath you could send a message to all your clients (Broadcast):
for(Channel my_client : my_clients) {
my_client.write("HELLO!");
}
remember to remove the clients when they disconnect too!
// Can't remember the precise exception correct my if I'm wrong!
catch(SocketException ex) {
my_clients.remove(this);
}
Note this expects that you some how authenticate and know the name of your client or supply them a UID which you reference when you are instructed to sent them something. And that the Channel class has the Write Method for connivance.
Hope that Help!

Categories

Resources