【问题标题】:send and recieve Socket Datagram发送和接收 Socket 数据报
【发布时间】:2023-04-11 08:26:01
【问题描述】:

我正在做一个服务器和客户端套接字数据报。

客户端连接到服务器,你需要在客户端中写入一个包含Hello或hello的字符串。

当服务器检测到带有 hello 或 Hello 的字符串时,用另一个字符串回复客户端。

问题是客户端没有读取服务器发送的字符串。

这是我的代码。


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();
        }
    }
}

我已经尝试让服务器休眠,以防服务器在客户端尝试读取之前发送字符串。

非常感谢一如既往的帮助。

【问题讨论】:

    标签: java sockets datagram


    【解决方案1】:

    客户端正在使用无参数DatagramSocket() 构造函数绑定到一个随机端口,用于发送和接收:

    构造一个数据报套接字并将其绑定到本地主机上的任何可用端口。套接字将绑定到通配符地址,即内核选择的 IP 地址。

    但是,当服务器接收到数据报时,您将忽略实际发送数据报的 IP 和端口:

    DatagramSocket.receive(DatagramPacket)

    从这个套接字接收一个数据报包。当此方法返回时,DatagramPacket 的缓冲区被接收到的数据填充。 数据报包还包含发件人的 IP 地址,以及发件人机器上的端口号。

    当服务器发送回复时,您将其发送回localhost:5555 的服务器本身,而不是发送给客户端。

    在服务器端,你需要改变这个:

    DatagramPacket datagrama2 = new DatagramPacket(..., addr.getAddress(), 5555);
    

    到此:

    DatagramPacket datagrama2 = new DatagramPacket(..., datagrama1.getAddress(), datagrama1.getPort());
    

    或者到这个:

    DatagramPacket datagrama2 = new DatagramPacket(..., datagrama1.getSocketAddress());
    

    附带说明,您的服务器也忽略了客户端发送的数据的实际长度。服务器使用 25 字节数组接收数据,但客户端实际上可能并未发送 25 字节。如果客户端发送的字节数少于 25 个字节,您最终会得到一个包含随机垃圾的String。如果客户端发送超过 25 个字节,`receive() 将截断数据。

    试试类似的方法:

    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")) {
        ...
    }
    

    【讨论】:

      【解决方案2】:

      这很有趣:)

      请记住,这种编码方式可能不是最好的,但它可以按您的意愿工作。

      客户端发送Hello,服务器接收Hello,然后发送(Hello back at you)。

      然后两者都终止。它不会永远循环这两条消息,但我向你展示了这个想法。

      服务器也需要充当客户端才能发送消息。

      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();
      
        }
      }
      

      DSender 是客户端,但也需要充当服务器(监听来自其他服务器的消息)

      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();
          
        }
      }
      

      参考: https://www.javatpoint.com/DatagramSocket-and-DatagramPacket

      我运行服务器,然后是客户端。

      【讨论】:

      • 非常感谢您的回复!我已经对其进行了测试,并且效果很好!我添加了一个扫描仪,以便用户可以输入一个字符串。非常感谢!
      • 很高兴有帮助:)
      猜你喜欢
      • 2013-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-14
      相关资源
      最近更新 更多