I'm trying to build a server with Java.
My question is: how to do if I have multiple users at the same time? The answer is: multi threading. But I don't know how to do.
For example, if there is two client connected at the same time, and a server (who does 2*number) : if the client1 say "50" to the server and the client 2 "10", the server is supposed to return "100" to the first client and "20" to the second. But i'm not sure my code works.
Server side:
public class Server {
public static void main(String[] args){
ServerSocket socket;
try {
socket = new ServerSocket(4444);
Thread t = new Thread(new Accept(socket));
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
class Accept implements Runnable {
private ServerSocket socketserver;
private Socket socket;
private int nbrclient = 1;
public Accept(ServerSocket s){
socketserver = s;
}
public void run() {
try {
socket = socketserver.accept();
in = new BufferedReader (new InputStreamReader (socket.getInputStream()));
String message = in.readLine();
System.out.println(message);
out = new PrintWriter(socket.getOutputStream());
out.println("Pong");
out.flush();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client side:
public class Client {
public static void main(String[] zero) {
Socket socket;
BufferedReader in;
PrintWriter out;
try {
socket = new Socket(InetAddress.getLocalHost(),4444);
out = new PrintWriter(socket.getOutputStream());
out.println("Ping");
out.flush();
in = new BufferedReader (new InputStreamReader (socket.getInputStream()));
String message = in.readLine();
System.out.println(message);
socket.close();
}catch (UnknownHostException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
}
If you have any ideas (how to do multi-threading and how to verify if my code works, like run two Clients.java and check if the multi-threading works)
The Server sides needs a while loop:
public class Server {
public static void main(String[] args){
ServerSocket socket;
try {
while(true){
socket = new ServerSocket(4444);
Socket socketInstance = socket.accept();
Thread t = new Thread(new Accept(socketInstance));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class Accept implements Runnable {
private Socket socket;
private int nbrclient = 1;
public Accept(Socket s){
socket = s;
}
public void run() {
try {
in = new BufferedReader (new InputStreamReader (socket.getInputStream()));
String message = in.readLine();
System.out.println(message);//this message should be your number
Double number = Double.parseString(message);
out = new PrintWriter(socket.getOutputStream());
//out.println("Pong");
out.println(2*number +"");
out.flush();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The client side looks ok. Just replace out.println("Ping"); with out.println("50"); or whatever you want.
You first start the server and then you can start multiple client applications. If you have any errors you can then post them here and have a look on an exact scenario.
Related
The program is intended to have multiple clients connect to a single server and the clients are able to send and receive messages among other clients.
For example if Client A says "Hi", Client B and Client C connected to the server would also receive "Hi".
In my current code, the server only receives the messages sent by the clients.
I'm currently looking for a solution to have the server broadcast the message sent by a client (eg. ClientA) to other clients. Any advice would be much appreciated.
This server class handles the connections of multiple clients with the use of threads:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
class EchoThread extends Thread {
private Socket socket;
//constructor
public EchoThread(Socket clientSocket) {
this.socket = clientSocket;
}
#Override
public void run() {
DataInputStream inp = null;
try {
inp = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//print whatever client is saying as long as it is not "Over"
String line = "";
while (!line.equals("Over")) {
try {
line = inp.readUTF();
System.out.println(line);
} catch (IOException e) { System.out.println(e); }
}
//closes connection when client terminates the connection
System.out.print("Closing Connection");
socket.close();
} catch (IOException e) { System.out.println(e); }
}
}
public class Server {
private static final int PORT = 5000;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
//starts the server
try {
serverSocket = new ServerSocket(PORT);
System.out.println("Server started");
System.out.println("Waiting for a client ...\n");
} catch (IOException e) { System.out.println(e); }
//while loop to accept multiple clients
int count = 1;
while(true) {
try {
socket = serverSocket.accept();
System.out.println("Client " + count + " accepted!");
count++;
} catch (IOException e) { System.out.println(e); }
//starts the server thread
new EchoThread(socket).start();
}
}
}
and this is the client class (I have multiple instances of this code running):
import java.net.*;
import java.io.*;
public class ClientA {
private Socket socket = null;
private DataInputStream input = null;
private DataOutputStream output = null;
public ClientA(String address, int port) {
//establish connection
try {
socket = new Socket(address, port);
System.out.println("Connected");
//takes input from terminal
input = new DataInputStream(System.in);
//sends output to the socket
output = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) { System.out.println(e); }
//string to read message from input
String line = "";
//keep reading until "Over" is input
while (!line.equals("Over")) {
try {
line = input.readLine();
output.writeUTF(line);
} catch (IOException e) { System.out.println(e); }
}
//close the connection
try {
input.close();
output.close();
socket.close();
} catch (IOException e) { System.out.println(e); }
}
public static void main (String args[]) {
ClientA client = new ClientA("127.0.0.1", 5000);
}
}
Do feel free to correct me on my code comments as I'm still not very familiar with socket programming.
You did well. Just add a thread to receive message in ClientA; and store socket clients in Server.
In fact, Server is also a "client" when is send message to client.
I add some code based on your code. It works well, hope it's helpful.
class EchoThread extends Thread {
//*****What I add begin.
private static List<Socket> socketList = new ArrayList<>();
//*****What I add end.
private Socket socket;
//constructor
public EchoThread(Socket clientSocket) {
this.socket = clientSocket;
socketList.add(socket);
}
#Override
public void run() {
DataInputStream inp = null;
try {
inp = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
//print whatever client is saying as long as it is not "Over"
String line = "";
while (!line.equals("Over")) {
try {
line = inp.readUTF();
System.out.println(line);
//*****What I add begin.
sendMessageToClients(line);
//*****What I add end.
} catch (IOException e) { System.out.println(e); break;}
}
//closes connection when client terminates the connection
System.out.print("Closing Connection");
socket.close();
} catch (IOException e) { System.out.println(e); }
}
//*****What I add begin.
private void sendMessageToClients(String line) throws IOException {
for (Socket other : socketList) {
if (other == socket) {
continue;//ignore the sender client.
}
DataOutputStream output = new DataOutputStream(other.getOutputStream());
output.writeUTF(line);
}
}
//*****What I add end.
}
public class ClientA {
private Socket socket = null;
private DataInputStream input = null;
private DataOutputStream output = null;
public ClientA(String address, int port) {
//establish connection
try {
socket = new Socket(address, port);
System.out.println("Connected");
//takes input from terminal
input = new DataInputStream(System.in);
//sends output to the socket
output = new DataOutputStream(socket.getOutputStream());
//*****What I add begin.
//Here create a thread to receive message from server.
DataInputStream inp = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
new Thread(() -> {
while (true) {
String str;
try {
str = inp.readUTF();
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();//error.
break;
}
}
}, "Client Reveiver.").start();
//*****What I add end.
} catch (IOException e) { System.out.println(e); }
//string to read message from input
String line = "";
//keep reading until "Over" is input
while (!line.equals("Over")) {
try {
line = input.readLine();
output.writeUTF(line);
} catch (IOException e) { System.out.println(e); }
}
//close the connection
try {
input.close();
output.close();
socket.close();
} catch (IOException e) { System.out.println(e); }
}
I would have a single server thread which would maintain a register of the clients, possibly in a concurrent collection. Then I would send each message received from a client to all other clients.
I want to establish a client-server-connection (with a Javafx Interface on the Clients side) but the Client will not connect to the server. Interestingly, when the launch(args)-Method-Call in the Main-method is commented out, the client will connect to the server.
I'm quite new to Java and especially Javafx and Client-Server-Applications.
The following Code do partially not represent the whole class, I've just left out methods that were not necessary in the context (or at least I think they are unnecessary.
Main.java
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
LoginUI loginUI = new LoginUI(primaryStage);
loginUI.setScene(primaryStage, loginUI.getScene());
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
try {
Client client = new Client(InetAddress.getLocalHost(), 9376);
} catch (UnknownHostException e) {
e.printStackTrace();
}
//loginUI.getSignUpUI().setSignUpButtonAction(client);
//my only Instace of LoginUI is in start-Method. How do I pass that to main, since main is static?
}
}
Client.java
public class Client {
private Socket clientSocket;
private DataOutputStream outputClient;
private DataInputStream inputClient;
public Client(InetAddress ipAddress, int port){
try {
this.clientSocket = new Socket(ipAddress, port);
this.outputClient = new DataOutputStream(clientSocket.getOutputStream());
this.inputClient = new DataInputStream(clientSocket.getInputStream());
outputClient.writeUTF("Client connected on port: " + clientSocket.getPort() + ", with IP: " + clientSocket.getInetAddress());
}
catch(IOException e3){
e3.printStackTrace();
}
}
}
Server.java
public class Server {
private ServerSocket skt;
private volatile boolean serverON;
private Socket clientSocket;
public Server(int port) {
try {
this.skt = new ServerSocket(port);
this.serverON = true;
}
catch(IOException e1){
e1.printStackTrace();
}
}
public void serverStart() {
while (serverON) {
clientSocket = null;
System.out.println("Waiting for client on port " + skt.getLocalPort());
try {
clientSocket = skt.accept();
System.out.println("Client has connected: " + clientSocket);
DataInputStream dataIn = new DataInputStream(clientSocket.getInputStream());
DataOutputStream dataOut = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("Trying to assign Thread to client...");
Thread thread = new ClientHandler(clientSocket, dataIn, dataOut);
thread.start();
}
catch (Exception e) {
try {
clientSocket.close();
}
catch (IOException e1){
e1.printStackTrace();
}
e.printStackTrace();
break;
}
}
}
}
ServerMain.java
public class ServerMain {
public static void main(String[] args){
Server server = new Server(9376);
server.serverStart();
}
}
I don't get any error (at least initially, errors still occur later when using the UI in specific ways) when the launch()-call is not commented out, the client just won't connect to the server.
I have a Server project and a Client project. While the Server is running the first connection from client works fine. At the seccond connection the Server fires the "java.net.BindException: Address already in use: JVM_Bind " error. Is there a way to add more connections on the same port?
Server:
public class Main {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Socket pipe = null;
while(true){
ServerSocket s = new ServerSocket(2345);
pipe = s.accept();
Connection c = new Connection(pipe);
c.start();
}
}
}
public class Connection extends Thread{
private Socket socket = null;
Mensch jim = null;
ObjectInputStream input = null;
ObjectOutputStream output = null;
ServerSocket s = null;
public Connection(Socket s){
socket = s;
}
public void run(){
try {
input = new ObjectInputStream(socket.getInputStream());
output = new ObjectOutputStream(socket.getOutputStream());
jim = (Mensch) input.readObject();
jim.setAge(33);
output.writeObject(jim);
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
And the Client:
public class Main {
public static void main(String[] args) {
Mensch jim = new Mensch(19, "Jim");
System.out.println(jim.getAge());
try {
Socket s = new Socket("127.0.0.1", 2345);
ObjectOutputStream clientOutputStream = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream clientInputStream = new ObjectInputStream(s.getInputStream());
clientOutputStream.writeObject(jim);
jim = (Mensch) clientInputStream.readObject();
System.out.println(jim.getAge());
clientOutputStream.close();
clientInputStream.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is the problem:
while(true) {
ServerSocket s = new ServerSocket(2345);
pipe = s.accept();
...
}
You're trying to bind to the same port repeatedly. All you need to do is create a single ServerSocket and call accept on it multiple times. (I'd also move the pipe variable declaration inside the loop...)
ServerSocket s = new ServerSocket(2345);
while(true) {
Socket pipe = s.accept();
...
}
The problem am having is that am not sure how to enable multiple clients to communicate with the server through threading, i've attempted it but I think am doing something wrong. Any help will be appreciated.
import java.io.*;
import java.net.*;
import java.util.*;
public class ChatServer {
ArrayList clientOutputStreams;
public class ClientHandler implements Runnable {
BufferedReader reader;
Socket sock;
public ClientHandler(Socket clientSocket) {
try {
sock = clientSocket;
InputStreamReader isReader = new InputStreamReader(
sock.getInputStream());
reader = new BufferedReader(isReader);
} catch (Exception x) {
}
}
public void run() {
String message;
try {
while ((message = reader.readLine()) != null) {
System.out.println("read" + message);
tellEveryone(message);
}
} catch (Exception x) {
}
}
}
public void go() {
clientOutputStreams = new ArrayList();
try {
ServerSocket serverSock = new ServerSocket(5000);
while (true) {
Socket clientSocket = serverSock.accept();
PrintWriter writer = new PrintWriter(
clientSocket.getOutputStream());
clientOutputStreams.add(writer);
Thread t = new Thread(new ClientHandler(clientSocket));
t.start();
System.out.println("got a connection");
}
} catch (Exception x) {
}
}
public void tellEveryone(String message) {
Iterator it = clientOutputStreams.iterator();
while (it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
} catch (Exception x) {
}
}
}
public static void main(String[] args) {
new ChatServer().go();
}`enter code here`
}
To allow multiple client to connect to your server you need a server to be continually looking for a new client to connect to. This can be done like:
while(true) {
Socket socket = Ssocket.accept();
[YourSocketClass] connection = new [YourSocketClass](socket);
Thread thread = new Thread(connection);
thread.start();
}
This is probably also best done in a separate server java file that can run independent of the client.
Problem:
I have written one java socket server which send response when I send first message from the client to it. But I want to send one more message based on the first response. After the first response i am not getting any other response?
Here is the Server code:
public class SendSmsServerSocket {
private final static CxpsLogger logger = CxpsLogger.getLogger(SendSmsServerSocket.class);
SendSmsServerSocket(){
try {
new SeverSocketForSms(new ServerSocket(4330));
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static class SeverSocketForSms extends Thread {
private Socket socket;
private ServerSocket serversocket;
private volatile static boolean running = true;
public SeverSocketForSms(ServerSocket ssocket) throws IOException {
this.serversocket = ssocket;
start();
}
public void run() {
try{
while(running) {
this.socket = serversocket.accept();
InputStreamReader ir = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(ir);
String msg = br.readLine();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("inside SeverSocketForSms: msg received is : "+msg);
}
}
catch(Exception e){
e.printStackTrace();
}
catch(Throwable t) {
System.out.println("Caught " + t + "xmlServerThread - closing thread");
}
}
public static void shutdown() {
System.out.println("Stopping socket connection and thread");
try{
socket.close();
}catch (Exception e) {
e.printStackTrace();
}
running = false;
}
public static void main (String [] args){
try {
System.out.println("Starting sms server ----- Please press Enter Key to stop the server after receiving one message");
SendSmsServerSocket s=new SendSmsServerSocket();
new Scanner(System.in).nextLine();
SeverSocketForSms.shutdown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Once you have an incoming connection, you should delgate the responsibility for handling that incoming connection to another Thread, otherwise you will block your "accept" thread until the current connection is closed...
while (running) {
this.socket = serversocket.accept();
Thread thread = new Thread(new Handler(socket));
thread.start();
}
And the Handler
public class Handler implements Runnable {
private Socket socket;
public Handler(Socket socket){
this.socket = socket;
}
public void run() {
// You may need to add a repeat and exit clause here...
InputStreamReader ir = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(ir);
String msg = br.readLine();
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("inside SeverSocketForSms: msg received is : " + msg);
}
}