how to read multiple lines from client to server - java

So i'm trying to send multiple lines of code everytime i type something in the client console. However when doing this it only prints the output of the client in the server once, what i would like to do is print the clients output in the server everytime after entering a line.
Client:
try {
Scanner scanner = new Scanner(System.in);
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
DataOutputStream outputStream;
System.out.println("Write something to client:");
while(scanner.hasNext()) {
System.out.println("Write something to client:");
outputStream = new DataOutputStream(socket.getOutputStream());
String message = scanner.nextLine();
outputStream.writeUTF(message);
}
} catch (IOException e) {
System.out.println("[ERROR] Unable to get streams from server");
}
}
ClientThread:
#Override
public void run() {
try {
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
System.out.println(inputStream.readUTF());
} catch (IOException e) {
e.printStackTrace();
}
}
Server:
public Server() {
try {
serverSocket = new ServerSocket(port);
System.out.println("[SERVER] Server initialized successfully");
// consider using!
Runtime.getRuntime().addShutdownHook(new Thread());
} catch (IOException e) {
System.out.println("[ERROR] Unable to launch server on port " + port);
}
while (true) {
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (IOException e) {
System.out.println("[ERROR] Unable to accept client request");
}
System.out.println("[SERVER] New user joined the chat: " + socket);
groupCounter++;
ClientThread client = new ClientThread("Client " + groupCounter, socket);
Thread thread = new Thread(client);
thread.start();
groupClients.add(client);
//System.out.println(groupCounter);
}

The problem is in the server side, serverSocket.accept() stops the execution and waits for a client to connect to the server socket. That's why you only receive one message every time.
Add an infinite loop in the ClientThread to make sure it keeps on reading the client socket input.
try {
while (true) {
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
System.out.println(inputStream.readUTF());
}
} catch (IOException e) {
e.printStackTrace();
}

Related

How can a server broadcast a message to other clients?

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.

Multi client chat application In java

I just got started with socket programming so in order to improve my understandings of it I wanna build a multi-client chat application.
They way I intend to do it is the following:
Once the application starts you have two choices: create server or join server.
If you chose to create a server a new thread will start and host the server, then another thread will start which is gonna create a new client and automatically connect to the server just build.
And here I've encountered the following problem.
Each client can send messages to the server, but in order to keep them synchronized for all clients I was thinking to redirect the retrieved messages from the server to all clients as shown in the following diagram.
The thing is that when I try to listen and send on both client and server I get this errors.
java.net.SocketException: Connection reset
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:200)
at java.base/java.io.DataInputStream.readUnsignedShort(DataInputStream.java:342)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:594)
at java.base/java.io.DataInputStream.readUTF(DataInputStream.java:569)
at parctice.Server.lambda$main$0(Server.java:32)
at java.base/java.lang.Thread.run(Thread.java:835)
This is my server:
int port = 4444;
try {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("server starts port = " + serverSocket.getLocalSocketAddress());
while(true){
Socket socket = serverSocket.accept();
System.out.println("accepts : " + socket.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
String[] message = {""};
new Thread(() -> {
try {
while(in.available() > 0){
System.out.println("SERVER > " + in.readUTF());
message[0] = in.readUTF();
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
System.err.println(message[0]);
try {
out.writeUTF(message[0] + "REDIRECTED MESSAGE");
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
and my client:
int portNumber = 4444;
System.out.println("CLIENT > Trying to connect to the server...");
try {
Socket socket = new Socket("localhost", portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
new Thread(() -> {
try {
while(in.available() > 0){
System.out.println("SERVER > " + in.readUTF());
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
try {
out.writeUTF("test");
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
In the end I would like to ask you guys if you think that the logic that I try to use is the right one and if not please let me know what's wrong and also if possible could you explain me why I am not being able to listen and send on both, client and server? Because when I try to send data through client and retrieve it on the server it works just fine, but I would like to accomplish both ways communication.
I've found this solution which seems to work for this scenario
First time we create the server:
private List<ClientThread> clients; // or "protected static List<ClientThread> clients;"
public List<ClientThread> getClients(){
return clients;
}
private void startServer(){
clients = new ArrayList<ClientThread>();
try {
serverSocket = new ServerSocket(PORT);
System.out.println("SERVER ON");
System.out.println("SERVER > Waiting for connections...");
// ACCEPT ALL CONNECTIONS
while (true){
try {
Socket socket = serverSocket.accept();
System.out.println("SERVER > New connection: " + socket.getRemoteSocketAddress());
ClientThread client = new ClientThread(this, socket);
Thread thread = new Thread(client);
thread.start();
clients.add(client);
} catch (IOException e) {
e.printStackTrace();
System.out.println("SERVER > Accept failed");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
Then for each client we create a new thread
public class ClientThread implements Runnable {
private Socket socket;
private Server server;
private String clientName;
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public ClientThread(Server server, Socket socket) {
this.server = server;
this.socket = socket;
}
#Override
public void run() {
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF("HI FROM SERVER");
while (!socket.isClosed()) {
try {
if (in.available() > 0) {
String input = in.readUTF();
// UNCOMMENT TO READ ON SERVER
// System.out.println("SERVER > " + input);
for (ClientThread thatClient : server.getClients()){
DataOutputStream outputParticularClient = new DataOutputStream(thatClient.getSocket().getOutputStream());
outputParticularClient.writeUTF(input + " GOT FROM SERVER");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Client:
public void createClient(){
try {
socket = new Socket("localhost", portNumber);
// socket = new Socket(getHost(), portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
new Thread(()->{
while(!socket.isClosed()){
try {
if (in.available() > 0){
String input = in.readUTF();
System.out.println(getUserName() + " > " + input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}

why it says that there is no line in the clients InputStream?(socket programming)

I tried to write a simple program that runs a server and then accepts two clients. Then one of them tries to send a string to another client.
but my code doesn't work and I don't know why.
This is my TestClient class:
public class TestClient extends Thread{
int id;
String Name;
Socket client;
boolean isAsk;
public TestClient(int id,String clientName,boolean isAsk) throws IOException {
this.id=id;
this.Name=clientName;
this.isAsk=isAsk;
}
public void connectTheClientToTheLocalHost(ServerSocket server){
try {
client = new Socket("localhost",1111);
server.accept();
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFromTerminal(){
try {
InputStream is=client.getInputStream();
OutputStream os = client.getOutputStream();
PrintWriter pw = new PrintWriter(os);
pw.println("sdklfsdklfk");
pw.flush();
pw.close();
}catch (IOException e){
e.printStackTrace();
}
}
public void closeTheCientSocket(){
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void write(){
try {
Scanner sc = new Scanner(client.getInputStream());
BufferedWriter bw = new BufferedWriter(new FileWriter(new File("file1.txt")));
String st =sc.nextLine();
bw.write(st);
bw.close();
}catch (IOException e){
e.printStackTrace();
}
}
#Override
public void run() {
if(isAsk){
readFromTerminal();
}
else{
write();
}
}
and this is the main function:
public class PCServer {
public static void main(String[] args){
try {
ServerSocket s = new ServerSocket(1111);
TestClient t1=(new TestClient(1,"reza",true));
TestClient t2=(new TestClient(2,"man",false));
t1.connectTheClientToTheLocalHost(s);
t1.start();
Scanner sc = new Scanner(t1.client.getInputStream());
String st=sc.nextLine();
System.out.println(st);
t1.closeTheCientSocket();
t2.connectTheClientToTheLocalHost(s);
PrintWriter pw = new PrintWriter(t2.client.getOutputStream());
pw.println(st);
pw.flush();
t2.start();
t2.closeTheCientSocket();
}catch (Exception e){
e.printStackTrace();
}
}
}
actually this code returns an exception in
String st=sc.nextLine();
in main function and says that there is no line found.
what is the problem?
ServerSocket in java usually used in another way.
If you need point-to-point connection, one host creates a ServerSocket and accepts connections. Examples:
First host example:
try(ServerSocket serverSocket = new ServerSocket(5555);
Socket socket = serverSocket.accept();
// it more convenient to use DataInputStream instead of Scanner I think
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());) {
while (!Thread.currentThread().isInterrupted()) {
String msg = dataInputStream.readUTF();
System.out.println("got request: " + msg);
dataOutputStream.writeUTF("1-response");
dataOutputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
Second host example:
try(Socket socket = new Socket("127.0.0.1", 5555);
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) {
while (!Thread.currentThread().isInterrupted()) {
dataOutputStream.writeUTF("2-request");
dataOutputStream.flush();
String msg = dataInputStream.readUTF();
System.out.println("got response: " + msg);
}
} catch (IOException e) {
e.printStackTrace();
}
If you want one host talk to another over the server (broker), then you need plane java Sockets on hosts and ServerSocket on broker, and broker must transmit messages it received from one host to another. Examples:
Broker (run it in separate thread or process)
try {
List<Socket> sockets = new ArrayList<>();
ServerSocket serverSocket = new ServerSocket(5555);
// accepting connections from 2 clients
for (int i = 0; i < 2; i++) {
Socket socket = serverSocket.accept();
sockets.add(socket);
}
// streams for first host
InputStream hostOneInputStream = sockets.get(0).getInputStream();
DataInputStream hostOneDataInputStream = new DataInputStream(sockets.get(0).getInputStream());
DataOutputStream hostOneDataOutputStream = new DataOutputStream(sockets.get(0).getOutputStream());
// streams for second host
InputStream hostTwoInputStream = sockets.get(1).getInputStream();
DataInputStream hostTwoDataInputStream = new DataInputStream(sockets.get(1).getInputStream());
DataOutputStream hostTwoDataOutputStream = new DataOutputStream(sockets.get(1).getOutputStream());
while (!Thread.currentThread().isInterrupted()) {
if (hostOneInputStream.available() > 0) {
String msg = hostOneDataInputStream.readUTF();
System.out.println("got message from host 1: " + msg);
hostTwoDataOutputStream.writeUTF(msg);
hostTwoDataOutputStream.flush();
System.out.println("message " + msg + " sent to host two");
}
if (hostTwoInputStream.available() > 0) {
String msg = hostTwoDataInputStream.readUTF();
System.out.println("got message from host 2: " + msg);
hostOneDataOutputStream.writeUTF(msg);
hostOneDataOutputStream.flush();
System.out.println("message " + msg + " sent to host one");
}
}
} catch (IOException e) {
e.printStackTrace();
}
First host (run it in separate thread or process)
try(Socket socket = new Socket("127.0.0.1", 5555);
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) {
while (!Thread.currentThread().isInterrupted()) {
dataOutputStream.writeUTF("1");
dataOutputStream.flush();
String msg = dataInputStream.readUTF();
System.out.println("got msg: " + msg);
TimeUnit.SECONDS.sleep(5);
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
Second host (run it in separate thread or process)
try(Socket socket = new Socket("127.0.0.1", 5555);
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) {
while (!Thread.currentThread().isInterrupted()) {
String msg = dataInputStream.readUTF();
System.out.println("got msg: " + msg);
TimeUnit.SECONDS.sleep(5);
dataOutputStream.writeUTF("2");
dataOutputStream.flush();
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}

Socket don't save values in list

I'm new in network developing in Java and I want to create a simple Socket server, that get values from client and collects all of them in ArrayList. I wrote an example code, but in server side it not collecting the strings. This is my server side:
Server
public class ServerSideSocket extends Thread{
private ServerSocket serverSocket;
private Socket socket;
private ArrayList<String> list = new ArrayList<String>();
DataInputStream inData;
DataOutputStream outData;
public ServerSideSocket(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public void run() {
while(true) {
try{
System.out.println("Waiting for connection...");
socket = serverSocket.accept();
System.out.println("Connected!" );
inData = new DataInputStream(socket.getInputStream());
outData = new DataOutputStream(socket.getOutputStream());
System.out.println(inData.readUTF());
list.add(inData.readUTF());
System.out.println("------------ VALUES ---------");
for (String value: list) {
System.out.println(value);
}
System.out.println("------------ END VALUES ---------");
outData.writeUTF("Message saved!");
outData.flush();
} catch (SocketException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inData.close();
outData.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
int port = 9999;
try {
Thread t = new ServerSideSocket(port);
t.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
and Client:
public class ClientSideSocket {
public static void main(String[] args) {
String serverName = "localhost";
int port = 9999;
String line = "";
try {
System.out.println("Connecting to " + serverName + " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to " + client.getRemoteSocketAddress());
OutputStream out = client.getOutputStream();
DataOutputStream outData = new DataOutputStream(out);
InputStream in = client.getInputStream();
DataInputStream inData = new DataInputStream(in);
outData.writeUTF("Simple text");
outData.flush();
System.out.println("Response from server: " + inData.readUTF());
System.out.println("You can write more messages!");
System.out.println();
client.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
what is wrong in my code?
This happens because you try to read twice from the data stream by calling inData.readUTF() method. First call successfully reads data from the stream, but instead of saving result you try to perform another read 2 lines below.
readUTF() is blocking method and thus it waits for another portion of data which never comes from the same client. That's why your server hungs forever
What you want to do is to read once and store result into local variable:
String res = inData.readUTF();
list.add(res);
You are writing data once as "Simple Text" which you can read only once.
Where in your code you are first reading it
System.out.println(inData.readUTF());
list.add(inData.readUTF());
Instead of this you should first store it in a String and then use it.
String message = inData.readUTF();
System.out.println(message);
list.add(message);

BufferedWriter.write() does not seem to work

I have two Java applications, where an Android client connects to a server on a computer and sends a message using BufferedWriter over websockets.
The client:
try {
toast("Sending...");
Socket sock = new Socket(ip, PORT);
OutputStream os = sock.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.flush();
bw.write("Hello Server!");
toast("Connected!");
} catch (UnknownHostException e) {
toast(e.getMessage());
} catch (IOException e) {
toast(e.getMessage());
}
The server:
public static void main(String[] args) {
ServerSocket server;
ConnectionThread ct;
Socket s;
ExecutorService es = Executors.newSingleThreadExecutor();
try {
System.out.println("Starting server...");
server = new ServerSocket(1337);
s = server.accept();
ct = new ConnectionThread(s);
es.execute(ct);
} catch (IOException ex) {
ex.printStackTrace();
}
}
The ConnectionThread class:
public class ConnectionThread implements Runnable {
private Socket sock;
private InputStream is;
private BufferedReader br;
private boolean online;
public ConnectionThread(Socket s) {
System.out.println("Creating connection thread.");
this.sock = s;
online = true;
}
#Override
public void run() {
String input = "";
try {
System.out.println("Starting to read...");
is = sock.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
while (online) {
input = br.readLine();
if(input != null){
System.out.print("Received message: ");
System.out.println(input);
}
}
br.close();
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
When I run the server, and then the client, the client will show the "Connected!" toast, and the server's output will be:
Starting server...
Creating connection thread.
Starting to read...
So, it seems like the connection is actually being made, but the message does not arrive. Does anybody know why this could be happening?
Your server is expecting a complete line terminated by a newline. Try:
bw.write("Hello Server!");
bw.newLine();
Do it like this...
String s = new String();
while ((br.readLine())!=null) {
s = s+br.readLine();
System.out.print("Received message: ");
System.out.println(input);
}
}
And
bw.println("Hello Server");
I notice that you don't send an endline on your client, so the BufferedReader.readline() will never return, because it cannot match the \n-character. Try it again with
bw.write("Hello Server!\n");
on the client side.

Categories