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

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

所以在过去的几天里,我一直在开发一个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;
}

}
hsvhsicv

hsvhsicv1#

在此服务器例程中:

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

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

private int port;

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

fzsnzjdm

fzsnzjdm2#

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

相关问题