IP headers in Java - java

I am testing the behaviour of some client software, and need to write some software that emulates router-like functionality, preferably using something simple like UDP sockets. All it needs to do is receive the packet, alter the time to live, and send it back. Is this possible in regular Java? Or do you do something like the following:
Listen on Socket A
For EACH udp packet received, open a NEW socket, set time to live on that socket, and send it back (or this isn't possible/efficient?)
Receiver gets packet with altered values that appear like it has traversed some hops (but in reality hasn't)
So two approaches may be possible - editing the recieved packet directly (and then simply sending back), or constructing a new packet, copying the values from the original one and setting the appropriate headers/socket options before sending it out.
EDIT: the 'router' does not do any complex routing at all such as forwarding to other routers... it is simply decrements the t-t-l header field of the received message and sends the message directly back to the client.

Please refer API of Socket and ServerSocket class. Most of the server implementation for variety of protocols does accept packets at standard port like 80 and send response using some ephemaral port.

Related

Underlying Workings of SelectionKey.interestOps(int ops)

I understand that Server socket channel is registered to listen for accept, when accepted a channel is registered for read and once read it is registered for write and this is done by adding the relevant keys to the SelectionKey's interest set using the interestOps method.
However, when we remove some interestOps from a key for e.g key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
What actually happens here? Does this mean that the server will just not listen for any incoming requests to channel belonging to this socket, and the source channel will be oblivious of this decision by the server and might keep on sending data to the server? Or will it somehow inform the channel source of this decision.
In packet switching parlance, is the above operation effectively the same as server receiving packets and just dropping the packet if the interestKeys for the channel this packet belong to have been "unset"
However, when we remove some interestOps from a key for e.g key.interestOps(key.interestOps() & ~SelectionKey.OP_READ);
What actually happens here?
What literally happens is something like:
public void interestOps(int interestOps)
{
this.interestOps = interestOps;
}
Does this mean that the server will just not listen for any incoming requests to channel belonging to this socket
It means that the Selector won't trigger any OP_READ events if data arrives via the socket. It doesn't mean that data won't be received.
and the source channel will be oblivious of this decision by the server and might keep on sending data to the server?
If by 'source channel' you mean the peer, it is not advised in anyway, unless the receive buffer fills up at the receiver.
Or will it somehow inform the channel source of this decision.
No.
In packet switching parlance, is the above operation effectively the same as server receiving packets and just dropping the packet if the interestKeys for the channel this packet belong to have been "unset".
No.

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.

detecting TCP/IP packet loss

I have tcp communication via socket code like :
public void openConnection() throws Exception
{
socket = new Socket();
InetAddress iNet = InetAddress.getByName("server");
InetSocketAddress sock = new InetSocketAddress(iNet, Integer.parseInt(port));
socket.connect(sock, 0);
out = new PrintWriter(socket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
and send method as :
synchronized void send(String message)
{
try
{
out.println(message);
}
catch (Exception e)
{
throw new RuntimeException(this.getClass() + ": Error Sending Message: "
+ message, e);
}
}
And I read from webpages that, TCP/IP does not guarantee delivery of packet, it retries but if network is too busy, packet may be dropped([link]).1
Packets can be dropped when transferring data between systems for two key reasons:
Heavy network utilization and resulting congestion
Faulty network hardware or connectors
TCP is designed to be able to react when packets are dropped on a network. When a packet is successfully delivered to its destination, the destination system sends an acknowledgement message back to the source system. If this acknowledgement is not received within a certain interval, that may be either because the destination system never received the packet or because the packet containing the acknowledgement was itself lost. In either case, if the acknowledgement is not received by the source system in the given time, the source system assumes that the destination system never received the message and retransmits it. It is easy to see that if the performance of the network is poor, packets are lost in the first place, and the increased load from these retransmit messages is only increasing the load on the network further, meaning that more packets will be lost. This behaviour can result in very quickly creating a critical situation on the network.
Is there any way, that I can detect if packet was received successfully by destination or not, I am not sure that out.println(message); will throw any exception, as this is non blocking call. It will put message in buffer and return to let TCP/IP do its work.
Any help?
TCP is designed to be able to react when packets are dropped on a network.
As your quote says, TCP is design to react automatically to the events you mention in this text. As such, you don't have anything to do at this level, since this will be handled by the TCP implementation you're using (e.g. in the OS).
TCP has some features that will do some of the work for you, but you are right to wonder about their limitations (many people think of TCP as a guaranteed delivery protocol, without context).
There is an interesting discussion on the Linux Kernel Mailing List ("Re: Client receives TCP packets but does not ACK") about this.
In your use case, practically, this means that you should treat your TCP connection as a stream of data, in each direction (the classic mistake is to assume that if you send n bytes from on end, you'll read n bytes in a single buffer read on the other end), and handle possible exceptions.
Handling java.io.IOExceptions properly (in particular subclasses in java.net) will cover error cases at the level you describe: if you get one, have a retry strategy (depending on what the application and its user is meant to do). Rely on timeouts too (don't set a socket as blocking forever).
Application protocols may also be designed to send their own acknowledgement when receiving commands or requests.
This is a matter of assigning responsibilities to different layers. The TCP stack implementation will handle the packet loss problems you mention, and throw an error/exception if it can't fix it by itself. Its responsibility is the communication with the remote TCP stack. Since in most cases you want your application to talk to a remote application, there needs to be an extra acknowledgement on top of that. In general, the application protocol needs to be designed to handle these cases. (You can go a number of layers up in some cases, depending on which entity is meant to take responsibility to handle the requests/commands.)
TCP/IP does not drop the packet. The congestion control algorithms inside the TCP implementation take care of retransmission. Assuming that there is a steady stream of data being sent, the receiver will acknowledge which sequence numbers it received back to the sender. The sender can use the acknowledgements to infer which packets need to be resent. The sender holds packets until they have been acknowledged.
As an application, unless the TCP implementation provides mechanisms to receive notification of congestion, the best it can do is establish a timeout for when the transaction can complete. If the timeout occurs before the transaction completes, the application can declare the network to be too congested for the application to succeed.
Code what you need. If you need acknowledgements, implement them. If you want the sender to know the recipient got the information, then have the recipient send some kind of acknowledgement.
From an application standpoint, TCP provides a bi-directional byte stream. You can communicate whatever information you want over that by simply specifying streams of bytes that convey the information you need to communicate.
Don't try to make TCP do anything else. Don't try to "teach TCP" your protocol.

Sending UDP packet to everybody in a LAN?

Is there a way to send a UDP packet inside a LAN so that every machine receives it? (Of course no guarantees because its UDP).
Like, sending a request "Hello, anybody out there?" and then listening for a response?
I got no problem with sending and receiving, just want to know if there's a way other than trying out every IP address possible...
Edit: This is what I use at the moment:
...
multicastSocket = new MulticastSocket();
multicastSocket.setBroadcast(true);
broadcastGroup = InetAddress.getByName("255.255.255.255");
// multicastSocket.joinGroup(broadcastGroup);
...
The last line of code is commented out because it throws an exception. Now I've read that sending a packet to 255.255.255.255 is "deprecated since years" and most likely won't work on many LANs. Also, I'm not sure if I even need a MulticastSocket for this or if a normal DatagramSocket would work as well. But anyway, what would be the preferred way to send a UDP broadcast nowadays?
Well, I found it out by myself:
Just open a MulticastSocket and use joinGroup on any IP between 224.0.0.0 and 239.255.255.255. Of course everything related to that multicast group needs to receive on the same multicast IP.
I did it for sending AND receiving, however, I think you only need it when receiving messages. When you want to broadcast a packet to everybody in the IP group, just send it to the IP you selected.
You should also do setBroadcast(true); to allow broadcasting for certain (?) systems.
Technically speaking you actually need to broadcast the message. Basically you need MulticastSocket, this kind of socket is used on the client-side to listen for packets that the server broadcasts to multiple clients.
Here is the java tutorial to help you achieve that:
http://docs.oracle.com/javase/tutorial/networking/datagrams/broadcasting.html

java socket sending and receiving

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.

Categories

Resources