Im running Netty and i need to read some messages from the client.
Then i need to execute some actions in the Server, then send a response to the client.
Maybe the Client need to answer again to the server.
I think all this have to happend in the same Thread.
How can i do this in the Netty server?
Im testing the code below using Telnet but i cant get a response from the server.
If i Comment the first block, (Read message block), so i start to receive the response in the Telnet console.
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) { // (2)
// Read the message sent from client.
try{
ByteBuf in = (ByteBuf) msg;
try {
while (in.isReadable()) { // (1)
System.out.print((char) in.readByte());
System.out.flush();
}
}
catch(Exception e){
System.out.println("---------------- Reading Exception ----------------");
e.printStackTrace();
}finally{
//ReferenceCountUtil.release(msg);
}
// treat the received message
if(msg.equals("teste")){
// do Something...
}
//Answer to the client
try {
ctx.write(msg); // (1)
ctx.flush(); // (2)
}
catch(Exception e){
System.out.println("---------------- Writing Exception ----------------");
e.printStackTrace();
}
}
finally {
//ReferenceCountUtil.release(msg); // (2)
}
}
after the while loop: while (in.isReadable()) {...}, the msg ByteBuf is not readable anymore, so nothing will be written to the client via ctx.write(msg)
Related
I have to implement (in the server side) the quit command which disconnects any clients still connected and closes the server.
Here the server code.
public class Server {
public static void main (String args []) {
if (args.length < 1) {
System.err.println("Usage: java Server <port>");
return;
}
int port = Integer.parseInt(args[0]);
try {
ServerSocket listener = new ServerSocket(port);
Files input = new Files();
while (true) {
System.out.println("Listening...");
Socket s = listener.accept();
System.out.println("Connected");
Thread clientHandlerThread = new Thread(new ClientHandler(s,input));
clientHandlerThread.start();
}
} catch (IOException e) {
System.err.println("Error during I/O operation:");
e.printStackTrace();
}
}
}
how can the server accept command line instructions while it is running?
First of all, you have to keep track of all the clients that you create by putting their instances in a list so that when you're going to shutdown everything, you could access them and tell them to finish their job.
And about how to tell the thread instances to do that, you should call their interrup() method to inform them that they should finish/stop whatever it's doing. Calling the interrupt() method on a thread leads an InterruptedException in the thread that you should handle and gracefully finish whatever you're doing.
For example if you have something like this in the run method of your ClientHandler:
while (true) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.out.println(
"We've been asked to finish up the communication. Bye! ;)");
}
// do your business
}
This was of course a very simplified scenario to demonstrate the overall approach. You should be able to find tons of tutorials online about how to use the interrupt.
We're using hornetQ, and got a separate java application which connects to the queue to read from it.
We're having a Connection to it, creating a JMS session from the connection,
then obtaining a JMS MessageConsumer from the session, then assigning a custom MessageListener to the MessageConsumer.
We call message.acknowledge() for every processed message.
This all works very well, but in the case where we kill our java-application in the middle of processing, before hitting acknowledge(), the message is removed from hornetQ, yet never processed, and lost forever.
It seems that our current java application JMS setup somehow works by removing from the queue, and then rolling back/re-inserting it, if something goes wrong.
But if we kill our application, there won't be any roll-back or re-inserting, as it happens within our client/java-code.
Is there a setting or delivery-mode or something I can configure in the client, that causes the HornetQ to treat every message as "not consumed"(and still in the queue) untill the client sends the ack, so that a rollback arent neccecary?
EDIT: Also tried using transactional mode, calling:
connection.createSession(true, acknowledgementType)
Our MessageListener:
#Override
public void onMessage(Message message) {
LOGGER.debug("Message received. Going to handle message.");
try {
final TextMessage messageReceived = (TextMessage) message;
final String text = messageReceived.getText();
LOGGER.debug(String.format("Message content:\n%s", text));
final boolean isMessageSent = eventDispatcher.handleEvent(text);
if (isMessageSent) {
LOGGER.error("Behold!");
message.acknowledge();
session.commit();
} else {
session.rollback();
}
} catch (JMSException jmse) {
LOGGER.error("Failed to get text from a message from the events queue.", jmse);
} catch (JAXBException jaxbe) {
LOGGER.error("Failed to deserialize contents of the message from the events queue.", jaxbe);
} catch (Exception ex) {
LOGGER.error("An error occurred when receiving an event from the events queue:", ex);
}
We're doing a socket programming project for our Uni. We are developing a file sync software, and we're currently stuck with sending and receiving messages sent over socket.
So, when testing on local machine, code works perfectly. But, when we simulate the server-client environment over LAN and WiFi we get null pointer exception. The files are being sent in chunks so only 5-10 of them pass through.
I guess there is some issue regarding the total time needed for sending messages over socket, and that this is the reason why we get the exception.
Method for sending messages sends the message and starts the timer thread. If no answer is received from the server within 2 seconds, the message will be sent again. Here is the code for sending messages:
public static void sendMessage(final byte[] message) {
try {
final Thread timer = new Thread() {
#Override
public void run() {
try {
System.out.println("timer started");
sleep(1500);
System.out.println("timer timeout");
sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread() {
#Override
public void run() {
try {
byte[] buffer = new byte[1250];
serverByteStream.read(buffer);
timer.stop();
} catch (Exception e) {
}
}
};
timer.start();
serverByteStream.write(message);
thread.start();
} catch (Exception e) {
}
}
When you recursively call sendMessage() again, you should kill the thread thread also.
Please post the full stacktrace and code where the error occurs also.
hey I am trying to make a console application that can receive and send messages to the clients.
It will accept multiple clients & handle them.
To add a new client i do this in the run method:
#Override
public void run() {
try {
this.server = new ServerSocket(this.port);
this.factory = new ServerFactory(this.server);
System.out.println("Server runs and now waiting for clients");
this.runClientHandler();
Socket client;
while ((client = this.server.accept()) != null) {
this.handler.addClient(this.factory.createClient(client));
System.out.println("done");
}
} catch (IOException e) {
e.printStackTrace();
}
}
But "done" will never be printed because of this client's infinite loop for his message:
public void handleClient() throws IOException {
byte[] buffer = new byte[5*1024];
int read = -1;
byte[] data;
String message;
while ((read = this.socket.getInputStream().read(buffer)) > -1) {
data = new byte[read];
System.arraycopy(buffer, 0, data, 0, read);
message = new String(data, "UTF-8");
System.out.println("Client message: " + message);
}
}
handleClient() method will run in Thread-2 at handleClients.add():
public void addClient(Client c) throws IOException {
c.writeMessageStream("hey");
System.out.println("New client!");
this.clients.add(c);
//prints here
c.handleClient();
//never reaches this..
}
How can I ignore the while loop and let the program execute while the while loop runs without making a new thread for each client?
Check NIO Selectors. They are part of Java NIO in JDK. Or you can use an out-of-the-box solutions like Netty or (worse) Apache MINA.
Your code won't be able to handle multiple clients as it is serving the client from the same thread it is accepting connections. Generally, the client connections should be handled by different threads and you may like to use asynchronous IO so that multiple connections can be handled from a single thread. You should use Netty which simplified all these. Here are some example programs http://netty.io/5.0/xref/io/netty/example/telnet/package-summary.html
The Application
I'm writing a client/server application in Java, that communicates by sending objects over sockets using the ObjectStream classes. Each node in the application looks approximately like this:
class Node {
SocketServer server;
Socket[] clients;
}
Here the server variable is the socket on which this node listens, and the client variables are the sockets on which other nodes listen, and to which this node sends objects.
The code that I use to write objects to one of the client sockets looks like this:
void sendMessage(Message<B, F> msg) throws IOException {
ObjectOutputStream writer = getWriter();
writer.writeObject(msg);
writer.flush();
}
private ObjectOutputStream writer;
ObjectOutputStream getWriter() throws IOException {
if (writer == null)
writer = new ObjectOutputStream(
new BufferedOutputStream(client.getOutputStream()));
return writer;
}
And the code that I use to handle connections and read objects from the node's server socket looks like this:
// the handler will listen for connections
final Thread handler = new Thread(new Runnable() {
public void run() {
try {
// create a new thread to handle the client
final Socket client = server.accept();
final Thread thread = new Thread(new Runnable() {
public void run() {
final ObjectInputStream reader;
try {
reader = new ObjectInputStream(client.getInputStream());
while (true) {
try {
val msg = reader.readObject();
messages.add((Message<B, F>) msg);
}
catch (EOFException e) {
// i noted it seemed to throw eofexceptions
}
catch (IOException e) {
// do something
}
}
}
catch (IOException e) {
// do something
}
}
});
thread.start();
} catch (IOException e) {
// do something
}
}
});
handler.start();
The Problem
I think I'm doing something wrong with the sockets here. Everything works fine when every server is only connected to a single client. However, when multiple clients are talking to the same server things go bad, and I get StreamCorruptedException's from the ObjectInputStream and other strange behaviour (putting in an instance of an UpdateRequest message, and getting out an instance of Integer(0) and some exceptions, for example.)
My intuition tells me that somehow the two object/byte streams are getting intermingled, and this produces the strange results when attempting to deserialize the objects. My question is: why is this happening aka what am I doing wrong, and how could I fix it?
You have an array of Sockets but you don't appear to have an array of writers and readers. So you're probably using the same writer and reader for all connections.
Really you should have a per-connection Connection object, that implements Runnable, and that has the Socket, the writer, and the reader as instance members.
Also when you catch EOFException you must break out of the loop and close the writer.
The problem was occurring due to messages being sent simultaneously, and this resulted in the bytes being mixed. The solution was to make sure that messages would only be received one at a time.