It has to do with the difference between TCP and UDP. When you create a TCP socket you are creating a synchronous client connection to the port on another machine, and when you connect to an address you actually get a local port on the socket as well. So in your example code the two sockets created might be
clientSocket = localhost:2649 <-> ipAddress:8000
clientSocket1 = localhost:2650 <-> ipAddress:8000
Note that while they remote address is the same, the local address has different ports, which is why this is allowed. So here the local an remote machines can reliably send the data back and forth using the established ports.
For UDP this is not the case (I am assuming you are using DatagramSocket). Since UDP is asynchronous (as opposed to synchronous like TCP), to recieve data you are not creating a binding to another specific machine, so for example if you were to try
DatagramSocket udp1 = new DatagramSocket(8000); // = localhost:8000 <-> ?
DatagramSocket udp2 = new DatagramSocket(8000); // = localhost:8000 <-> ?
the udp socket does not know where the data is coming from so there can not be a unique mapping like TCP, also unlike TCP the port you specify is your machine's port, not a remote machine port.
Another way to think of it when you create a UDP socket it is like creating a TCP server socket. When you create a TCP server socket it is waiting for a connection to come from some machine but that machine is unknown and when you create a TCP server socket the port you specify is a local port:
ServerSocket ss1 = new ServerSocket(8000); // = localhost:8000 <-> ?
ServerSocket ss2 = new ServerSocket(8000); // = localhost:8000 <-> ?
Again like UDP this will create a bind exception because the port is for the local machine and the mappings are no longer unique. But when you accept a connection on a server socket the remote machine comes into play to make the socket unique, just as when you create a Socket to a remote machine:
Socket s1 = ss1.accept();// localhost:8000 <-> remoteIp1:12345
Socket s2 = ss1.accept();// localhost:8000 <-> remoteIp2:54321
Note that although the local address is the same, the remote addresses for the sockets are different, and hence the total mapping (localip:port<->remoteip:port) is now unique.
So in a way you can think of a UDP socket as kind of like a TCP server socket and that is why you have to bind it to a unique port.