本地 DatagramSocket(Server) 正在向自身发送数据包

Local DatagramSocket(Server) is sending packets to itself

因此,过去几天我一直在研究 UDP API,我尝试先在本地计算机上测试 API。

所以我在不同的线程中创建了一个服务器和一个客户端实例。

当我用客户端向服务器发送数据包时,服务器收到了这些数据包, 但是当我试图从服务器向客户端发送数据包时,服务器只是将其消息发送给自己并响应它收到的数据包,最终陷入无限消息发送循环。

以下是当前代码的部分内容:

Client

Server

客户:

package com.github.sebyplays.jsimpleudp;

import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

public class Client implements ICommunicator{

    @Getter private DatagramSocket datagramSocket;
    private boolean running;
    @Getter @Setter private byte[] buffer = new byte[1024];
    @Getter @Setter private PacketReceiver packetReceiver;
    @Getter @Setter private InetAddress host;
    private Type type = Type.CLIENT;
    @Getter private int port;
    @Getter private DatagramPacket lastReceivedPacket;
    @Getter private DatagramPacket lastSentPacket;
    private long lastReceivedTime = 0;
    private long lastSentTime = 0;

@SneakyThrows
public Client(String host, int port, PacketReceiver packetReceiver) {
    this.packetReceiver = packetReceiver;
    this.port = port;
    this.host = InetAddress.getByName(host);
    this.datagramSocket = new DatagramSocket();
}

@Override
public void start() {
    running = true;
    Thread thread = new Thread("udpclient"){
        @SneakyThrows
        @Override
        public void run() {
            while (running){
                DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length, host, port);
                datagramSocket.receive(datagramPacket);
                lastReceivedPacket = datagramPacket;
                lastReceivedTime = System.currentTimeMillis();
                callReceiver(datagramPacket);
            }
        }
    };
    thread.start();
}

@Override
public void stop() {
    running = false;
    if(!datagramSocket.isClosed()){
        datagramSocket.close();
    }
}

public void sendPacket(DatagramPacket datagramPacket){
    try {
        datagramSocket.send(datagramPacket);
        lastSentPacket = datagramPacket;
        lastSentTime = System.currentTimeMillis();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void callReceiver(DatagramPacket datagramPacket){
    packetReceiver.onPacket(this, datagramPacket, datagramPacket.getAddress(),
            new String(datagramPacket.getData(), 0, datagramPacket.getLength()), this.getType());
}

@Override
public Type getType() {
    return this.type;
}

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

@Override
public long getLastReceivedTime() {
    return System.currentTimeMillis() - lastReceivedTime;
}

@Override
public long getLastSentTime() {
    return System.currentTimeMillis() - lastSentTime;
}

public static void main(String[] args) {
    Client client = new Client("mcsilent.de", 2312, new PacketReceiver() {
        @Override
        public void onPacket(ICommunicator iCommunicator, DatagramPacket datagramPacket, InetAddress source, String packet, Type type) {
            System.out.println(packet);
        }
    });
    client.start();
    Scanner scanner = new Scanner(System.in);
    while (true){
        if(scanner.nextLine().equalsIgnoreCase("r")){
            client.sendMessage(client.getHost(), "InfoRequest::lobby01");
        }
    }
}

}

服务器:

package com.github.sebyplays.jsimpleudp;

import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class Server implements ICommunicator{

@Getter private DatagramSocket datagramSocket;
private boolean running;
@Getter @Setter private byte[] buffer = new byte[1024];
private Type type = Type.SERVER;
private int port;
@Getter @Setter private PacketReceiver packetReceiver;
@Getter private DatagramPacket lastReceivedPacket;
@Getter private DatagramPacket lastSentPacket;
private long lastReceivedTime = 0;
private long lastSentTime = 0;


public Server(int port, PacketReceiver packetReceiver) throws SocketException {
    this.datagramSocket = new DatagramSocket(port);
    this.packetReceiver = packetReceiver;
    this.port = port;
}

public void start(){
    this.running = true;
    Thread thread = new Thread("udpserver"){
        @SneakyThrows
        @Override
        public void run() {
            while (running){
                DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
                datagramSocket.receive(datagramPacket);
                lastReceivedPacket = datagramPacket;
                lastReceivedTime = System.currentTimeMillis();
                callReceiver(datagramPacket);
            }
        }
    };
    thread.start();

}
@Override
public void stop(){
    this.running = false;
    if(!datagramSocket.isClosed()){
        datagramSocket.close();
    }
}

public void sendPacket(DatagramPacket datagramPacket){
    try {
        datagramSocket.send(datagramPacket);
        lastSentPacket = datagramPacket;
        lastSentTime = System.currentTimeMillis();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void callReceiver(DatagramPacket datagramPacket){
    packetReceiver.onPacket(this, datagramPacket, datagramPacket.getAddress(),
            new String(datagramPacket.getData(), 0, datagramPacket.getLength()), this.getType());
}

@Override
public Type getType() {
    return this.type;
}

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

@Override
public long getLastReceivedTime() {
    return System.currentTimeMillis() - lastReceivedTime;
}

@Override
public long getLastSentTime() {
    return System.currentTimeMillis() - lastSentTime;
}

}

在此服务器例程中:

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

我唯一能在范围内看到的'port'是实例成员变量

private int port;

这是服务器侦听的端口。因此,您将此数据报发送给自己(假设客户端和服务器的 IP 地址相同)。

您应该从收到的数据报中提取源地址和端口。

我已经解决了我的问题,并将post答案供public参考。

两个端点都在同一主机上的同一端口上侦听。

他们无法区分彼此,因此引起了很多混乱。 客户端在与服务器相同的端口上监听数据包。 此外,客户端在与服务器相同的端口上发送数据包,客户端在其上侦听。

所以问题修复只是为每个实例选择不同的侦听端口。

例如,客户端正在侦听端口 31254,而服务器正在侦听 2132。 客户端发包到2132,服务端发到31254.

正如iggy猜测的那样。

非常感谢大家