本地 DatagramSocket(Server) 正在向自身发送数据包
Local DatagramSocket(Server) is sending packets to itself
因此,过去几天我一直在研究 UDP API,我尝试先在本地计算机上测试 API。
所以我在不同的线程中创建了一个服务器和一个客户端实例。
当我用客户端向服务器发送数据包时,服务器收到了这些数据包,
但是当我试图从服务器向客户端发送数据包时,服务器只是将其消息发送给自己并响应它收到的数据包,最终陷入无限消息发送循环。
以下是当前代码的部分内容:
客户:
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猜测的那样。
非常感谢大家
因此,过去几天我一直在研究 UDP API,我尝试先在本地计算机上测试 API。
所以我在不同的线程中创建了一个服务器和一个客户端实例。
当我用客户端向服务器发送数据包时,服务器收到了这些数据包, 但是当我试图从服务器向客户端发送数据包时,服务器只是将其消息发送给自己并响应它收到的数据包,最终陷入无限消息发送循环。
以下是当前代码的部分内容:
客户:
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猜测的那样。
非常感谢大家