Problems running frequent bash commands in Java HTTP Server - java

I implemented a simple HTTP Server that once calling an endpoint, it will retrieve a text file from S3 and returns it. Unfortunately, when the requests are high, like 100 times per second, it goes to unstable state and can't respond to HTTP requests and they go to timeout. For accessing the S3, I'm run a bash command (which one command takes 2s to execute), so one thought I have is maybe the frequent bash commands and pipes is not efficient. And to add, we are running the code in kubernetes in case it might also cause resource restrictions, etc.
What is the problem? Is it the frequent pipes, HTTP Server API, etc? How to address it?
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URI;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
public class FileRetriever implements Runnable {
HttpServer server;
ProcessBuilder processBuilder;
public FileRetriever() {
processBuilder = new ProcessBuilder();
Thread t = new Thread(this);
t.start();
}
public void run() {
try {
server = HttpServer.create(new InetSocketAddress(serverPort), 0);
server.createContext("/getfile", new GetFileHandler());
server.setExecutor(null);
server.start();
} catch (IOException e) {
logger.error("HttpServer ERROR", e);
}
}
class GetFileHandler implements HttpHandler {
#Override
public void handle(HttpExchange he) throws IOException {
// parse request
// http://localhost:9003/getfile?id=xxxxx
String response = "";
URI requestedUri = he.getRequestURI();
String query = requestedUri.getRawQuery();
String pair[] = query.split("=");
String id="";
if (pair[0].equals("id")) {
id = pair[1];
try {
String command = "aws --endpoint-url="+S3server+" s3 cp s3://file-store/"+id+"/files/"+id+".txt -";
processBuilder.command("sh", "-c", command+" ; true");
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader readerErrors = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line;
while ((line = reader.readLine()) != null) {
response+=line+"\n";
}
if(response.trim().equals("")) {
response="Not Found";
he.sendResponseHeaders(404, response.length());
}
else {
logger.info("Received file successfully: " + id);
he.sendResponseHeaders(200, response.length());
}
} catch (Exception e) {
response = "ERROR in GetFileHandler.";
}
OutputStream os = he.getResponseBody();
os.write(response.toString().getBytes());
os.close();
}
}
}
}

Related

Trouble writing to OutputStream socket

I am writing a simple web server program for class that sends files to the web browser on request. I have written as much as I could. The difficulty is getting the data written to the OutputStream. I don't know what I am missing. I couldn't get the simple request to show up on the web browser.
I wrote it to the "name" OutputStream but when I reload the tab in the browser with the URL: "http://localhost:50505/path/file.txt" or any other like that "localhost:50505" it doesn't show up what I wrote to the OutputStream "name". It is supposed to show that.
package lab11;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketImpl;
import java.util.Scanner;
import java.io.OutputStream;
import java.io.PrintWriter;
public class main {
private static final int LISTENING_PORT = 50505;
public static void main(String[] args) {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(LISTENING_PORT);
}
catch (Exception e) {
System.out.println("Failed to create listening socket.");
return;
}
System.out.println("Listening on port " + LISTENING_PORT);
try {
while (true) {
Socket connection = serverSocket.accept();
System.out.println("\nConnection from "
+ connection.getRemoteSocketAddress());
handleConnection(connection);
}
}
catch (Exception e) {
System.out.println("Server socket shut down unexpectedly!");
System.out.println("Error: " + e);
System.out.println("Exiting.");
}
}
public static void handleConnection(Socket sok) {
try {
// Scanner in = new Scanner(sok.getInputStream());
InputStream one = sok.getInputStream();
InputStreamReader isr = new InputStreamReader(one);
BufferedReader br = new BufferedReader(isr);
String rootDirectory = "/files";
String pathToFile;
// File file = new File(rootDirectory + pathToFile);
StringBuilder request = new StringBuilder();
String line;
line = br.readLine();
while (!line.isEmpty()) {
request.append(line + "\r\n");
line = br.readLine();
}
// System.out.print(request);
String[] splitline = request.toString().split("\n");
String get = null;
String file = null;
for (String i : splitline) {
if (i.contains("GET")) {
get = i;
String[] splitget = get.split(" ");
file = splitget[1];
}
}
}
OutputStream name = sok.getOutputStream();
Boolean doesexist = thefile.exists();
if (doesexist.equals(true)) {
PrintWriter response = new PrintWriter(System.out);
response.write("HTTP/1.1 200 OK\r\n");
response.write("Connection: close\r\n");
response.write("Content-Length: " + thefile.length() + "\r\n");
response.flush();
response.close();
sendFile(thefile, name);
} else {
System.out.print(thefile.exists() + "\n" + thefile.isDirectory() + "\n" + thefile.canRead());
}
}
catch (Exception e) {
System.out.println("Error while communicating with client: " + e);
}
finally { // make SURE connection is closed before returning!
try {
sok.close();
}
catch (Exception e) {
}
System.out.println("Connection closed.");
}
}
private static void sendFile(File file, OutputStream socketOut) throws
IOException {
InputStream in = new BufferedInputStream(new FileInputStream(file));
OutputStream out = new BufferedOutputStream(socketOut);
while (true) {
int x = in.read(); // read one byte from file
if (x < 0)
break; // end of file reached
out.write(x); // write the byte to the socket
}
out.flush();
}
}
So, I don't know what I really did wrong.
When I load the browser with localhost:50505 it just says can't connect or localhost refused to connect.
You are writing the HTTP response in System.out. You should write it in name, after the headers, in the body of the response. You probably want to describe it with a Content-Type header to make the receiver correctly show the file.

How do I get my multithreaded server/client chat program to echo messages to all clients using sockets?

right now I have a java program that uses threads and sockets to echo text responses like a real chat window. Currently, my program works by running the server and than as many clients as I want. When a client enters a message, that message is echoed to the server and also to the client that sent the message.
My problem is that I want the message any client enters to be sent not only to the server and to themselves, but to every other client as well.
Heres how it currently works:
Server:
Received client message: test1
Client 1:
Enter message: test1
test1
Client 2:
Enter message:
Client 1 enters test1, receives test1 back and the server also receives test1. Client 2 gets nothing. My goal is to have any messages entered in the clients display on the client that sent the message as well as the other clients and server.
Working example:
Server:
Received client message: test1
Received client message: hello
Client 1:
Enter message: test1
test1
From client 2: hello
Client 2:
Enter message:
From client 1: test1
hello
The formatting doesnt have to be exactly like that, but thats the idea. My code so far is below. Ive read that I need to add my clients to a list and then loop over them and send them all the message but im not sure. Any help would be great.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Scanner;
public class EchoMultiThreadClient {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 4000)) {
//socket.setSoTimeout(5000);
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);
Scanner scanner = new Scanner(System.in);
String echoString;
String response;
do {
System.out.println("Enter string to be echoed: ");
echoString = scanner.nextLine();
pw.println(echoString);
if(!echoString.equals("exit")) {
response = br.readLine();
System.out.println(response);
}
} while(!echoString.equals("exit"));
// }catch(SocketTimeoutException e) {
// System.out.println("The Socket has been timed out");
} catch (IOException e) {
System.out.println("Client Error: " + e.getMessage());
}
}
}
server code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
public class EchoMultiThreadServer {
private static Vector<Echoer> clients = new Vector<Echoer>();
public static void main(String [] args) {
try(ServerSocket serverSocket = new ServerSocket(4000)){
while(true) {
Socket socket = serverSocket.accept();
Echoer echoer = new Echoer(socket);
echoer.start();
clients.add(echoer);
}
}catch(IOException e) {
System.out.println("Server Exception"+e.getMessage());
}
}
}
thread code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class Echoer extends Thread{
private Socket socket;
public Echoer(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter wr = new PrintWriter(socket.getOutputStream(), true);
while(true) {
String echoString = in.readLine();
System.out.println("Received Client Input: " + echoString);
if(echoString.equals("exit")) {
break;
}
wr.println(echoString);
}
}catch(IOException e) {
System.out.println("Oooops " + e.getMessage());
}finally {
try {
socket.close();
}catch(IOException e) {
// later
}
}
}
}
I can see two problems with your current logic:
At the client side, you are essentially reading user input, then sending to server and getting a (single) response. So the problem here is that you only get one response, while you should take more than one for each user input line: that is the user's input plus the other users' input. Since you don't know when and how many the other users' inputs are going to be, you need to go asynchronous. I mean that you need 2 threads: one for reading user input and the other for reading server input/response (note: we are still at the client side). Since you already have one of the 2 threads, ie the one which runs the main method, then you can use it instead of creating a new one.
At the server side, your Echoer is reading user input but only sending it back to the same client. You need for example a loop to send the client's input to all other clients too.
So what would seem to me a proper logic is:
Client side:
Reading server's responses thread logic:
forever, do:
get server's message.
print server's message to user.
main method:
connect to server.
start a "Reading server's responses thread".
get user input.
while the user's input it not "exit", do:
send user's input to server.
get user input.
disconnect from server.
Server side:
Echoer thread:
forever, do:
read client's message.
for every client, do:
send the message to the client.
main method:
start server socket.
forever, do:
accept incoming connection.
start an Echoer thread for the accepted connection.
There are some missing bits though, such as how to maintain the list of all clients, but for that I can see you are already using a Vector<Echoer> clients at the server side. So just pass that Vector to every Echoer you create, so they can do the broadcasting of each incomming message. Important note here: at the server side, you have more than one threads: the main one and each Echoer, so make sure you synchronize on the Vector while you are modifying it at the main thread and also while broadcasting at the Echoers.
Notes:
I am assuming in all the above logic that there is no particular order in which the clients send their messages. For example if always client A sent first, then client B and so on, and the whole process was repeating, then you wouldn't need to go multithreading at all.
Please take your time. First implement it and then tell me if you encouter any problems.
Edit 1: full sample code.
Client code:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class Client {
//This is the "Reading server's responses thread" I am talking about in the answer.
private static class ReadingRunnable implements Runnable {
private final BufferedReader serverInput;
public ReadingRunnable(final InputStream is) {
serverInput = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
}
#Override
public void run() {
try {
//While the server is not disconnected, we print each line to 'System.out':
for (String line = serverInput.readLine(); line != null; line = serverInput.readLine())
System.out.println(line);
}
catch (final IOException iox) {
iox.printStackTrace(System.out);
}
finally {
System.out.println("Input from server stopped.");
}
}
}
public static void main(final String[] args) {
try {
System.out.print("Connecting... ");
try (final Socket sck = new Socket("localhost", 50505);
final OutputStream os = sck.getOutputStream();
final InputStream is = sck.getInputStream()) {
System.out.println("Connected.");
new Thread(new ReadingRunnable(is)).start();
final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8));
final Scanner scan = new Scanner(System.in);
for (String userInput = scan.nextLine(); !"exit".equalsIgnoreCase(userInput); userInput = scan.nextLine()) {
bw.write(userInput);
bw.newLine();
bw.flush();
}
}
}
catch (final IOException iox) {
iox.printStackTrace(System.out);
}
finally {
System.out.println("Output from user stopped.");
}
}
}
Server code:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Objects;
public class Server {
private static class Echoer implements Runnable {
private final ArrayList<Echoer> all;
private final BufferedWriter bw;
private final BufferedReader br;
public Echoer(final ArrayList<Echoer> all,
final InputStream is,
final OutputStream os) {
this.all = Objects.requireNonNull(all);
bw = new BufferedWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8));
br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
}
//Instead of exposing 'bw' via a getter, I just built a helper method to send a message to the Echoer:
public void send(final String msg) throws IOException {
bw.write(msg);
bw.newLine();
bw.flush();
}
#Override
public void run() {
try {
for (String line = br.readLine(); line != null; line = br.readLine()) {
System.out.println(line); //Print the received line at the server.
synchronized (all) { //We are reading from a collection which may be modified at the same time by another (the main) Thread, so we need to synchronize.
//Broadcast the received line:
for (int i = all.size() - 1; i >= 0; --i) {
try {
all.get(i).send(line);
}
catch (final IOException iox) {
all.remove(i); //In case we cannot send to the client, disconnect him, ie remove him from the list in this simple case.
}
}
}
}
}
catch (final IOException iox) {
}
finally {
synchronized (all) {
all.remove(this); //Disconnect him, ie remove him from the list in this simple case.
}
System.out.println("Client disconnected.");
}
}
}
public static void main(final String[] args) throws IOException {
System.out.print("Starting... ");
try (final ServerSocket srv = new ServerSocket(50505)) {
final ArrayList<Echoer> all = new ArrayList<>();
System.out.println("Waiting for clients...");
while (true) {
final Socket sck = srv.accept();
try {
final OutputStream os = sck.getOutputStream();
final InputStream is = sck.getInputStream();
final Echoer e = new Echoer(all, is, os); //Pass all the Echoers at the new one.
synchronized (all) { //We will write to a collection which may be accessed at the same time by another (an Echoer) Thread, so we need to synchronize.
all.add(e); //Update list of Echoers.
}
new Thread(e).start(); //Start serving Echoer.
}
catch (final IOException iox) {
System.out.println("Failed to open streams for a client.");
}
}
}
}
}

Android tcp socket can not receive data

I am trying to work with sockets in android programming, sending to the server works fine but i have problems with receiving a string from the server.
the socket is connected, but if the server is sending a string the android app only prints out: java.io.BufferedReader#418daee0
i dont know what that mean..is it an error or something like that?
this is my code:
Maybe someone could help me a little bit to get that work.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class Client extends Activity {
private Socket socket;
private static final int SERVERPORT = 2000;
private static final String SERVER_IP = "192.168.1.1";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Thread(new ClientThread()).start();
}
class ClientThread implements Runnable {
#Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
InputStream in = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String test = br.toString();
TextView message = (TextView) findViewById(R.id.received);
message.setText(test);
//in.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
what you need to do is read from the BufferedReader. Currently you are just printing the br object.
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = br.readLine ()) != null) {
System.out.println (line);
}
as per the javadocs readLine will return null if the end of the stream has been reached
problem:
String test = br.toString();
You are basically referencing the memory location in string form of the br object thus printing the memory location in your TextView. What you need to do is to read the inputStream from the socket connection of the server from your BufferedReader object.
solution:
String test = br.readLine();
The readLine method will wait for the response of the server from the InputStream where the socket is connected. Now the above will only get one line of response from the server if the server sends multiple line then you put it in a while loop.

Single java thread using excess system resources

I am trying to create a server listener. It sits back and waits for data coming from the client and performs setting actions due to the nature of the data. But right now, after receiving the first data stream, it goes into a resource hog, the memory usage shoots up and the CPU usage is maxing out a single core.
1 - How can I fix this? How can I make it listen without all the resource hog, as you can see it is a really really small program.
2 - The client itself that sends these data streams, runs once. It starts up, connects to the server, sends the data and quits. While the server is still "on", if I retry running the client again, the server doesn't receive the data.
Server Code:
package mediaserver;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Main {
ServerSocket ss;
Socket s;
BufferedReader br;
public Main() throws IOException{
ss = new ServerSocket(1111);
s = ss.accept();
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
new Thread(new runner()).start();
}
class runner implements Runnable{
public void run(){
while(true){
try {
String n = br.readLine();
System.out.println(n);
} catch (IOException ex) {
}
finally{
try {
s.close();
ss.close();
} catch (IOException ex) {
}
}
}
}
}
public static void main(String[] args) throws IOException {
new Main();
}
}
Client Code
package mediaserver;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class test {
public static void main(String [] args) throws UnknownHostException, IOException, InterruptedException{
Socket s = new Socket("127.0.0.1", 1111);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bw.write("");
bw.newLine();
bw.flush();
}
}
The server never gets the data on additional run because ss.accept() is only called one time. You need to wrap this in a loop:
s = ss.accept();
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
new Thread(new runner()).start();
The following piece of code is an infinite loop:
while(true) {
try {
String n = br.readLine();
System.out.println(n);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
finally {
...
}
}
Once the client disconnects, the BufferedReader instance will encounter the end-of-file and readLine will return null. The loop then will continue to print null infinitely.
The fix it, check for null:
while(true) {
try {
String n = br.readLine();
if (n == null)
break;
System.out.println(n);
} catch (IOException ex) {
}
finally {
...
}
}

multithread client-server chat, using sockets

Server and client communicating with my own protocol which looks like XMPP. I should to realize chat application. So when one user write String it immedeatly should be sended to other client through the server. I have method sendToAll on server. But user see the message of other user only when it press enter.
How can user receive messages without pressing enter button?
So this is my client:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.apache.log4j.Logger;
import dataart.practice.protocols.XMLProtocol;
public class Client {
public static final String SERVER_HOST = "localhost";
public static final Integer SERVER_PORT = 4444;
public static final Logger LOG = Logger.getLogger(Client.class);
private static BufferedReader in;
private static PrintWriter out;
private static BufferedReader inu;
public static void main(String[] args) throws IOException {
System.out.println("Welcome to Client side");
XMLProtocol protocol = new XMLProtocol();
Socket fromserver = null;
fromserver = new Socket(SERVER_HOST, SERVER_PORT);
in = new BufferedReader(new InputStreamReader(fromserver.getInputStream()));
out = new PrintWriter(fromserver.getOutputStream(), true);
inu = new BufferedReader(new InputStreamReader(System.in));
String fuser, fserver;
while (true){
if(in.ready()){//fserver = in.readLine()) != null) {
System.out.println("asdasdsd");
fuser = inu.readLine();
if (fuser != null) {
if (fuser.equalsIgnoreCase("close"))
break;
if (fuser.equalsIgnoreCase("exit"))
break;
protocol.setComId((long) 0);
protocol.setContent(fuser);
protocol.setLogin("Guest");
try {
JAXBContext jaxbContext = JAXBContext.newInstance(XMLProtocol.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
jaxbMarshaller.marshal(protocol, out);
out.flush();
} catch (JAXBException e) {
LOG.error("Error while processing protocol" + e);
}
}
}
}
out.close();
in.close();
inu.close();
fromserver.close();
}
}
And Server with ServerThread.
public static void main(String[] args) throws IOException {
LOG.trace("Server started");
ServerSocket s = new ServerSocket(SERVER_PORT);
try {
while (true) {
LOG.trace("Waiting for connections...");
Socket socket = s.accept();
try {
// new ServerThread(socket);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
userCounter++;
addUser("Guest" + userCounter, out);
LOG.trace("User " + userCounter + " has been added!");
exec.execute(new ServerThread(socket, in, out));
} catch (IOException e) {
socket.close();
}
}
} finally {
s.close();
}
}
ServerThread.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.Socket;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import org.apache.log4j.Logger;
import dataart.practice.protocols.XMLProtocol;
import dataart.practice.serverUtils.Commands;
public class ServerThread implements Runnable {
private static final Logger LOG = Logger.getLogger(ServerThread.class);
private XMLProtocol protocol;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
private String buffer = "";// may be exist another. way but it's not working
private Boolean login = false;
public ServerThread(Socket s, BufferedReader in, PrintWriter out) throws IOException {
this.in = in;
this.out = out;
out.println("</XMLProtocol>");
socket = s;
new Thread(this);
}
public void run() {
try {
while (true) {
if ((buffer = in.readLine()) != null) {
if (buffer.endsWith("</XMLProtocol>")) {
protocol = getProtocol(buffer);
//Server.onlineUserList.put(protocol.getLogin(), out);
/* if (!login){
out.println("Maybe login first?");
}
*/
LOG.trace("Getting message from user: " + protocol.getLogin() + " recived message: " + protocol.getContent());
///out.println(protocol.getLogin() + " says:" + protocol.getContent());
Server.sendToAll(protocol.getContent()+"</XMLProtocol>");
} else {
LOG.trace("Nop protocol do not send with it end");
}
}
}
} catch (IOException e) {
LOG.error("Error in reading from stream: " + e);
} catch (JAXBException e) {
LOG.error("Error in Marshalling: " + e);
} finally {
try {
socket.close();
LOG.trace("Socket closed");
} catch (IOException e) {
LOG.error("Socket no closed" + e);
}
}
}
public XMLProtocol getProtocol(String buffer) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(XMLProtocol.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
return (XMLProtocol) jaxbUnmarshaller.unmarshal(new StreamSource(new StringReader(buffer)));
}
public Boolean loginIn(XMLProtocol protocol) {
return true;
}
}
You will need to multi-thread both the client and server. The client will need one thread that listens for messages from the server and writes them to his/her screen and one thread that waits for his/her keyboard input and sends it to the server. Likewise for each connection to the server, it will need a thread waiting for input from the client and one thread sending output from other users to the client.
The reason you don't see incoming messages until you press enter is because of the client while loop. It's commented out now, but it looks like your loop used to:
- Read incoming messages from server
- Read input from keyboard
- Send input to server
So you read whatever was available from the server, and then the client waits for more keyboard input before reading from the server again (in the next iteration).
Another word of advice, from my understanding, creating JAXBContext can be an expensive operation. You don't need to recreate it every time you send a message. Consider initializing one in your server and client and then reusing it for each marshall/unmarshall.
Try this,
Do Not use BufferedReader() with PrintWriter..... PrintWriter is itself the Bridge between byte level socket data and character form.
Eg:
I am showing for a single client, use the while loop for n nos of clients
ServerSocket s = new ServerSocket(4444);
Socket incoming = s.accept();
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
System.out.println(pw.write(new Scanner(System.in).nextLine()));

Categories

Resources