本地datagramsocket(服务器)正在向自身发送数据包

ht4b089n  于 2021-09-13  发布在  Java
关注(0)|答案(2)|浏览(495)

所以在过去的几天里,我一直在开发一个udp api,我尝试先在本地机器上测试我的api。
所以我在不同的线程中创建了一个服务器和一个客户端示例。
当我用客户机向服务器发送数据包时,服务器收到了这些数据包,但当我试图从服务器向客户机发送数据包时,服务器只是将其消息发送给自己,并对其接收到的数据包做出响应,最终形成了无限消息发送的循环。
以下是当前代码的一些部分:
客户
服务器
客户:

  1. package com.github.sebyplays.jsimpleudp;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. import lombok.SneakyThrows;
  5. import java.io.IOException;
  6. import java.net.DatagramPacket;
  7. import java.net.DatagramSocket;
  8. import java.net.InetAddress;
  9. import java.util.Scanner;
  10. import java.util.concurrent.TimeUnit;
  11. public class Client implements ICommunicator{
  12. @Getter private DatagramSocket datagramSocket;
  13. private boolean running;
  14. @Getter @Setter private byte[] buffer = new byte[1024];
  15. @Getter @Setter private PacketReceiver packetReceiver;
  16. @Getter @Setter private InetAddress host;
  17. private Type type = Type.CLIENT;
  18. @Getter private int port;
  19. @Getter private DatagramPacket lastReceivedPacket;
  20. @Getter private DatagramPacket lastSentPacket;
  21. private long lastReceivedTime = 0;
  22. private long lastSentTime = 0;
  23. @SneakyThrows
  24. public Client(String host, int port, PacketReceiver packetReceiver) {
  25. this.packetReceiver = packetReceiver;
  26. this.port = port;
  27. this.host = InetAddress.getByName(host);
  28. this.datagramSocket = new DatagramSocket();
  29. }
  30. @Override
  31. public void start() {
  32. running = true;
  33. Thread thread = new Thread("udpclient"){
  34. @SneakyThrows
  35. @Override
  36. public void run() {
  37. while (running){
  38. DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length, host, port);
  39. datagramSocket.receive(datagramPacket);
  40. lastReceivedPacket = datagramPacket;
  41. lastReceivedTime = System.currentTimeMillis();
  42. callReceiver(datagramPacket);
  43. }
  44. }
  45. };
  46. thread.start();
  47. }
  48. @Override
  49. public void stop() {
  50. running = false;
  51. if(!datagramSocket.isClosed()){
  52. datagramSocket.close();
  53. }
  54. }
  55. public void sendPacket(DatagramPacket datagramPacket){
  56. try {
  57. datagramSocket.send(datagramPacket);
  58. lastSentPacket = datagramPacket;
  59. lastSentTime = System.currentTimeMillis();
  60. } catch (IOException e) {
  61. e.printStackTrace();
  62. }
  63. }
  64. public void callReceiver(DatagramPacket datagramPacket){
  65. packetReceiver.onPacket(this, datagramPacket, datagramPacket.getAddress(),
  66. new String(datagramPacket.getData(), 0, datagramPacket.getLength()), this.getType());
  67. }
  68. @Override
  69. public Type getType() {
  70. return this.type;
  71. }
  72. @Override
  73. public void sendMessage(InetAddress inetAddress, String message){
  74. byte[] messageBytes = message.getBytes();
  75. DatagramPacket datagramPacket = new DatagramPacket(messageBytes, messageBytes.length, inetAddress, port);
  76. sendPacket(datagramPacket);
  77. }
  78. @Override
  79. public long getLastReceivedTime() {
  80. return System.currentTimeMillis() - lastReceivedTime;
  81. }
  82. @Override
  83. public long getLastSentTime() {
  84. return System.currentTimeMillis() - lastSentTime;
  85. }
  86. public static void main(String[] args) {
  87. Client client = new Client("mcsilent.de", 2312, new PacketReceiver() {
  88. @Override
  89. public void onPacket(ICommunicator iCommunicator, DatagramPacket datagramPacket, InetAddress source, String packet, Type type) {
  90. System.out.println(packet);
  91. }
  92. });
  93. client.start();
  94. Scanner scanner = new Scanner(System.in);
  95. while (true){
  96. if(scanner.nextLine().equalsIgnoreCase("r")){
  97. client.sendMessage(client.getHost(), "InfoRequest::lobby01");
  98. }
  99. }
  100. }
  101. }

服务器:

  1. package com.github.sebyplays.jsimpleudp;
  2. import lombok.Getter;
  3. import lombok.Setter;
  4. import lombok.SneakyThrows;
  5. import java.io.IOException;
  6. import java.net.DatagramPacket;
  7. import java.net.DatagramSocket;
  8. import java.net.InetAddress;
  9. import java.net.SocketException;
  10. public class Server implements ICommunicator{
  11. @Getter private DatagramSocket datagramSocket;
  12. private boolean running;
  13. @Getter @Setter private byte[] buffer = new byte[1024];
  14. private Type type = Type.SERVER;
  15. private int port;
  16. @Getter @Setter private PacketReceiver packetReceiver;
  17. @Getter private DatagramPacket lastReceivedPacket;
  18. @Getter private DatagramPacket lastSentPacket;
  19. private long lastReceivedTime = 0;
  20. private long lastSentTime = 0;
  21. public Server(int port, PacketReceiver packetReceiver) throws SocketException {
  22. this.datagramSocket = new DatagramSocket(port);
  23. this.packetReceiver = packetReceiver;
  24. this.port = port;
  25. }
  26. public void start(){
  27. this.running = true;
  28. Thread thread = new Thread("udpserver"){
  29. @SneakyThrows
  30. @Override
  31. public void run() {
  32. while (running){
  33. DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
  34. datagramSocket.receive(datagramPacket);
  35. lastReceivedPacket = datagramPacket;
  36. lastReceivedTime = System.currentTimeMillis();
  37. callReceiver(datagramPacket);
  38. }
  39. }
  40. };
  41. thread.start();
  42. }
  43. @Override
  44. public void stop(){
  45. this.running = false;
  46. if(!datagramSocket.isClosed()){
  47. datagramSocket.close();
  48. }
  49. }
  50. public void sendPacket(DatagramPacket datagramPacket){
  51. try {
  52. datagramSocket.send(datagramPacket);
  53. lastSentPacket = datagramPacket;
  54. lastSentTime = System.currentTimeMillis();
  55. } catch (IOException e) {
  56. e.printStackTrace();
  57. }
  58. }
  59. public void callReceiver(DatagramPacket datagramPacket){
  60. packetReceiver.onPacket(this, datagramPacket, datagramPacket.getAddress(),
  61. new String(datagramPacket.getData(), 0, datagramPacket.getLength()), this.getType());
  62. }
  63. @Override
  64. public Type getType() {
  65. return this.type;
  66. }
  67. @Override
  68. public void sendMessage(InetAddress inetAddress, String message) {
  69. byte[] messageBytes = message.getBytes();
  70. DatagramPacket datagramPacket = new DatagramPacket(messageBytes, messageBytes.length, inetAddress, port);
  71. sendPacket(datagramPacket);
  72. }
  73. @Override
  74. public long getLastReceivedTime() {
  75. return System.currentTimeMillis() - lastReceivedTime;
  76. }
  77. @Override
  78. public long getLastSentTime() {
  79. return System.currentTimeMillis() - lastSentTime;
  80. }
  81. }
hsvhsicv

hsvhsicv1#

在此服务器例程中:

  1. @Override
  2. public void sendMessage(InetAddress inetAddress, String message) {
  3. byte[] messageBytes = message.getBytes();
  4. DatagramPacket datagramPacket = new DatagramPacket(messageBytes, messageBytes.length, inetAddress, port);
  5. sendPacket(datagramPacket);
  6. }

我能在范围中看到的唯一“端口”是示例成员变量

  1. private int port;

服务器正在侦听的端口。所以,您将这个数据报发送给自己(假设客户端和服务器的ip地址相同)。
您应该从接收到的数据报中提取源地址和端口。

fzsnzjdm

fzsnzjdm2#

我已经解决了我的问题,并将公布答案供公众参考。
两个端点都在同一主机上、同一端口上侦听。
他们无法区分彼此,因此引起了很大的混乱。客户端与服务器在同一端口上侦听数据包。此外,客户端在与服务器相同的端口上发送数据包,客户端在该端口上侦听数据包。
因此,问题的解决方法只是为每个示例选择不同的侦听端口。
例如,客户端正在侦听端口31254,服务器正在侦听2132。客户端将数据包发送到2132,服务器发送到31254。
正如伊吉猜测的那样。
非常感谢你们。

相关问题