Simple multithreaded socket server does not work (Socket is closed) - multithreading

I have a really simple multithreaded server as attached.
When my client calls the server, the server gives below exception:
java.net.SocketException: Socket is closed
but my code did not close the socket.
The first code segment is my client. The second and third code segments define the server and the way it handles requests. I had another single-threaded client-server and it worked properly.
Could somebody help take a look?
public class SocketClient {
public static void main(String[] args) {
String hostname = "127.0.0.1";
int port = 900;
try{
Socket socket = new Socket(hostname, port);
OutputStream output = socket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
writer.println("GET /");
writer.println();
writer.flush();
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (UnknownHostException ex) {
System.out.println("Server not found: " + ex.getMessage());
} catch (IOException ex) {
System.out.println("I/O error: " + ex.getMessage());
}
}
}
public class SimpleHTTPServer {
public static void main(String[] args) throws Exception {
//create a network socket which can accept connection on certain TCP port
//create Server which can accept requests
final ServerSocket server = new ServerSocket(900);
System.out.println("Listening for connection on port 900...");
while(true) {
try (Socket socket = server.accept()) { //creates socket when new request is received
System.out.println("received request");
RequestHandler rh = new RequestHandler(socket); //RequestHandler implements runnable interface, pass this object to create Thread
Thread thread = new Thread(rh);
thread.start(); //begins run() method defined in rh
}
}
}
}
public class RequestHandler implements Runnable {
private Socket socket;
public RequestHandler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
System.out.println("calling handleRequest");
handleRequest();
} catch (Exception e) {
System.err.println(e);
try {
socket.close();
} catch (IOException e1) {
System.err.println("Error Closing socket connection");
System.exit(0);
}
}
}
private void handleRequest() throws Exception {
System.out.println("handleRequest called");
Date today = new Date();
String httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + today;
System.out.println("1st" + httpResponse);
socket.getOutputStream().write(httpResponse.getBytes("UTF-8"));
System.out.println("2nd" + httpResponse);
System.out.println("got a new request");
}
}

I changed the server to below and it works-
public class SimpleHTTPServer {
public static void main(String[] args) throws Exception {
//create a network socket which can accept connection on certain TCP port
//create Server which can accept requests
final ServerSocket server = new ServerSocket(900);
System.out.println("Listening for connection on port 900...");
while(true) {
try { //creates socket when new request is received
Socket socket = server.accept();
System.out.println("received request");
RequestHandler rh = new RequestHandler(socket); //RequestHandler implements runnable interface, pass this object to create Thread
Thread thread = new Thread(rh);
thread.start(); //begins run() method defined in rh
// Date today = new Date();
// String httpResponse = "HTTP/1.1 200 OK\r\n\r\n" + today;
// socket.getOutputStream().write(httpResponse.getBytes("UTF-8"));
// System.out.println("got a new request");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

Related

Spring integration TCP/IP close connection problem

I use spring integration as a Full Duplex communication system's gateway module.
that flow is client app <--> spring-integration-ip-module (siid) <--> server app
The problem is when client app closed, ssid can't closed connection with server app side?
here is my code
// siid connet to client
#Bean
public TcpNetServerConnectionFactory server(){
TcpNetServerConnectionFactory server=new TcpNetServerConnectionFactory(1234);
server.setMapper(new TcpSerMapper()); // use 'mapper' attribute in XML
MySerializer mySeri=new MySerializer();
server.setDeserializer(mySeri);
server.setSerializer(mySeri);
return server;
}
// inboundGateway, inChannel as reqeustChannel
#Bean
public TcpInboundGateway inGate(){
TcpInboundGateway inGate=new TcpInboundGateway();
inGate.setConnectionFactory(server());
inGate.setRequestChannelName("inChannel");
inGate.setReplyChannelName("outputChannel");
return inGate;
}
// serviceActivator to get inChannel's payload msg and send though a gateway.
#ServiceActivator(inputChannel = "inChannel")
public byte[]doClientForward(Message<?> msg){
byte[]msgPayload=(byte[])(msg.getPayload());
byte[]sendResult=null;
ToTCP toTcp=(ToTCP)contextBean.get("toTcpBean"); // ToTCP is a gateway
sendResult=toTcp.sends((msgPayload),"localhost",7779);
QueueChannel outputChannel=(QueueChannel)contextBean.get("outputChannel");
return sendResult;
}
public static class DynamicSerSeri extends AbstractPooledBufferByteArraySerializer {
protected byte[] doDeserialize(InputStream inputStream, byte[] buffer) throws IOException {
byte[] bytes = this.copyBuffer(inputStream, buffer);
return bytes;
}
public void serialize(byte[] object, OutputStream outputStream) throws IOException {
outputStream.write(object);
}
public byte[] copyBuffer(InputStream inputStream, byte[] buffer) throws IOException {
int n = 0;
int bite = 0;
try {
while (true) {
bite = inputStream.read(); // blocked here
this.setMaxMessageSize(inputStream.available() + 1);
buffer = new byte[inputStream.available() + 1];
if (bite < 0 && n == 0) {
throw new SoftEndOfStreamException("Stream closed between payloads");
}
checkClosure(bite);
buffer[n++] = (byte) bite;
if (bite == -1) {
break;
}
if (n == this.maxMessageSize) {
break;
}
}
return buffer;
} catch (SoftEndOfStreamException e) {
throw e; // I was stuck here. when client closed, cf can't receive this exception and send close singnal to server side
} catch (IOException e) {
publishEvent(e, buffer, n);
throw e;
} catch (RuntimeException e) {
publishEvent(e, buffer, n);
throw e;
}
}
}
#MessagingGateway()
public interface ToTCP {
#Gateway(requestChannel = "toTcp.input", replyChannel = "outputChannel")
public byte[] sends(byte[] data, #Header("host") String host, #Header("port") int port);
}
#Bean
public IntegrationFlow toTcp() {
return f -> f.route(new ClientTcpRouter());
}
// I am not sure I understand IntegrationFlowContext,but it works
public static class ClientTcpRouter extends AbstractMessageRouter {
#Autowired
private IntegrationFlowContext flowContext;
#Override
protected synchronized Collection<MessageChannel> determineTargetChannels(Message<?> message) {
// connection to server side.
TcpNetClientConnectionFactory cf = new TcpNetClientConnectionFactory(host, port); //?? this connection factory does's closed when inGate's connection factory throw SoftEndOfStreamException
TcpOutboundGateway handler = new TcpOutboundGateway();
handler.setConnectionFactory(cf);
cf.setDeserializer(new DynamicSerSeri());
cf.setSerializer(new DynamicSerSeri());
IntegrationFlow flow = f -> f.handle(handler);
IntegrationFlowContext.IntegrationFlowRegistration flowRegistration =
this.flowContext.registration(flow)
.addBean(cf)
.id(hostPort + ".flow")
.register();
MessageChannel inputChannel = flowRegistration.getInputChannel();
this.subFlows.put(hostPort, inputChannel);
return inputChannel;
}
}
TcpInboundGateway get the connection from client into the inputChannel, and I use a serviceActivator to get inputChannel's payload and send to server side by a TcpOutboundGateway which has a connection factory with server side.
when the client closed the connection with spring-integration-ip-module, TcpInboundGateway can get the exception in SoftEndOfStreamException, but I don't known how to closed TcpOutboundGateway's connection to the server side.
Use an ApplicationListener bean or #EventListener method to listen for TCP Events.
When you first open an outbound connection, you will get a TcpConnectionOpenEvent. It is published on (and will be receive on) the calling thread by default. You can associate the outbound connection id with the inbound.
Listen for TcpConnectionCloseEvent from the inbound connection factory; you can then close the outbound connection using its connectionId.
outboundFactory.closeConnection(connectionId);
EDIT
Since you are using a TcpNetServerConnectionFactory, you can use a ThreadAffinityClientConnectionFactory which will automatically associate the outgoing connection with the incoming connection.
When you get the event for the incoming connection close, it will be on the same thread, so you can simply call releaseConnection() on that thread and the outgoing connection will close.
Here is an example
#SpringBootApplication
public class So55207274Application {
public static void main(String[] args) {
SpringApplication.run(So55207274Application.class, args);
}
#Bean
public IntegrationFlow flow() {
return IntegrationFlows.from(Tcp.inboundGateway(server()))
.log()
.handle(Tcp.outboundGateway(threadBoundClient()))
.get();
}
#Bean
public TcpNetServerConnectionFactory server() {
return new TcpNetServerConnectionFactory(1234);
}
#Bean
public ThreadAffinityClientConnectionFactory threadBoundClient() {
return new ThreadAffinityClientConnectionFactory(client());
}
public TcpNetClientConnectionFactory client() {
TcpNetClientConnectionFactory client = new TcpNetClientConnectionFactory("localhost", 1235);
client.setSingleUse(true);
return client;
}
#EventListener
public void listen(TcpConnectionCloseEvent event) {
if (event.getConnectionFactoryName().equals("server")) {
try {
threadBoundClient().releaseConnection();
}
catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(event);
}
// Test server
#Bean
public IntegrationFlow test() {
return IntegrationFlows.from(Tcp.inboundGateway(Tcp.netServer(1235)))
.transform(Transformers.objectToString())
.<String, String>transform(p -> p.toUpperCase())
.get();
}
}

Trouble Writing multiThread Chat program

im writing a multithread chat program where i hope to have a server connected to multiple clients, the clients can talk to each and send messages to each other. I want all messages from the clients to be visible to the server, moreover that the server can send messages to all visible clients. My program only connects the server to one client and they can send messages.
package chatserver2;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
// import all the class that you will need for functionailty
// extends jframe to develop gui's in java
public class Server2 {
private static JTextField userInput; //
private static JTextArea theChatWindow; //
private static ObjectOutputStream output; // stream data out
private static ObjectInputStream input; // stream data in
private static ServerSocket server;
private static Socket connection; // socket means set up connetion between 2 computers
private static JFrame frame;
private static int n;
//Constructor
public static void main(String[] args) throws IOException {
Server2 obj = new Server2();
// Socket sock=new Socket("localhost",6789);
System.out.println("Hello 4");
obj.RunServer();
System.out.println("Hello 3");
try {
while (true) {
System.out.println("Hello 2");
Handler obj2 = new Handler();
//Handler obj3=new Handler();
obj2.start();
System.out.println("Accepted connection from "
+ connection.getInetAddress() + " at port "
+ connection.getPort());
n++;
System.out.println("Count " + n);
}
} finally {
connection.close();
}
}
public Server2() {
frame = new JFrame();
userInput = new JTextField();
userInput.setEditable(false); // set this false so you dont send messages when noone is available to chat
// action event listener to check when the user hits enter for example
userInput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
sendMessage(event.getActionCommand()); // string entered in the textfield
userInput.setText(""); // reset text area to blank again
}
}
);
// create the chat window
frame.add(userInput, BorderLayout.NORTH);
theChatWindow = new JTextArea();
frame.add(new JScrollPane(theChatWindow));
frame.setSize(300, 150);
frame.setVisible(true);
}
// run the server after gui created
public void RunServer() {
try {
server = new ServerSocket(6789); // 1st number is port number where the application is located on the server, 2nd number is the amount of people aloud to connect
while (true) {
try {
waitForConnection(); // wait for a connection between 2 computers
setupStreams(); // set up a stream connection between 2 computers to communicate
whileChatting(); // send message to each other
// connect with someone and have a conversation
} catch (EOFException eofException) {
showMessage("\n Server ended Connection");
}
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//Wait for a connection then display connection information
private void waitForConnection() {
showMessage("waiting for someone to connect to chat room....\n");
try {
connection = server.accept();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
showMessage("Now connected to" + connection.getInetAddress().getHostName());
showMessage(" at port " + connection.getPort());
}
// stream function to send and recive data
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
// String message = "WAIT";
// sendMessage(message);
//showMessage("\n Connection streams are now setup \n");
}
// this code while run during chat conversions
private void whileChatting() throws IOException {
String message = "WAIT ";
sendMessage(message);
allowTyping(true); // allow user to type when connection
do {
// have conversion while the client does not type end
try {
message = (String) input.readObject(); // stores input object message in a string variable
showMessage("\n " + message);
System.out.println("Message from Client " + message);
} catch (ClassNotFoundException classnotfoundException) {
showMessage("\n i dont not what the user has sent");
}
} while (!message.equals("CLIENT - END"));// if user types end program stops
}
private void closeChat() {
showMessage("\n closing connections...\n");
allowTyping(true);
try {
output.close(); // close output stream
input.close(); // close input stream
connection.close(); // close the main socket connection
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// send message to the client
private void sendMessage(String message) {
try {
output.writeObject(message);
output.flush(); // send all data out
showMessage("\nServer - " + message);
System.out.println("Message to client " + message);
} catch (IOException ioexception) {
theChatWindow.append("\n ERROR: Message cant send");
}
}
// update the chat window (GUI)
private void showMessage(final String text) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
theChatWindow.append(text);
}
}
);
}
// let the user type messages in their chat window
private void allowTyping(final boolean trueOrFalse) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
userInput.setEditable(trueOrFalse);
}
}
);
}
public static class Handler extends Thread {
private Socket connection;
// static private ServerSocket server;
public Handler() {
// this.socket = socket;
String message = "WAIT";
}
//connection = server.accept();
public void run() {
System.out.println("Connect" + Server2.connection);
while (true) {
try {
waitForConnection();
setupStreams();
whileChatting();
} catch (IOException ex) {
Logger.getLogger(Server2.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private void waitForConnection() {
System.out.println("Heelo");
showMessage("waiting for someone to connect to chat room....\n");
System.out.println("server" + server);
try {
connection = server.accept();
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
System.out.println("Connection" + connection);
showMessage("Now connected to" + connection.getInetAddress().getHostName());
showMessage("AT port" + connection.getPort());
}
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
showMessage("\n Connection streams are now setup \n");
}
// this code while run during chat conversions
private void whileChatting() throws IOException {
String message = " You are now connected ";
sendMessage(message);
allowTyping(true); // allow user to type when connection
do {
// have conversion while the client does not type end
try {
message = (String) input.readObject(); // stores input object message in a string variable
showMessage("\n " + message);
} catch (ClassNotFoundException classnotfoundException) {
showMessage("\n i dont not what the user has sent");
}
} while (!message.equals("CLIENT - END"));// if user types end program stops
}
private void closeChat() {
showMessage("\n closing connections...\n");
allowTyping(true);
try {
output.close(); // close output stream
input.close(); // close input stream
connection.close(); // close the main socket connection
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// send message to the client
static private void sendMessage(String message) {
try {
output.writeObject(message);
output.flush(); // send all data out
showMessage("\nServer - " + message);
} catch (IOException ioexception) {
theChatWindow.append("\n ERROR: Message cant send");
}
}
// update the chat window (GUI)
static private void showMessage(final String text) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
theChatWindow.append(text);
}
}
);
}
// let the user type messages in their chat window
private void allowTyping(final boolean trueOrFalse) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
userInput.setEditable(trueOrFalse);
}
}
);
}
}
}
Here is the client :
package chatserver2;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// import all the class that you will need for functionailty
// extends jframe to develop gui's in java
public class Client2 extends JFrame {
private JTextField userInput; //
private JTextArea theChatWindow; //
private ObjectOutputStream output; // stream data out
private ObjectInputStream input; // stream data in
private Socket connection; // socket means set up connetion between 2 computers
//Constructor
public Client2() {
super("My Chat Service");
userInput = new JTextField();
userInput.setEditable(false); // set this false so you dont send messages when noone is available to chat
// action event listener to check when the user hits enter for example
userInput.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
sendMessage(event.getActionCommand()); // string entered in the textfield
userInput.setText(""); // reset text area to blank again
}
}
);
// create the chat window
add(userInput, BorderLayout.NORTH);
theChatWindow = new JTextArea();
add(new JScrollPane(theChatWindow));
setSize(300, 150);
setVisible(true);
}
// run the server after gui created
public void RunServer() {
try {
connection = new Socket("localhost", 6789);// 1st number is port number where the application is located on the server, 2nd number is the amount of people aloud to connect
while (true) {
try {
// wait for a connection between 2 computers
setupStreams(); // set up a stream connection between 2 computers to communicate
whileChatting(); // send message to each other
// connect with someone and have a conversation
} catch (EOFException eofException) {
showMessage("\n Server ended Connection");
} finally {
closeChat();
}
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
//Wait for a connection then display connection information
// stream function to send and recive data
private void setupStreams() throws IOException {
output = new ObjectOutputStream(connection.getOutputStream()); // set up pathway to send data out
output.flush(); // move data away from your machine
input = new ObjectInputStream(connection.getInputStream()); // set up pathway to allow data in
showMessage("\n Connection streams are now setup \n");
}
// this code while run during chat conversions
private void whileChatting() throws IOException {
String message = "";
allowTyping(true); // allow user to type when connection
do {
// have conversion while the client does not type end
try {
message = (String) input.readObject(); // stores input object message in a string variable
System.out.println("message " + message);
if (message.equals("WAIT")) {
ServerSocket server2 = new ServerSocket(5000);
System.out.println("Hello");
message = "5000";
sendMessage(message);
}
System.out.println("From server " + message);
showMessage("\n " + message);
} catch (ClassNotFoundException classnotfoundException) {
showMessage("\n i dont not what the user has sent");
}
} while (!message.equals("CLIENT - END"));// if user types end program stops
}
private void closeChat() {
showMessage("\n closing connections...\n");
allowTyping(true);
try {
output.close(); // close output stream
input.close(); // close input stream
connection.close(); // close the main socket connection
} catch (IOException ioexception) {
ioexception.printStackTrace();
}
}
// send message to the client
private void sendMessage(String message) {
try {
output.writeObject(" - " + message);
output.flush(); // send all data out
showMessage("\nServer - " + message);
} catch (IOException ioexception) {
theChatWindow.append("\n ERROR: Message cant send");
}
}
// update the chat window (GUI)
private void showMessage(final String text) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
theChatWindow.append(text);
}
}
);
}
// let the user type messages in their chat window
private void allowTyping(final boolean trueOrFalse) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
userInput.setEditable(trueOrFalse);
}
}
);
}
public static void main(String[] args) {
Client2 obj = new Client2();
obj.RunServer();
}
}

Creating a Chat client with JavaFX using sockets

I am having trouble coding the socket side of a JavaFX chat client. This is my first time having to deal with socket in any sort of way, so some trouble was expected. I've been following this page to design the server-client side:
http://pirate.shu.edu/~wachsmut/Teaching/CSAS2214/Virtual/Lectures/chat-client-server.html
My problem is getting text I enter into the GUI into a DataInputSteam and DataOutputStream so that others on the same server can see the changes. I do
not understand how to convert the text in the UI to something the sockets
can work with.
Here is part of my controller class:
#FXML
private TextArea messageArea;
#FXML
private Button sendButton;
private ChatClient client;
#FXML
public void initialize() {
client = new ChatClient(ChatServer.HOSTNAME, ChatServer.PORT);
sendButton.setOnAction(event -> {
client.handle(messageArea.getText());
});
}
The ChatClient class is a Runnable with a DataInputStream and DataOutputStream field that connects to a Socket. I haven't changed much from the link:
public class ChatClient implements Runnable {
private Socket socket;
private Thread thread;
private DataInputStream streamIn;
private DataOutputStream streamOut;
private ChatClientThread client;
public ChatClient(String serverName, int port) {
System.out.println("Establishing connection...");
try {
socket = new Socket(serverName, port);
System.out.println("Connected: " + socket);
start();
} catch (UnknownHostException e) {
System.out.println("Unknown host: " + e.getMessage());
} catch (IOException e) {
System.out.println("Unexpected: " + e.getMessage());
}
}
#Override
public void run() {
while (thread != null) {
try {
streamOut.writeUTF(streamIn.readUTF());
streamOut.flush();
} catch (IOException e) {
System.out.println("Sending error: " + e.getMessage());
stop();
}
}
}
public void handle(String msg) {
try {
streamOut.writeUTF(msg);
streamOut.flush();
} catch (IOException e) {
System.out.println("Could not handle message: " + e.getMessage());
}
System.out.println(msg);
}
public void start() throws IOException {
streamIn = new DataInputStream(socket.getInputStream());
streamOut = new DataOutputStream(socket.getOutputStream());
if (thread == null) {
client = new ChatClientThread(this, socket);
thread = new Thread(this);
thread.start();
}
}
So in the controller class, I am calling the handle method which deals with the streams. The original code just wrote to the console, so I had to change the line:
streamIn = new DataInputStream(System.in)
to
streamIn = new DataInputStream(socket.getInputStream());
There is also a ChatClientThread class that extends Thread and just calls ChatClient.handle() in its run method.
I guess my question is how to update a GUI whenever writeUTF and readUTF interact with the DataStreams. I understand that streamOut.writeUTF(msg) changes the DataOutputStream to "have" that string, but I'm not sure how I'm supposed to use that datastream to update my gui so that all clients using the application can see the update. The way I have it now, if I run two instances of the JavaFX app, they dont' communicate through the UI or the console. My program just stalls whenever I click the send button

How to initiate an update for clients by the server in java

I have a client/server app to manage a line of some sort.
all the clients add objects to my line.
I want the server to send a screen capture of the jpanel to the clients every time there is a change in the line, line inserted or removed.
I managed to capture the jpanel to a jpeg and even send it.
but the flow of my app is stopped, after the first update I get eofexception that terminates my listening server socket.
what is the correct way to update a client ? should I set a serversocket to always listen on the client side too ?
please help, im stuck with this for like 2 weeks.
This is my listening thread (Server):
public class ListeningThread implements Runnable {
static boolean listening = true;
public BufferedReader in;
public void run() {
ServerSocket echoServer = null;
String line;
DataInputStream is = null;
PrintStream os = null;
Socket clientSocket = null;
try {
echoServer = new ServerSocket(RequestReciever._communicationPort);
}
catch (IOException e) {
System.out.println(e);
}
// Create a socket object from the ServerSocket to listen and accept
// connections.
// Open input and output streams
try {
// As long as we receive data, send it to be phrased to a request.
while (true) {
clientSocket = echoServer.accept();
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());
// An option for a stop listening button. currently not available !
if( listening==true ) {
line = is.readUTF();
os.println(line);
System.out.println(line);
RequestReciever.pharseToRequest(line);
// clientSocket = null;
}
else {
echoServer.close();
is.close();
os.close();
break;
}
}
}
catch (IOException e) {
e.printStackTrace();
System.out.println("Listening Thread Unknown error");
}
}
}
This is my Pharse Method:
public static void pharseToRequest(String input) {
List<String> list = new ArrayList<String>(Arrays.asList(input.split(";;;")));
if (list.get(0).equalsIgnoreCase("Login") && list.get(1).equalsIgnoreCase ("Login") && list.get(2).equalsIgnoreCase("5"))
{
_adminClients.add(list.get(4));
updateScreenCapture();
AdminClientUpdate tmp = new AdminClientUpdate(list.get(4));
Thread aCU = new Thread (tmp);
aCU.start();
}
else
{
ServerRequest newReq = new ServerRequest(list.get(0), list.get(1), Integer.parseInt(list.get(2)),list.get(3),list.get(4));
addRequest(newReq);
}
}
and This is the AdminClientUpdate Class
public class AdminClientUpdate implements Runnable {
static boolean listening = true;
public BufferedReader in;
public String _ip;
public AdminClientUpdate(String ip)
{
_ip = ip;
}
public void run() {
try {
Socket socket = new Socket(_ip, RequestReciever._communicationPort);
InputStream in = new FileInputStream("Capture/tmp.jpg");
java.io.OutputStream out = socket.getOutputStream();
copy(in, out);
System.out.println("Sent Image !");
socket.close();
out.close();
in.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
System.out.println("Cant find tmp.jpg");
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static void copy(InputStream in, java.io.OutputStream out) throws IOException {
byte[] buf = new byte[8192];
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
}
eliminate this
echoServer.close();
this line closes the socket. due which the connection is aborted.
After a few brain meltdowns , I have decided that putting a server socket on the client side to listen for updates from the server is the best way.
I fixed a few things :
* The server should start a new thread to handle every accepted connection, instead of processing each one in-line in the accept thread.
* I tried to get the first update via the server socket instead of the login initialization.
now, after getting the 1st update while logging in, I added a Server Socket on the client side so it will keep listening for further updates from server.

JavaFX network background task with javafx.concurrent

I'm implementing an JavaFX application which is communicating with a mobile phone via wifi (android).
Therefore I have a server thread on the JavaFX running in a background process:
public class NetworkService implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
private RoutePlannerJFX application;
private UserData userData;
public NetworkService(ExecutorService pool,
ServerSocket serverSocket,
RoutePlannerJFX app,
UserData data) {
this.serverSocket = serverSocket;
this.pool = pool;
application = app;
userData = data;
}
public void run() {
try {
while ( true ) {
Socket cs = serverSocket.accept();
pool.execute(new Handler(serverSocket, cs, application, userData));
}
} catch (IOException ex) {
System.out.println("--- Interrupt NetworkService-run");
}
finally {
System.out.println("--- Ende NetworkService(pool.shutdown)");
pool.shutdown(); //keine Annahme von neuen Anforderungen
try {
pool.awaitTermination(4L, TimeUnit.SECONDS);
if ( !serverSocket.isClosed() ) {
System.out.println("--- Ende NetworkService:ServerSocket close");
serverSocket.close();
}
} catch ( IOException e ) { }
catch ( InterruptedException ei ) { }
}
}
}
which has a handler:
public class Handler implements Runnable {
private final Socket client;
private final ServerSocket serverSocket;
private RoutePlannerJFX application;
private UserData userData;
Handler(ServerSocket serverSocket,Socket client, RoutePlannerJFX app, UserData data) {
this.client = client;
this.serverSocket = serverSocket;
application = app;
userData = data;
}
public void run() {
StringBuffer sb = new StringBuffer();
PrintWriter out = null;
try {
System.out.println( "running service, " + Thread.currentThread() );
out = new PrintWriter( client.getOutputStream(), true );
BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(
client.getInputStream()));
char[] buffer = new char[100];
int anzahlZeichen = bufferedReader.read(buffer, 0, 100);
String nachricht = new String(buffer, 0, anzahlZeichen);
String[] werte = nachricht.split("\\s");
System.out.println(nachricht+"\n");
POI poi = new POI(nachricht);
userData.addItemToPoiList(poi);
application.setScene("INSTRUCT");
} catch (IOException e) {System.out.println("IOException, Handler-run");}
finally {
System.out.println(sb); //Rückgabe Ergebnis an den Client
if ( !client.isClosed() ) {
System.out.println("****** Handler:Client close");
try {
client.close();
} catch ( IOException e ) { }
}
}
}
}
The application has a public method to change the scene (setScene()).
That's the way I wish I could do it, but now I know, that I cannot switch the scene in my backgroundprocess.
Has anyone an idea how to implement this problem? I need to fire an action, when my backgroundprocess receives a message from the the client, but I don't know what's the best way to do that… I already found javafx.concurrent, but which do I have to use and how?
Thank's in advance!
For the client side you can use either a Task or a Service to run in a separate thread & update the GUI as described in the documentation
You can check this post too JavaFX Async Task

Resources