Some UDP socket programming questions I am confused about - java

What would happen if change both clientSocket and serverSocket to “mySocket”?
Can the client send a segment to server without knowing the server’s IP address and/or port number?
Can multiple clients use the server?
From my notes, on page 20 : http://www.cs.ucc.ie/~cjs/teach/cs2505/02-app-layer-b.pdf . Kind of confused with these.
I assume if you change both client and serverSocket to mySocket then nothing would happen, since it would only be a variable name change( I assume ).
And I assume the client can't send a message without know the IP address/port no?
And that multiple clients cannot use the server since that would require threading?

(1) Since I see no reference to mySocket other than the one in the question I would say your answer seems right.
(2) The address/port are obviously necessary. However this could be a trick question in that client could call connect() on the socket. With UDP, connect() the kernel keeps track of the address passed in the call as the peer of the socket. The socket could then just call write() or send() rather than having to use sendto(). Still, calling connect would still require the address/port in the first place so who knows what they are getting at.
(3) There is no "connection" in UDP. Many clients could send to the server. The server can get the address of the individual clients from its recvfrom and then turn around and use that address in its sendto.

Related

Java - Is it possible to send a client to another server?

I'm working on a ServerSocket with java, and I would like to know, upon a client connecting, is it possible to send the Client/Socket to another ServerSocket. For example a client connects to 123.41.67.817(Just a random IP) and upon connection, the client gets sent straight to for example 124.51.85.147(Another Random IP) with a port of course. So a little Map of what would happen.
ServerSocket(Listening for Connections)
Client ---> ServerSocket(Client connects)
ServerSocket -> Client(Server says: Hello, I am going to send you to 124.51.85.147)
Client -> ServerSocket(Client Says: OK!)
Client ---> ServerSocket(124.51.85.147)(Client gets sent to a different server Socket)
ServerSocket(124.51.85.147) -> Client(Server2 says: Welcome!) and then the client stays on Server2(124.51.85.147)
Is this possible in any way. Sorry for the long question.
Is this possible in any way.
No.
At the most basic level, a TCP/IP connection is a conversation between a pair of IP addresses. There is no provision in the TCP/IP protocol for changing one of the two IP addresses in mid conversation.
Even if it were possible at the Java level to (somehow) serialize the Socket object and send it to another program (local or remote), it would not be possible to change the IP addresses for the underlying conversation; see above.
Historical footnote: A long time ago (1980's) in a country far away (Cambridge UK) there was a network (The Cambridge Ring) whose stream protocol (BSP) implemented an operation known as "replug". If you had BSP connection between A & B and another between B & C, then B could replug the connections so that A talked directly to C. Reference: "The Cambridge Distributed Computer System" by R.M. Needham & A.J Herbert (Annex C).
I've never seen a replug operation elsewhere. Indeed, if you think about it, it requires a complicated 3-way handshake to implement a replug-like operation reliably. In the BSP case, they didn't do that ... at least according to the description in Needham & Herbert.

Why Bind a socket

I've searched here and found a similar article but I didn't really get the answer I'm looking for. I'm learning Networking with Java through some examples and some pseudo-reverse engineering. Oracle's documentation is helping quite a bit too but I've got a few questions.
Why exactly do you bind an IP address to a Socket? Is it necessary? When would you use said binding?
Here is part of the code that raised the question to me:
ServerSocket myServerSocket = new ServerSocket(1337);
System.out.println("Server is waiting for an incoming connection from client...");
Socket recievingSocket = myServerSocket.accept();
Now from what I understand that if I was to bind a Socket it would be right after the running accept() correct?
Why exactly do you bind an IP address to a Socket?
To determine which outbound interface it will connect via.
Is it necessary?
In theory, no. In practice it is sometimes required when connecting via a VPN.
Now from what I understand that if I was to bind a Socket it would be right after the running accept() correct?
Incorrect. An accepted or connected Socket is already bound. The only ways to bind a Socket are:
Create it with new Socket() with no arguments and then call bind(), or
Create it with the four-argument constructor, where the first two arguments are the target address and the second two are the bind-address.
The major use of bind() is in conjunction with ServerSocket. For instance, in your example, calling new ServerSocket(1337) creates a socket, binds it to 0.0.0.0:1337, and puts it into the LISTEN state.
You bind a socket to an address in order to restrict where the socket is going to be listening to. It is not necessary if you want it to use default behavior, which IIRC is to listen to ANY.
You would bind before you use accept because accept tells the socket to start listening on the socket, but bind tell it where to look. The socket needs to know where to look before it listens.
Socket is essentially = IP + Port.
So yes you need an IP address to create a socket. And the process is termed as binding because you may bind multiple ports to same address all listening to their respective incoming connections.
Above pretty much sums your question of is it necessary but to add another point - Lets say you create a client to connect to your server. How will it connect if does not know server IP address and port to which it is suppose to connect.

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

Some java Datagram Socket questions

I have recently nose dived into socket programming using java, and I have a few general sort of questions.
There is a bind() method, as well as a connect() and disconnect(). There is no unbind(). Is this because upon disconnecting the socket is unbound? Does garbage collection take care of this once the program exits? Or is this not even a valid question?
Also, upon creating a DatagramSocket, how is it different if I only provide the port and the address? I am creating a program to collect data off a network, as the data floats around and log it. Should I just use the local address? Could not using the address when I create the socket cause me to not be able to collect packets?
I am just trying to get a stronger understanding on the inner-workings of these things.
There are about 15 independent questions in there, but I'll do my best to address them:
There is a bind() method, as well as a connect() and disconnect(). There is no unbind(). Is this because upon disconnecting the socket is unbound?
bind() is separate from connect() and disconnect(). Bind is used to bind a socket to a particular port -- effectively to "listen" for connections whereas connect() is used to open a connection to a socket that is already listening on a particular port. The equivalent of unbind() is close()
Does garbage collection take care of this once the program exits? Or is this not even a valid question?
This is a totally valid question, although garbage collection is a technology used for memory management, not socket/OS resource management. If you don't release a particular port, it will remain associated with your application until your application terminates and it will then be reclaimed by the OS. This is OS-level functionality, not JVM functionality, etc.
Also, upon creating a DatagramSocket, how is it different if I only provide the port or provide the port and the address?
At some point, you have to provide the internet address and port or the socket you wish to connect to or to bind to. There's no way around it.
I am creating a program to collect data off a network, as the data floats around and log it. Should I just use the local address? Could not using the address when I create the socket cause me to not be able to collect packets?
I'm not sure what you're asking here, are you talking about logging all packets on the network, aka a sniffer? That's going to require more than simple datagram programming. You actually have to inject yourself at the network-adapter level to intercept packets as they are read off the line. What you're talking about will only allow you to receive packets that are sent to the specific port you're listening to.
A DatagramSocket remains bound when disconnected, it is the close() method that would unbind it. Note that for a UDP (datagram) socket the semantics of connect() and disconnect() are different as compared to a TCP (or other connection oriented) socket. UDP is a connectionless protocol and a bound DatagramSocket can send and receive packets without being 'connected'. The connect() method has a purely local effect in that it causes the socket to only be able to send and receive packets to a given host/port, i.e. acting as a filter. A DatagramSocket connected to a multicast or broadcast address will only be able to send packets and not receive them.
bind(SocketAddress) is used to attach a socket to a local address/port combination, before a socket is bound it cannot receive or send any packets. The default behaviour of the constructors is to bind the socket immediately. To create an unbound 'DatagramSocket' use the DatagramSocket(SocketAddress) constructor passing null as an argument. Then it is possible to apply any custom configuration to the socket before binding it with bind().
As far as I know an open DatagramSocket that goes out of scope will cause a resource leak, the object may be garbage collected, but I'm pretty sure the underlying UDP socket will remain allocated by the OS until the JVM process exits.
If an address is not specified before the socket is bound, when bound it will attach to the wildcard address (INADDR_ANY), making it able to receive and send packets from any available local address (unless it is later 'connected' to some host). If a port is not specified (or specified as 0) then the socket is bound to some available port chosen by the OS (ephemeral port).
Edit: An example
// bind to INADDR_ANY, allowing packets on all IP addresses of host:
DatagramSocket dsock = new DatagramSocket(55555);
DatagramPacket packet = new DatagramPacket(new byte[8192]);
//next packet can be from anywhere including local host (127.0.0.0/8)
dsock.receive(packet);
// restrict communication to a single host/port:
dsock.connect(new InetSocketAddress("somehost.net", 99));
// next packet can only be from somehost.net on port 99:
dsock.receive(packet);

How to distinguish between two different UDP clients on the same IP address?

I'm writing a UDP server, which is a first for me; I've only done a bit of TCP communications. And I'm having trouble figuring out exactly how to distinguish which user is which, since UDP deals only with packets rather than connections and I therefore cannot tell exactly who I'm communicating with.
Here is pseudocode of my current server loop:
DatagramPacket p;
socket.receive(p); // now p contains the user's IP and port, and the data
int key = getKey(p);
if(key == 0) { // connection request
key = makeKey(p);
clients.add(key, p.ip);
send(p.ip, p.port, key); // give the user his key
} else { // user has a key
// verify key belongs to that IP address
// lookup the user's session data based on the key
// react to the packet in the context of the session
}
When designing this, I kept in mind these points:
Multiple users may exist on the same IP address, due to the presence of routers, therefore users must have a separate identification key.
Packets can be spoofed, so the key should be checked against its original IP address and ignored if a different IP tries to use the key.
The outbound port on the client side might change among packets.
Is that third assumption correct, or can I simply assume that one user = one IP+port combination? Is this commonly done, or should I continue to create a special key like I am currently doing?
I'm not completely clear on how TCP negotiates a connection so if you think I should model it off of TCP then please link me to a good tutorial or something on TCP's SYN/SYNACK/ACK mess.
Also note, I do have a provision to resend a key, if an IP sends a 0 and that IP already has a pending key; I omitted it to keep the snippet simple. I understand that UDP is not guaranteed to arrive, and I plan to add reliability to the main packet handling code later as well.
UDP packet headers have a source port, which is generally used as the reply port. If not used, it should be zero, and then it is up to the higher level protocol to figure out how to coordinate request-response activity with multiple clients.
* The outbound port on the client side might change among packets.
Is that third assumption correct
Not if the client keeps using the same outbound socket. Sending the first datagram will cause a local bind, so the socket will be on a fixed local port from then on.
Your questions are just the tip of the iceburg WRT laundry list of issues you need to be aware of when using UDP. You should expect NAT routers to fail to provide any meaningful forwarding of a UDP protocol you design. TCP works because the routers understand the TCP state machine and store connection state of each session so they know how to forward it. They will have no idea how your custom UDP protocol works. NAT devices include specific protocol handlers for well known UDP applications.
If a sender is bound to a source port and or interface the senders source ports remain constant until unbound.
With UDP you can bind both peers to a known source port for (dst) incoming and or (src) outgoing messages. For client/server applications you typically want the client to bind to a dynamic source port so that multiple clients can co-exist on a single client system. The server can then respond to the client using the dynamic source port provided via the src port from request used as destination port in the response. Using a known port for peers allows you to configure UDP forwarding in NAT devices.
ex client/server with server on known port 3000
client binds to a random port (1234) but knows server is listening on port 3000.
client (src 1234) -> server (dst 3000)
server (dst 1234) -> client (src 3000)
...
If a computer has multiple interfaces you should expect to either need to explicitly bind a listener or sender to a specific IP address or be able to handle requests and responses from a peer being sent and recieved from a random IP based on the whims of the computers routing table. If you choose to bind requests to a specific interface then you need to be cognizant of the routing table if messages from a multi-homed system need to transit a different local interface for delivery. For example if you bind a UDP socket to 127.0.0.1 you obviously can't use it to send to any Internet routable IP Addresss.
In terms of protocol design its common to frame a session id and sequence fields in the UDP payload so that peers can keep track of sessions and individual exchanges.
There are a whole host of fragmentation, NAT coexistance, security and congestion issues you need to be aware of to successfully design a robust UDP protocol. I advise against it unless absolutely necessary.

Categories

Resources