I am doing a server and client socket datagram. The client connects to the server and you need to write in the client a string that contains Hello or hello. When the server detects a string with hello or Hello, replies to the client with another string. The problem is that the client doesn't read the string that the server sends. Here is my code.
Client public class Client < public static void main(String[] args) < try < System.out.println("Creando socket datagram"); DatagramSocket datagramSocket = new DatagramSocket(); Scanner myObj = new Scanner(System.in); // Create a Scanner object System.out.println("Say Hello"); String saludo = myObj.nextLine(); System.out.println("Sending message"); InetAddress addr = InetAddress.getByName("localhost"); DatagramPacket datagrama = new DatagramPacket(saludo.getBytes(), saludo.getBytes().length, addr, 5555); datagramSocket.send(datagrama); System.out.println("Message sent"); System.out.println("Reading message"); byte[] mensaje = new byte[25]; DatagramPacket datagrama1 = new DatagramPacket(mensaje, 25); datagramSocket.receive(datagrama1); System.out.println("Message recieved: " + new String(mensaje)); System.out.println("Closing"); datagramSocket.close(); System.out.println("FInished"); >catch (IOException e) < e.printStackTrace(); >> >
public class Server < public static void main(String[] args) throws InterruptedException < try < for (;;) < System.out.println("Creating socket datagram"); InetSocketAddress addr = new InetSocketAddress("localhost", 5555); DatagramSocket datagramSocket = new DatagramSocket(addr); System.out.println("RReading message"); byte[] mensaje = new byte[25]; DatagramPacket datagrama1 = new DatagramPacket(mensaje, 25); datagramSocket.receive(datagrama1); System.out.println("Message recieved: " + new String(mensaje)); if (new String(mensaje).contains("hello") || new String(mensaje).contains("Hello")) < String quetal = "¿Hello, how are you doing?"; System.out.println("Sending message"); TimeUnit.SECONDS.sleep(2); DatagramPacket datagrama2 = new DatagramPacket(quetal.getBytes(), quetal.getBytes().length, addr.getAddress(), 5555); datagramSocket.send(datagrama2); System.out.println("Message Sent"); >datagramSocket.close(); > > catch (IOException e) < e.printStackTrace(); >> >
I have tried putting a sleep in the server in case the server sends the string before the client tries to read. Many thanks for the help as always.
4,573 1 1 gold badge 13 13 silver badges 40 40 bronze badges asked Dec 15, 2020 at 14:06 syzygy syzygy syzygy syzygy 41 1 1 silver badge 7 7 bronze badgesThe client is using the parameter-less DatagramSocket() constructor to bind to a random port with which to send and receive on:
Constructs a datagram socket and binds it to any available port on the local host machine. The socket will be bound to the wildcard address, an IP address chosen by the kernel.
However, when the server receives a datagram, you are ignoring the IP and port where the datagram was actually sent from:
Receives a datagram packet from this socket. When this method returns, the DatagramPacket 's buffer is filled with the data received. The datagram packet also contains the sender's IP address, and the port number on the sender's machine.
When the server is sending the reply, you are sending it back to the server itself at localhost:5555 , not to the client at all.
On the server side, you need to change this:
DatagramPacket datagrama2 = new DatagramPacket(. addr.getAddress(), 5555);
DatagramPacket datagrama2 = new DatagramPacket(. datagrama1.getAddress(), datagrama1.getPort());
DatagramPacket datagrama2 = new DatagramPacket(. datagrama1.getSocketAddress());
On a side note, your server is also ignoring the actual length of the data that is being sent by the client. The server is receiving data using a 25-byte array, but the client may not actually be sending 25 bytes. If the client sends less than 25 bytes, you will end up with a String that contains random garbage on the end of it. And if the client sends more than 25 bytes, receive() will truncate the data.
Try something more like this instead:
System.out.println("Reading message"); byte[] buffer = new byte[65535]; DatagramPacket datagrama1 = new DatagramPacket(buffer, buffer.length); datagramSocket.receive(datagrama1); String mensaje = new String(datagrama1.getData(), datagrama1.getLength()); System.out.println("Message recieved: " + mensaje); if (mensaje.contains("hello") || mensaje.contains("Hello"))answered Dec 15, 2020 at 17:20 Remy Lebeau Remy Lebeau 585k 32 32 gold badges 487 487 silver badges 818 818 bronze badges
Better still, just reuse the incoming DatagramPacket and just change the data. The source address is already in there.
Commented Jan 2 at 22:36Kindly keep in mind, the way this is coded might not be the best, however it works as you want.
The Client sends Hello, The server receives Hello, and Sends (Hello back at you).
Both then terminate. It doesnt keep on looping those 2 messages forever, but I showed you the idea.
The Server needs to act as a Client as well in order to send messages.
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; public class DReceiver < public static void replyToTheClientListening() throws IOException < DatagramSocket ds = new DatagramSocket(); String str = "hello back at you"; InetAddress ia = InetAddress.getByName("127.0.0.1"); DatagramPacket dp = new DatagramPacket(str.getBytes(), str.length(), ia, 3001); ds.send(dp); ds.close(); >public static void listenToMessagesFromTheClient() throws IOException < DatagramSocket ds = new DatagramSocket(3000); ds.setSoTimeout(60000); //Wait 60 SECONDS for messages byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, 1024); ds.receive(dp); String strRecv = new String(dp.getData(), 0, dp.getLength()); if("hello".equalsIgnoreCase(strRecv)) < //hello in any case System.out.println("Received a MSG from the Client " + strRecv); replyToTheClientListening(); >ds.close(); > public static void main(String[] args) throws Exception < listenToMessagesFromTheClient(); >>
The DSender is a Client but also needs to act as a Server (To Listen to Messages coming in from the other Server)
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; public class DSender < public static void actAsAServerAndListenToMessages() throws IOException < //Listen to Port 3001 --The Server will send to that port DatagramSocket dsReceive = new DatagramSocket(3001); dsReceive.setSoTimeout(60000); //Make it wait 60 SECONDS byte[] buf = new byte[1024]; DatagramPacket dpReceive = new DatagramPacket(buf, 1024); dsReceive.receive(dpReceive); String strRecv = new String(dpReceive.getData(), 0, dpReceive.getLength()); System.out.println("Client -- Received a Msg back from Server --" + strRecv); dsReceive.close(); >public static void sendAMessageAsAClientToTheServer() throws IOException < // Client will send a message to Port 3000 which the Server listens to. DatagramSocket ds = new DatagramSocket(); String str = "hello"; InetAddress ia = InetAddress.getByName("127.0.0.1"); DatagramPacket dp = new DatagramPacket(str.getBytes(), str.length(), ia, 3000); ds.send(dp); ds.close(); >public static void main(String[] args) throws Exception < sendAMessageAsAClientToTheServer(); actAsAServerAndListenToMessages(); >>
I run the server, then the Client.