java socket sending and receiving - java

since hours I am thinking about how I should use Java Sockets to send and receive data. I hope you can help me finding a good way to do it.
I have build a Server/Client structure where the client connects to the server and gets his own thread handling a request-response method. The information are capsuled in XML.
At the beginning the Server starts a blocking socket read. First I use writeInt() where the lenght of the XML message is transmitted. After that the Server reads the amount of lenght bytes and parses the message. After the transmission the client goes in the receive state and waits for an response.
That is fine but after the client authenticates the server waits for the things that will come and blocks.
But what should I do when the server has no information which needs to be transmitted. I could try to destroy the read blocking and send the message to the client. But what happens if the client comens in mind that he has also a message and also begins to send. In that moment no one will listen.
For that maybe I could use some sort of buffer but I have the feeling that this is not the way I should go.
I have been searching for a while and found some interesting information but I didn't understand them well. Sadly my book is only about this simple socket model.
Maybe I should use two threads. One sending and one receiving. The server has a database where the messages are stored and waiting for transmission. So when the server receives a message he stores that message in the database and also the answer like "message received" would be stored in the database. The sender thread would look if there are new messages and would send "message received" to the client. That approach would not send the answer in millisenconds but I could image that it would work well.
I hope that I gave you enough information about what I am trying. What would you recommend me how to implement that communication?
Thanks

But what should I do when the server has now information which needs to be transmitted.
I would make writes from the server synchronized. This will allow you to respond to requests in one thread, but also send other messages as required by another thread. For the client you can have a separate thread doing the receiving.
A simpler model may be to have two sockets. One socket works as you do now and when you "login" a unique id is sent to the client. At this point the client opens a second connection with a dedicated thread for listening to asynchronous events. It passes the unique id so the server know which client the asynchronous messages are for.
This will give a you a simple synchronous pattern as you have now and a simple asynchronous pattern. The only downside is you have two socket connections and you have co-ordinate them.

Related

Java - Recognise sent-to-one and sent-to-all messages from server, on the client-side

I am working on a server/client application that allows multiple clients to be connected to the server at any given time.
For each client, the server sets up a ClientHandler object that has an input and output stream to the client connected at this socket. Through this connection, the client is free to send a number of messages to the server at any point throughout the running of the program, and the server will respond according to the message.
What I need to implement is a mechanism that sends, at certain times, messages to all currently-connected clients. I have done this by storing all the output streams to clients in an ArrayList<PrintWriter> that will allow the same message to be sent to all clients.
What I am struggling with is this:
When a message is received that is individual to the client, the client GUI is updated accordingly (only a select number of messages can be sent, so there only a select number of possible responses-from-server, dealt with by client-side if statements). However, when a message is received by the client that was sent to all clients, I would like the client to update the GUI quite differently.
Considering that both forms of input come from the same input stream, I can see this being difficult, and I anticipate that I will have to declare any methods that cause output using the PrintWriter will have to be made synchronized. However, is there a way to process the different inputs while using the same PrintWriter at all? Would this have to be done using further if statements or could it be done using a separate Thread on the client side that handles messages sent to all clients?
Thanks for any advice, if you think you can help then feel free to ask for parts of my existing code!
Mark
You are first of all lacking a protocol between your server and your clients!
Obviously the server can send two types of messages "response" and "broadcast".
A rather simple approach is tagging your messages: e.g. prefix your mesages with "R" if it is a response to a request and with "B" if it is an unattended broadcast message. (This all depends how communication between server and clients is intended to be performed.)
Whether your client needs different threads for coping with the messages is a completly different story. Having different threads is useful if the processing activity within your client would prevent timely reads of the socket. Then you might consider having an I/O thread that is doing communications and is dispatching the messages to different "handlers" (could be other threads) for processing. (This I/O thread also can remove the tag such that existing processing code need not learn about the lower protocol with the server.)
An analogous reasoning might apply to your server side. Depending on the dynamics of interactions and processing of requests, you might use several threads. Then you should have one that is doing I/O with the clients and others that are doing the work (generating responses or broadcast messages)
When your clients connect to the server, your server creates a Socket for it, here it is Socket socket = ss.accept();, your socket variable will be holding that client.
now if you just keep adding your client socket to a arraylist in your while loop, you will have a list of clients actively connected with your server like:
after the accept:
clients = new ArrayList<DataOutputStream>();
Socket socket = ss.accept();
os = new DataOutputStream(socket.getOutputStream());
clients.add(os);
Now as you have all the clients in that clients arraylist, you can loop through it, or with some protocol define which client should i send the data after reading.

How to check if a message is really delivered in Netty using websocket?

I'm developing a websocket application by using Netty. I'd like to know if a message is really delivered from a source to a destination. In particular, let's assume that a client and a server have an open channel and exchange some messages for a while. At a certain point, the client goes down, but the channel is still active in Netty. I tried to use isReachable() before sending the message, but this method seems to be buggy in some scenarios (e.g. a machine with Win7 is up, but isReachable() returns false). Now, my idea is to implement a mechanism using ACKs, namely the server sends the message and the client sends back an ack. To do that, I need a timeout to see if, after a certain interval, the corresponding ack does not arrive. Is there something similar in Netty?
Regarding isReachable() - it's only a best effort API. The documentation points out that it tries to send an ICMP echo request or create a TCP connection to port 7 on the destination host, both of which are highly likely to be blocked by a firewall. Is this happening in your case?
As for the acknowledgement, there's nothing in Netty that provides this as standard, but it shouldn't be too difficult to implement. Firstly each message needs to be uniquely identifible by some sort of identifier, possibly a sequence number but a globally unique identifier means you can potentially recover across disconnections. Then you want to create a combined handler that implements both ChannelInboundHandler and ChannelOutboundHandler (assuming Netty 4). When a message is sent
add the message to a map indexed by its id
create a timer associated with the message id. Add it to another map indexed by message id
forward the message
When the ACK is received cancel the timer and remove the timer and message from their respective maps. If the timer fires use the associated id to decide what to do with the timer and message (possibly retransmit and reset the timer).
Netty provides a HashedWheelTimer for efficiently managing lots of timers with a resolution suitable for this kind of activity.
You may also want to consider putting a limit on the number of retries so you can stop and raise an error rather than continually indefinitely.

Java multithreaded stateful server - networking design

I'm trying to implement a stateful, multi-client server application and have some questions about the networking/threading design. The problem I'm currently facing is how to exchange messages between the communication layer and the logic layer.
The server handles multiple clients, where each of them can be active in multiple "channels", where each channel has multiple stages and may have multiple clients acting in it. Think of it to something similar as a chat program with multiple rooms.
I have already implemented the receiving of messages on the server side. Each client has his own thread that blockingly reads the data and decodes into a message. Now how to proceed? In my oppinion, each channel should also have this own thread to easily maintain its state. I could use a BlockingQueue to exchange the received messages with the channel thread, who's blockingly waiting for new messages on that queue.
But then how to send messages to the clients? The logic in the channel will handle the message, and produce some messages to be sent to one/some/all of the clients. Is it safe to use the channel thread to directly write to the socket? Or should I use another BlockingQueue to transmit the messages to the client handler thread? But how to wake it then, since it's waiting on the socket to read? Or should I use a separate send-thread per client, or even a separate send-socket?
BTW: I know I could use existing libraries for the networking layer, but I want do do it from scratch on plain sockets.
Put a send message method on the communication object that wraps the socket. Synchronize this method so that only one thread can be calling it at once. Then, it doesn't make any difference how many threads call this method. Each message will only be sent one at a time. You also don't have to disturb the thread that's blocking to read. This send method will be a quick enough operation that you don't have to worry about other threads blocking while a thread sends.
As long as the channel has a reference to the communication objects for each connected client, it can send messages and not worry about it.
If it ever caused problems, you could always modify that send message to enqueue the object to be sent. Then you could have a specific send thread to block on the queue and write the contents to the socket. But from my experience, this won't be necessary.
What about a event mechanism? When you ready with processing the request and there is a data for client available, then simply send it with an event for the client socket handler thread. as because the transmission from client is ended, you can send reply normally - if i think correctly.

Sending an array over a socket with Java

I have an 2-dimensional array to send over the socket
The client is implemented so that it has 2 threads, one for rendering the swing gui and one for RECEIVING the data from server.
The server is implemented so that it has 2 threads, one for listening to incoming request and then put the request to another thread for processing the request (communicating with client)
Once the client interact with the swing gui, data will be constructed and sent to the server (actually, send to the thread which is in charge of processing the particular client), the server then processes the data and send back to client with a new data in an 2-dimensional array with updated information. The client can use the array to render the view.
However, when the first time the client send data, it ok, everything is fine. But the next time, client send new data, but it still receive the old one (server data is still updating)
I dont know if the problem is with the socket itself or the thread.
If you are using Serialization, see the Javadoc for ObjectOutputStream.reset() and ObjectOutputStream.writeUnshared().

NIO: Send message and then disconnect immediately

In some circumstances I wish to send an error message from a server to client using non-blocking I/O (SocketChannel.write(ByteBuffer)) and then disconnect the client. Assuming I write the full contents of the message and then immediately disconnect I presume the client may not receive this message as I'm guessing that the OS hasn't actually sent the data at this point.
Is this correct, and if so is there a recommended approach to dealing with this situation?
I was thinking of using a timer whereby if I wish to disconnect a client I send a message and then close their connection after 1-2 seconds.
SocketChannel.write will in non-blocking mode return the number of bytes which could immediately be sent to the network without blocking. Your question makes me think that you expect the write method to consume the entire buffer and try asynchronously to send additional data to the network, but that is not how it's working.
If you really need to make sure that the error message is sent to the client before disconnecting the socket, I would simply enable blocking before calling the write method. Using non-blocking mode, you would have to call write in a loop, counting the number of bytes being sent by each invocation and exit the loop when you've succeeded to pass the entire message to the socket (bad solution, I know, unnecessary code, busy wait and so on).
you may be better off launching a thread and synchronously write data to the channel. the async api is more geared toward "one thread dispatching multiple channels" and not really intended for fire and forget communications.
The close() method of sockets makes sure, everything sent using write before is actually sent before the socket is really closed. However this assumes that your write() was able to copy all data to the tcp stacks output window, which will not always work. For solutions to this see the other answers.

Categories

Resources