所以我正在研究java udp客户端和服务器,但客户端不断接收不正确的数据或双倍。这是我的代码。
public class Server extends Thread {
static int playerx = 50;
static int playery = 50;
private DatagramSocket socket;
Player p;
Vector<Player> connectedPlayers = new Vector<Player>();
public static enum PacketTypes {
INVALID(-1), LOGIN(00), DISCONNECT(01), MOVE(02);
private int packetId;
private PacketTypes(int packetId) {
this.packetId = packetId;
}
public int getId() {
return packetId;
}
}
public byte packetId;
public static void main(String[] args){
Server s = new Server();
s.start();
}
public Server() {
try {
this.socket = new DatagramSocket(1331);
} catch (SocketException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
socket.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
this.parsePacket(packet.getData(), packet.getAddress(), packet.getPort());
}
}
private void parsePacket(byte[] data, InetAddress address, int port) {
String message = new String(data).trim();
//System.out.println("Data: "+message);
if(message.startsWith("00")){
System.out.println("User Connected: "+message.substring(2, message.length()));
p = new Player(50, 50, 1);
sendData(("00"+p.x+"").getBytes(), address, port);
sendData(("00"+p.y+"").getBytes(), address, port);
System.out.println("LOGIN: "+ p.x+" || "+p.y);
return;
}
if(message.startsWith("02")){
//if(message.substring(2, message.length())=="R"){
p.x+=1;
System.out.println(p.x+" has increased again!");
sendData(("02"+p.x+"").getBytes(), address, port);
sendData(("02"+p.y+"").getBytes(), address, port);
System.out.println("MOVE: "+p.x+" || "+p.y);
//}
return;
}
}
public void sendData(byte[] data, InetAddress ipAddress, int port) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, port);
try {
this.socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
游戏客户端是:
public class Game extends BasicGame{
Client c;
public Game(String title) {
super(title);
}
public static void main(String[] args){
try {
AppGameContainer app = new AppGameContainer(new Game("NET-CODE"));
app.setDisplayMode(800, 600, false);
app.setTargetFrameRate(60);
app.start();
} catch (SlickException e) {
e.printStackTrace();
}
}
public boolean isCon = false;
public int x;
public int y;
@Override
public void render(GameContainer gc, Graphics g) throws SlickException {
if(isCon){
g.fillRect(x, y, 32, 32);
}
}
@Override
public void init(GameContainer gc) throws SlickException {
c = new Client("127.0.0.1", this);
c.start();
c.sendData("00James".getBytes());
}
@Override
public void update(GameContainer gc, int delta) throws SlickException {
Input i = gc.getInput();
if(i.isKeyDown(Input.KEY_D)){
c.sendData("02R".getBytes());
}
}
}
,客户端线程是:
public class Client extends Thread{
private InetAddress ipAddress;
private DatagramSocket socket;
private Game game;
public Client(String ipAddress, Game game) {
try {
this.socket = new DatagramSocket();
this.ipAddress = InetAddress.getByName(ipAddress);
this.game = game;
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
byte[] data = new byte[1024];
DatagramPacket packet = new DatagramPacket(data, data.length);
try {
socket.receive(packet);
} catch (IOException e) {
e.printStackTrace();
}
this.parsePacket(packet.getData(), packet.getAddress(), packet.getPort());
}
}
int cycle = 0;
private void parsePacket(byte[] data, InetAddress address, int port) {
String message = new String(data).trim();
if(message.startsWith("02")){
if(cycle == 0){
game.x = Integer.parseInt(message.substring(2, message.length()));
System.out.println(" MOVE Data X: "+message);
cycle++;
}
if(cycle == 1){
game.y = Integer.parseInt(message.substring(2, message.length()));
System.out.println("MOVE Data Y: "+message);
cycle=0;
}
}
if(message.startsWith("00")){
if(cycle == 0){
game.x = Integer.parseInt(message.substring(2, message.length()));
System.out.println("LOGIN Data X: "+message);
cycle++;
}
if(cycle == 1){
game.y = Integer.parseInt(message.substring(2, message.length()));
System.out.println("LOGIN Data Y: "+message);
cycle=0;
game.isCon = true;
}
}
}
public void sendData(byte[] data) {
DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 1331);
try {
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
因此,当服务器在移动时发送更新的播放器的x和y线时,它会发送默认的x和y,然后发送更新的x和y。因此,当我按D向右移动时,客户端会得到一个响应(打印到控制台): 51,50(在x轴上递增) 50,50(默认) 并且它会继续这样做,所以玩家在屏幕上画画根本不会移动!
答案 0 :(得分:0)
错误,这是UDP,您可以多次接收任何数据报。你可能在某个地方有一个错误,没有显示,导致你发送两次,但即使修复了你仍然可以得到重复,你需要防御它。序号是一个好的开始。
然而还有另一个问题:
this.parsePacket(packet.getData(), packet.getAddress(), packet.getPort());
private void parsePacket(byte[] data, InetAddress address, int port)
此方法无法使用参数,因为您还需要传递数据包长度。我会改变它只是接受DatagramPacket
本身作为唯一参数,但在其中需要注意getData(),
getLength()
,甚至可能getOffset()
,以及源地址的东西。