How to IR remote control to IPTV with javaFx application? - java

I am trying to develop a JavaFx application for testing an IPTV. And my task is checking of channel changing successfully. There is no any component or device at the moment. But I am searching for this task, after that I will buy.
My application will send some remote control command over the IR device.
Here is an IR device, but It doesn't have a Java API.
Is there a way for this solution?

I searched and found a device which name was RedRat. It is usb-infrared device that we can use it linux and windows OS.
There is a utility for using it with a programming language.
Here is a sample java code, may be useful for somebody. But you should have a redrat device.
First step, you have to download this redRatHub and paste a direction
secondly, run main class which has same path with redrathub folders.
public class MyDemo {
private static Client client;
private static String DEVICE_NAME = "";
private static String DATA_SET = "";
public static void main(String[] args) {
try {
startRedRat();
client = new Client();
client.openSocket("localhost", 40000);
DEVICE_NAME = client.readData("hubquery=\"list redrats\"").split("]")[1].split("\n")[0].trim();
DATA_SET = client.readData("hubquery=\"list datasets\"").split("\n")[1];
sendCommand("power");
TimeUnit.SECONDS.sleep(5);
sendCommand("btn1", "btn1", "btn1", "btn1");
sendCommand("btnOK");
TimeUnit.SECONDS.sleep(30);
sendCommand("btnBACK");
sendCommand("channel+");
sendCommand("btn6", "btn1");
sendCommand("channel+");
sendCommand("channel-");
sendCommand("volume+");
sendCommand("volume-");
sendCommand("power");
client.closeSocket();
p.destroy();
} catch (Exception ex) {
System.err.println(ex.getMessage());
} finally {
System.out.println("Finished. Hit <RETURN> to exit...");
}
}
private static void sendCommand(String... command) {
try {
for (String cmd : command) {
client.sendMessage("name=\"" + DEVICE_NAME + "\" dataset=\"" + DATA_SET + "\" signal=\"" + cmd + "\"");
TimeUnit.MILLISECONDS.sleep(500);
System.out.println(cmd + " signal send");
}
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void startRedRat() {
try {
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
p = Runtime.getRuntime().exec("cmd /C C:\\RedRatHub\\RedRatHubCmd.exe C:\\RedRatHub\\TivibuDB.xml");
return null;
}
};
worker.run();
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
}
}
this class is communicate with redrat device over the serial ports.
public class Client {
private Socket socket;
private DataOutputStream out;
private DataInputStream in;
/*
* Opens the socket to RedRatHubCmd.
*/
public void openSocket(String host, int port) throws UnknownHostException, IOException {
if (socket != null && socket.isConnected()) return;
socket = new Socket(host, port);
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
}
/*
* Closes the RedRatHubCmd socket.
*/
public void closeSocket() throws IOException {
socket.close();
}
/*
* Sends a message to the readData() method. Use when returned data from RedRatHub is not needed.
*/
public void sendMessage(String message) throws Exception {
String res = readData(message);
if (!res.trim().equals("OK")) {
throw new Exception("Error sending message: " + res);
}
}
/*
* Reads data back from RedRatHub. Use when returned data is needed to be output.
*/
public String readData(String message) throws IOException {
if (socket == null || !socket.isConnected()) {
System.out.println("\tSocket has not been opened. Call 'openSocket()' first.");
return null;
}
// Send message
out.write((message + "\n").getBytes("UTF-8"));
// Check response. This is either a single line, e.g. "OK\n", or a multi-line response with
// '{' and '}' start/end delimiters.
String received = "";
byte[] inBuf = new byte[256];
while (true) {
// Read data...
int inLength = in.read(inBuf);
//byte[] thisMSg = new byte[inLength];
String msg = new String(Arrays.copyOfRange(inBuf, 0, inLength), "UTF-8");
received += msg;
if (checkEom(received)) return received;
}
}
/*
* Checks for the end of a message
*/
public boolean checkEom(String message) {
// Multi-line message
if (message.trim().endsWith("}")) {
return message.startsWith("{");
}
// Single line message
return message.endsWith("\n");
//return true;
}
}

Related

Java can't get a continuous reading/writing to a socket

I'm studying electronic engineering but for my internship I've been asked to make a program that must communicate via a socket to a certain ip and port. The program has a main class which is the GUI and I made another class for the connection which runs parallel using a Thread. The problem is that when I click the "Connect" button that I have on my GUI, it only receives or sends once the data, despite having a while loop. To further receive and send data I must spam-click my connect and disconnect button.
public class ConnectionSocket implements Runnable {
private final int port;
private final String ipAddr;
private final Observer observador;
private DataInputStream in;
private DataOutputStream out;
private Socket sc = null;
private boolean inputAvailable = false;
public boolean lastInput = false;
private String nextOutputMessage;
private boolean disconnect=false;
private Observable observable;
public ConnectionSocket(String ip, int p , Observer panel) {
this.ipAddr = ip;
this.port = p;
this.observador = panel;
}
#Override
public void run() {
this.observable = new Observable();
observable.addPropertyChangeListener(observador);
this.observable.notifyData("Message Connected");
System.out.print("\n**********************\nConectado\n**********************\n");
while (!disconnect) {
try {
try {
sc = new Socket(this.ipAddr , this.port);
}
catch (IOException e) {
System.out.println("Socket TimeOut");
}
if(sc != null) {
out = new DataOutputStream(sc.getOutputStream());
in = new DataInputStream(sc.getInputStream());
}
while(!disconnect){
if (sc != null) {
try {
if(in.available() != 0) {
receiveData();
}
else {
inputAvailable = false;
}
}
catch(IOException ex) {
System.out.println("***Read or write error***");
System.out.println(ex.toString());
}
}
}
if ( sc != null ) {
try { sc.close(); }
catch ( IOException e ) {}
}
} catch (IOException ex) {
Logger.getLogger(ConnectionSocket.class.getName()).log(Level.SEVERE, null, ex);
}
}
//Close the socket
cutConnection();
System.out.print("\n**********************\nDesconectado\n**********************\n");
}
public void sendNewData(String msg) throws IOException { //this method receives data from the GUI//
nextOutputMessage = msg;
sendData();
}
private synchronized void sendData() throws IOException {
System.out.println("Panel: " + nextOutputMessage);
out.writeByte((byte) Integer.parseInt(nextOutputMessage));
}
private synchronized void receiveData() throws IOException {
if(!inputAvailable)System.out.print("CUBE: ");
inputAvailable = true;
while(in.available() != 0) {
byte dat = (byte) in.read();
this.observable.notifyData(Character.toString((char) dat));
System.out.print((char) dat);
}
}
public void cutConnection() {
try {
disconnect = true;
if(this.in != null) {
this.in.close();
}
if(this.out != null) {
this.out.close();
}
if(this.sc != null) {
this.sc.close();
}
} catch (IOException ex) {
this.sc = null;
}
}
}
I use two additional classes which use PropertyChangeListener to send the data received to the GUI, otherwise it just blocks it.
I receive and send data as ASCII code.
This is the method in the GUI class which starts the thread (the connection)
private void connect(String ip, int port) {
jButton_connect.setText("Desconectar");
labelMessage("Conectando...");
observerPanel = new Observer(this);
connection = new ConnectionSocket(ip , port, observerPanel);
Thread t = new Thread(connection);
t.start();
}
So basically I would appreciate any hint about what I'm doing wrong, because I can't really find any solution suitable for my needs. BTW any solution that includes getting rid of the double while loop would be great, as it consumes a lot of cpu in that point. Feel free to criticise any stupid thing I made because I had to learn java from zero to do this so it's probably not really good.
Thanks in advance
Edit 1: Does the sc = new Socket(this.ipAddr , this.port); sentence need to be called in the loop or once it's called it permanently bounds to that ip and port? I only need to connect to a specific ip and port. Thanks

Java - Multithread Server to serve multiple concurrent clients

I've been trying to make the code below to have multiple clients communicate with the same server.
Currently, it works one client at a time with the server but it seems to be that when the second client opens, code stops at new ObjectInputStream(connection.getInputStream()); in the Class 3 (client) - see below.
I've tried making the inputstream object transient to be shared in different threads but it didn't work, nor with making runClient method synchronized.
If I were to implement Serializable in the client class using serialVersionUID, how can I make multithreading work with the same server or is there any better way..?
Class 1 - server main
public class EchoServer {
private ServerSocket server;
private int portNum;
public static final int DEFAULT_PORT = 8081;
public EchoServer(int portNum) {
this.portNum = portNum;
}
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length > 0) {
(new EchoServer(Integer.parseInt(args[0]))).runServer();
} else {
(new EchoServer(DEFAULT_PORT)).runServer();
}
}
}
Class 2
public class ClientHandler implements Runnable {
private ObjectOutputStream output;
private ObjectInputStream input;
private String message;
/** Integer to hold the message number. */
private int messagenum;
private Socket connection;
public ClientHandler(Socket connection) {
this.connection = connection;
}
#Override
public void run() {
do{
handleRequest();
} while (true);
}
public void handleRequest() {
try {
output = new ObjectOutputStream(this.connection.getOutputStream());
input = new ObjectInputStream(this.connection.getInputStream());
do {
try {
message = (String) input.readObject();
System.out.println(messagenum +" Output> " +message);
} catch (EOFException | SocketException e) {
message = null;
}
if (message != null) {
output.writeObject(messagenum +" FromServer> " +message);
output.flush();
++messagenum;
}
} while (message != null);
input.close();
output.close();
this.connection.close();
} catch (IOException | ClassNotFoundException ex) {
System.err.println("Error encountered! Exiting program...");
ex.printStackTrace();
}
}
}
Class 3 - client main
public class EchoClient implements Serializable {
private static final long serialVersionUID = 1L;
private Socket connection;
private ObjectOutputStream output;
private transient ObjectInputStream input;
private String message = "";
private static String serverName;
public static final String DEFAULT_SERVER_NAME = "localhost";
private static int portNum;
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
public EchoClient(String serverName, int portNum) {
this.serverName = serverName;
this.portNum = portNum;
}
public synchronized void runClient() {
try {
connection = new Socket(InetAddress.getByName(serverName), portNum);
output = new ObjectOutputStream(connection.getOutputStream());
input = new ObjectInputStream(connection.getInputStream());
do {
System.out.print("Input> ");
message = keyboard.readLine();
if (message != null){
output.writeObject(message);
output.flush();
message = (String) input.readObject();
System.out.println(message);
}
} while (message != null);
input.close();
output.close();
connection.close();
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (ClassNotFoundException exception) {
exception.printStackTrace();
}
}
public static void main(String[] args) {
switch (args.length) {
case 2:
(new EchoClient(args[0], Integer.parseInt(args[1]))).runClient();
break;
case 1:
(new EchoClient(DEFAULT_SERVER_NAME, Integer.parseInt(args[0]))).runClient();
break;
default:
(new EchoClient(DEFAULT_SERVER_NAME, server.EchoServer.DEFAULT_PORT)).runClient();
}
}
}
Call server.accept() in the loop to accept multiple client connections as mentioned in the other answers. Start a new thread with the Thread.start method instead of Thread.run- What's the difference between Thread start() and Runnable run().
volatile boolean isRunning = true;
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
while(isRunning) {
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).start();
}
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
run server needs to wait for connections in a loop otherwise it will connect once and that is it. It needs to close its connections too. Clean up its threads. that's just in server main. I'm pretty sure this is a duplicate. So keep on researching
As said by efekctive, you need your server.accept() in a loop, else it will accept the first client and exit the program. So put these two lines in runServer() in a loop like this:
boolean isRunning = true;
while(isRunning){
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
}

Handling multi Java TCP clients with Threads

I have been working with TCP server/client stuff for a while. I am actully good at UDP programming when it comes to connecting more than one user that is multiple clients. I tried to do the same on a TCP server that i made using Threads but whenever the Thread gets to this piece of code
String reader = (String)in.readObject();
an error is generated and the thread stops executing the code but the thread still runs the program keeping it alive.
Anyway here is the entire source code :
public class TestServer implements Runnable {
private Thread run, streams, connect, receive, send;
private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;
private boolean running, incomingMessage = false;
private int port;
public TestServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);
run = new Thread(this, "Run");
run.start();
}
public void run() {
running = true;
connect();
receive();
}
private void connect() {
connect = new Thread("Connect") {
public void run() {
while(running) {
try {
conn = socket.accept();
} catch (IOException e) {
e.printStackTrace();
}
console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());
try {
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}; connect.start();
}
private void setupStreams() throws IOException {
streams = new Thread("Streams") {
public void run() {
try {
console("Setting up Streams");
out = new ObjectOutputStream(conn.getOutputStream());
out.flush();
in = new ObjectInputStream(conn.getInputStream());
console("Streams are now setup");
incomingMessage = true;
receive.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}; streams.start();
}
private void receive() {
receive = new Thread("Receive") {
public void run() {
while(incomingMessage) {
String message = "";
try {
message = (String) in.readObject();
//This is the only flaw the program
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
console("Client : " + message);
}
}
};
}
private void console(String message) {
System.out.println(message);
}
public static void main(String[] args) {
try {
new TestServer(1234);
} catch (IOException e) {
e.printStackTrace();
}
}
}
FYI am not new to this. The error is caused because the server starts receiving packets even when there are no packets to be received. But because the thread forces it to receive it, i generates the error in the thread and dont know any other way to counter this. So please help. Thanks in Advance.
You shouldn't need 2 threads per connection. One thread is all that's required. After the connection is accepted, pass it to a worker thread to start reading. This can be done in a while loop in the worker thread.
Even though the socket's input stream can be read, the ObjectInputStream() class is more sensitive. If there is any error, its state is corrupted and it can't be used.
while (true) {
try {
Object input = in.readObject();
message = (String) input;
} catch (IOException e) {
e.printStackTrace();
break; //unrecoverable
} catch (ClassNotFoundException e) {
e.printStackTrace();
break; //unrecoverable
}
console("Client : " + message);
}
It's a better design to use a specific message protocol instead of sending serialized Java objects. For example if you are sending Strings like your sample, an InputStreamReader can be used to convert bytes to characters more easily and with less error handling.
These resources would be helpful to you:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
Java - Listening to a socket with ObjectInputStream
ObjectInputStream(socket.getInputStream()); does not work

Why is it my code cannot run many clients in java multithreading?

Why is this code nott accumulating many clients?
I'm new to java.
It only runs for only 1 client.
Can anyone explain why it doesn't support multiple clients for socket programming?
import java.net.*;
import java.io.*;
/**
* Demo Server: Contains a multi-threaded socket server sample code.
*/
public class ServerDemo extends Thread
{
final static int _portNumber = 5559; //Arbitrary port number
public static void main(String[] args)
{
try {
new ServerDemo().startServer();
} catch (Exception e) {
System.out.println("I/O failure: " + e.getMessage());
e.printStackTrace();
}
}
public void startServer() throws Exception {
ServerSocket serverSocket = null;
boolean listening = true;
try {
serverSocket = new ServerSocket(_portNumber);
} catch (IOException e) {
System.err.println("Could not listen on port: " + _portNumber);
System.exit(-1);
}
while (listening) {
handleClientRequest(serverSocket);
}
serverSocket.close();
}
private void handleClientRequest(ServerSocket serverSocket) {
try {
new ConnectionRequestHandler(serverSocket.accept()).run();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Handles client connection requests.
*/
public class ConnectionRequestHandler implements Runnable{
private Socket _socket = null;
private PrintWriter _out = null;
private BufferedReader _in = null;
public ConnectionRequestHandler(Socket socket) {
_socket = socket;
}
public void run() {
System.out.println("Client connected to socket: " + _socket.toString());
try {
_out = new PrintWriter(_socket.getOutputStream(), true);
_in = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
String inputLine, outputLine;
BusinessLogic businessLogic = new BusinessLogic();
outputLine = businessLogic.processInput(null);
_out.println(outputLine);
//Read from socket and write back the response to client.
while ((inputLine = _in.readLine()) != null) {
outputLine = businessLogic.processInput(inputLine);
if(outputLine != null) {
_out.println(outputLine);
if (outputLine.equals("exit")) {
System.out.println("Server is closing socket for client:" + _socket.getLocalSocketAddress());
break;
}
} else {
System.out.println("OutputLine is null!!!");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally { //In case anything goes wrong we need to close our I/O streams and sockets.
try {
_out.close();
_in.close();
_socket.close();
} catch(Exception e) {
System.out.println("Couldn't close I/O streams");
}
}
}
}
/**
* Handles business logic of application.
*/
public static class BusinessLogic {
private static final int LoginUserName = 0;
private static final int LoginPassword = 1;
private static final int AuthenticateUser = 2;
private static final int AuthSuccess = 3;
private int state = LoginUserName;
private String userName = null;
private String userPassword = null;
public String processInput(String clientRequest) {
String reply = null;
try {
if(clientRequest != null && clientRequest.equalsIgnoreCase("login")) {
state = LoginPassword;
}if(clientRequest != null && clientRequest.equalsIgnoreCase("exit")) {
return "exit";
}
if(state == LoginUserName) {
reply = "Please Enter your user name: ";
state = LoginPassword;
} else if(state == LoginPassword) {
userName = clientRequest;
reply = "Please Enter your password: ";
state = AuthenticateUser;
} else if(state == AuthenticateUser) {
userPassword = clientRequest;
if(userName.equalsIgnoreCase("John") && userPassword.equals("doe")) {
reply = "Login Successful...";
state = AuthSuccess;
} else {
reply = "Invalid Credentials!!! Please try again. Enter you user name: ";
state = LoginPassword;
}
} else {
reply = "Invalid Request!!!";
}
} catch(Exception e) {
System.out.println("input process falied: " + e.getMessage());
return "exit";
}
return reply;
}
}
}
You are not starting the thread in your code.
instead of
new ConnectionRequestHandler(serverSocket.accept()).run();
call
new Thread(new ConnectionRequestHandler(serverSocket.accept())).start();
method run() of your Runnable class will be invoked when you start your thread, you should not call this run() method directly.
Instead of that you should make a thread instance via
Thread myThread = new Thread(aRunnableInstance);
and start it:
myThread.start();
You're not starting a new thread, but simply running the RequestHandler code in the main thread.
Look up the difference between Thread.start() and Runnable.run(). This question might help.
Edit:
You're just missing the part where you would tell the JVM to create a new Thread to execute your Runnable code. Without a call to Thread.start() your current (and only) thread would be busy handling one request at a time. You want one Thread per request, basically. There are more advanced ways of doing this (thread pools and whatnot), but this should get you started.
private void handleClientRequest(ServerSocket serverSocket) {
try {
new Thread(ConnectionRequestHandler(serverSocket.accept())).start();
} catch (IOException e) {
e.printStackTrace();
}
}

Java the best way of waiting & getting data from your client

I started learning networking with the main networking package in JDK, it's pretty simple and easy after a few examples. But now I am interested into making multi-client applications like a chat system.
My structure idea so far is like this:
Connection handler class, which handles incoming connections, and holds the list of clients.
If new connection was found, create a new client object, start it's thread (Client object will implement runnable, so it will start it's own looping service, it will loop for new packets received), and add it to the list.
I create a new thread for each client instead of looping through all clients because the reading from client process stops the whole execution and will wait for the client to send data, which is kinda annoys me and this is my issue there.
I have created a simple console app that receives messages from the client, but now I want to detect disconnections. I read that bufferedReader .read() method returns -1 if user is not connected, so I thought I could loop and do that every number of seconds to every client, but the thing is, the client must send a packet in order to .read() it, so let's say if you do .read() it will wait & stop the whole thread until packet is received, (I think).
This is my current code which gets messages from client:
public boolean isConnected() {
try {
this.in.read();
this.lastCheck = System.currentTimeMillis();
return true;
} catch (IOException e) {
if (!inConnection()) {
System.out.println("User disconnected");
try {
this.destruct();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
return false;
}
private boolean inConnection() {
return System.currentTimeMillis() - lastCheck < this.maxTime;
}
public void startClientService() throws IOException {
while(!this.session.isClosed()) {
if (System.currentTimeMillis() - this.checkTime > 600) {
System.out.println(System.currentTimeMillis() - this.checkTime);
if (this.isConnected()) {
int packetType = this.dataIn.readInt();
packets.getPacket(packetType);
}
}
}
}
public void destruct() throws IOException {
this.session.close();
this.connection.removeClient(this);
System.out.println("Session killed");
}
Basically what happens here, I am sending a integer packed from the client, I might have many things to do so therefore I can set many unique packet ID's, so if I want to receive and process a chat message, the packet id is 216, the client sends a int 216, server reads the packet, enters the switch loop of all packet ids and detects if its really 216, if yes it gets the instance of the packed class that handles messages & gets the bytes of the received message like this:
public class Chat implements Packet {
#Override
public void processPacket(Session c) {
String message = readMessage(c);
System.out.println("Message: " + message);
}
private String readMessage(Session c) {
byte[] data = c.readBytes();
String message = null;
try {
message = new String(data, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return message;
}
}
And this is how I read bytes:
public byte[] readBytes() {
int len;
byte[] data = null;
try {
len = this.dataIn.readInt();
data = new byte[len];
if (len > 0) {
this.dataIn.readFully(data);
}
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
Okay my problem:
after adding the is disconnected detection, when I send my message, nothing happens. This is probably due to the .read() it stops and is waiting for a response. BUT if I write a message again, I will get the message in server.
This is my temporary, ugly client:
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 43594);
Scanner r = new Scanner(System.in);
PrintWriter out = new PrintWriter(socket.getOutputStream());
String input;
while(true) {
input = r.next();
if (input != null) {
sendMessage(input, out);
}
}
}
public static void sendMessage(String message, PrintWriter out) {
byte[] encoded = encode(message);
out.write(0);
out.println(encoded + "\n");
out.flush();
}
public static byte[] encode(String s) {
return DatatypeConverter.parseBase64Binary(s);
}
public static String decode(byte[] s) {
return DatatypeConverter.printBase64Binary(s);
}
}
My question is: What is a better way of reading data from client without making the application wait for it and actually loop everytime? OR maybe should I have a new thread for checking if user is online so it's 2 threads per 1 client?
If someone needs my session object (client object):
public class Session extends Thread implements Runnable {
private Socket session;
private Client client;
private PrintWriter out;
private BufferedReader in;
private PacketHandler packets;
private DataInputStream dataIn;
private ConnectionHandler connection;
private final int checkTime = 1600;
private final int maxTime = 22000;
private long lastCheck;
public Session(Socket session) {
this.session = session;
this.client = new Client(this);
try {
this.setStream();
} catch (IOException e) {
e.printStackTrace();
}
this.packets = new PacketHandler(this);
System.out.println("[New session created]: " + session.getRemoteSocketAddress());
}
public void setConnectionHandler(ConnectionHandler c) {
this.connection = c;
}
public void run() {
try {
this.startClientService();
} catch (IOException e) {
e.printStackTrace();
}
}
public void setStream() throws IOException {
this.out = new PrintWriter(this.session.getOutputStream());
this.in = new BufferedReader(new InputStreamReader(this.session.getInputStream()));
this.dataIn = new DataInputStream(this.session.getInputStream());
}
public Client getClient() {
return this.client;
}
public byte[] readBytes() {
int len;
byte[] data = null;
try {
len = this.dataIn.readInt();
data = new byte[len];
if (len > 0) {
this.dataIn.readFully(data);
}
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
public String readMessage() {
try {
return this.in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public boolean isConnected() {
try {
this.in.read();
this.lastCheck = System.currentTimeMillis();
return true;
} catch (IOException e) {
if (!inConnection()) {
System.out.println("User disconnected");
try {
this.destruct();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
return false;
}
private boolean inConnection() {
return System.currentTimeMillis() - lastCheck < this.maxTime;
}
public void startClientService() throws IOException {
while(!this.session.isClosed()) {
if (System.currentTimeMillis() - this.checkTime > 600) {
System.out.println(System.currentTimeMillis() - this.checkTime);
if (this.isConnected()) {
int packetType = this.dataIn.readInt();
packets.getPacket(packetType);
}
}
}
}
public void destruct() throws IOException {
this.session.close();
this.connection.removeClient(this);
System.out.println("Session killed");
}
}
Thanks!
While I don't have time to look over all the code, here are two things that could help you out.
1) Use a defined message header. Define X number of bytes of each message that the client will send to the server. Use these bytes to define how long the message will be, and what type of message it is. The server knows the length and layout of this header, and uses it to process the message in a particular way. Example could be a header of one byte. A value of 1 could be a I'm connected message. 2 could be I'm about to disconnect. 3 could be I'm currently away, and 4 could be an incoming chat message.
2) There are 2 ways you can handle the input. First is to use blocking IO, and create a separate thread to receive messages from each client. I believe this is what you are currently doing. The second is to use non-blocking IO, and have a separate thread iterate over the open sockets and do a read. Non-blocking will check if there is data to read, but if there is not, the thread will continue executing.

Categories