Java UDP客户端/服务器数据报问题 - NAT - OSX 10.9

时间:2013-12-17 06:43:30

标签: java sockets udp nat datagram

我最近开始创建一个2D侧滚动游戏,仅使用Mac OSX Mavericks的java 7库,当我进入多人游戏时,我能够为我的游戏创建客户端和服务器处理程序,并且它们在客户端将数据发送到'localhost'但是当我使用我的外部IP时,服务器永远不会收到数据,我认为客户端的问题是当客户端被告知发送到'localhost'而不是我的外部IP时它是有效的,我有端口转发服务器的端口和本地IP,我的Mac的防火墙被禁用。在Java 7或Mac上是否存在UDP数据报套接字问题?

ClientHandler.java

package com.diedericksclan.main.network;

import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;

import com.diedericksclan.main.gui.*;
import com.diedericksclan.main.network.handling.Packet;
import com.diedericksclan.main.network.handling.PacketDisconnect;
import com.diedericksclan.main.network.handling.PacketLogin;
import com.diedericksclan.main.network.handling.PacketMovement;
import com.diedericksclan.main.network.handling.PlayerMP;
import com.diedericksclan.main.network.handling.Packet.PacketType;

public class ClientHandler extends Thread {

    private InetAddress IPaddress;
    private DatagramSocket dataSocket;
    private DisplayHandler game;
    public static boolean connected = false;
    private int serverPort = 2048;
    private int port;

    public ClientHandler(DisplayHandler game, String ipaddress, int serverPort) {
        this.game = game;
        this.serverPort = serverPort;
        try {
            this.dataSocket = new DatagramSocket();
            this.IPaddress = InetAddress.getByName(ipaddress);
            this.port = dataSocket.getPort();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

     public void callHost()
     { 
          this.sendByteData("-3".getBytes());
     } 

    public void run() {
        while (true) {
            byte[] gameData = new byte[8192];
            DatagramPacket in = new DatagramPacket(gameData, gameData.length);
            try {
                this.dataSocket.receive(in);
            } catch (IOException e) {
                e.printStackTrace();
            }
            this.parsePacket(in.getData(), in.getAddress(), in.getPort());
        }
    }

    private void parsePacket(byte[] data, InetAddress address, int port) {
        String dataString = new String(data).trim();
        System.out.println("Server[" + address.getHostAddress() + ":" + port + "] Data Recived: " + dataString);
        PacketType type = Packet.lookupPacket(dataString.substring(0, 2));
        Packet packet = null;
        switch (type) {
        default:
            break;
        case CONNECT:
            this.connected = true;
            break;
        case SHUTDOWN:
            this.game.setCurrentDisplay(this.game.dispMMenu);
            this.game.dispGame.getEntities().clear();
            this.connected = false;
            break;
        case INVALID:
            break;
        case LOGIN:
            packet = new PacketLogin(data);
            System.out.println("[" + address.getHostAddress() + ":" + Integer.toString(port) + "] " + ((PacketLogin)packet).getUsername() + " - Has just logged onto the server!");
            PlayerMP playerLogin = new PlayerMP(game, ((PacketLogin)packet).getUsername(), address, port);
            this.game.dispGame.getEntities().add(playerLogin);
            break;
        case DISCONNECT:
            packet = new PacketDisconnect(data);
            System.out.println("[" + address.getHostAddress() + ":" + Integer.toString(port) + "] " + ((PacketDisconnect)packet).getUsername() + " - Has just disconnected from the server!");
            int index = this.game.dispGame.getEntityIndex(((PacketDisconnect)packet).getUsername());
            this.game.dispGame.removePlayer(((PacketDisconnect)packet).getUsername());
            if(this.game.dispGame.getEntities().get(index).getUsername() == ((PacketDisconnect)packet).getUsername()) {
                this.game.dispGame.removePlayer(((PacketDisconnect)packet).getUsername());
            }
            this.connected = false;
            break;
        case MOVEMENT:
            packet = new PacketMovement(data);
            for(PlayerMP p : this.game.dispGame.getEntities()) {
                if(p.getUsername().equals(((PacketMovement)packet).getUsername())) {
                    p.setX(((PacketMovement)packet).getX());
                }
            }
            break;
        }
    }

    public void sendByteData(byte[] data) {
        DatagramPacket out = new DatagramPacket(data, data.length, this.IPaddress, this.serverPort);
        try {
            this.dataSocket.send(out);
            System.out.println("Sending byte[] data to ServerHandler(" + out.getAddress().getHostAddress() + ":" + out.getPort() + ")   From: " + InetAddress.getByName("localhost").getHostAddress() + ":" + this.dataSocket.getLocalPort());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ServerHandler.java

package com.diedericksclan.main.network;

import java.io.IOException;
import java.net.*;
import java.util.*;
import com.diedericksclan.main.gui.*;
import com.diedericksclan.main.network.handling.*;
import com.diedericksclan.main.network.handling.Packet.*;
import com.diedericksclan.main.network.handling.*;
import com.diedericksclan.main.recource.*;

public class ServerHandler extends Thread {

    private DatagramSocket dataSocket;
    private DisplayHandler game;
    public List<PlayerMP> players = new ArrayList<PlayerMP>();

    public ServerHandler(DisplayHandler game, int port) {
        this.game = game;
        try {
            this.dataSocket = new DatagramSocket(port, InetAddress.getByName("192.168.1.2"));
            System.out.println(this.dataSocket.getInetAddress().getHostAddress() + ":" + port + "    ===    " + this.dataSocket.getLocalAddress().getHostAddress() + ":" + port);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        System.out.println("made");
        while (true) {
            byte[] data = new byte[8192];
            DatagramPacket packet = new DatagramPacket(data, data.length);
            try {
                dataSocket.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 dataString = new String(data).trim();
        PacketType type = Packet.lookupPacket(dataString.substring(0, 2));
        Packet packet = null;
        switch (type) {
        default:
            break;
        case CONNECT:
            System.out.println("Here");
            this.sendByteData("-3".getBytes(), address, port);
            break;
        case INVALID:
            break;
        case LOGIN:
            packet = new PacketLogin(data);
            System.out.println("[" + address.getHostAddress() + ":" + port + "] " + ((PacketLogin)packet).getUsername() + " - Has just joined the server!");
            PlayerMP playerLogin = new PlayerMP(game, ((PacketLogin)packet).getUsername(), address, port);
            this.addConnection(playerLogin, (PacketLogin)packet);
            break;
        case DISCONNECT:
            packet = new PacketDisconnect(data);
            System.out.println("[" + address.getHostAddress() + ":" + port + "] " + ((PacketDisconnect)packet).getUsername() + " - Has just left the server!");
            this.removeConnection((PacketDisconnect)packet);
            break;
        case MOVEMENT:
            System.out.println("Here");
            packet = new PacketMovement(data);
            this.players.get(this.getPlayerIndex(((PacketMovement)packet).getUsername())).setX(((PacketMovement)packet).getX());
            this.sendByteDataToAll(packet.getData(), address, port);
            break;
        }
    }

    public void addConnection(PlayerMP player, PacketLogin login) {
        boolean alreadyOn = false;
        for(PlayerMP p : players) {
            if(player.getUsername().equals(p.getUsername())) {
                if(p.IPaddress == null) {
                    p.IPaddress = player.IPaddress;
                }
                if(p.port == -1) {
                    p.port = player.port;
                }
                alreadyOn = true;
            } else if(!player.getUsername().equals(p.getUsername())) {
                this.sendByteDataToAll(login.getData(), player.IPaddress, player.port);
                login = new PacketLogin(p.getUsername());
                this.sendByteData(login.getData(), player.IPaddress, player.port);
            } else {
                System.out.println("Error whilst trying to send data to clients");
                this.sendByteData(login.getData(), p.IPaddress, p.port);
            }
        }
        if(!alreadyOn) {
            this.players.add(player);
        }
    }

    public void removeConnection(PacketDisconnect packet) {
        this.players.remove(this.getPlayerIndex(packet.getUsername()));
        packet.writeData(this);
    }

    public PlayerMP getPlayer(String username) {
        for(PlayerMP p : players) {
            if (p.getUsername().equals(username)) {
                return p;
            }
        }
        return null;
    }

    public int getPlayerIndex(String username) {
        int index = 0;
        for(PlayerMP p : players) {
            if (p.getUsername().equals(username)) {
                break;
            }
            index++;
        }
        return index;
    }

    public void sendByteData(byte[] data, InetAddress IPaddress, int port) {
        if(port != -1) {
            DatagramPacket out = new DatagramPacket(data, data.length, IPaddress, port);
            try {
                this.dataSocket.send(out);
                System.out.println("Sending byte[] data to ClientHandler(" + out.getAddress().getHostAddress() + ":" + out.getPort() + ")");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void sendByteDataToAll(byte[] data) {
        for(PlayerMP p : players) {
            sendByteData(data, p.IPaddress, p.port);
        }
    }

    public void sendByteDataToAll(byte[] data, InetAddress IPaddress, int port) {
        for(PlayerMP p : players) {
            if(p.IPaddress != IPaddress) {
                sendByteData(data, p.IPaddress, p.port);
            } else if(p.port != port) {
                sendByteData(data, p.IPaddress, p.port);
            } else {

            }
        }
    }

    public void close() {
        this.sendByteDataToAll("-2".getBytes()); //Disconnects all players when server is closed
        this.players.clear();
    }
}

DisplayHandler.java(创建客户端和服务器处理程序的位置)

@Override
    public void start() {
        this.shread.start();
        this.soundThread.start();
        if(JOptionPane.showConfirmDialog(this, "Do you want to host a lan server?") == 0) {
            this.server = new ServerHandler(this, 2048); //Creates server if user wants to. Prams: DisplayHandler, int port - the port the server should host on
            this.server.start();
            System.out.println("Done1");
        }
        this.client = new ClientHandler(this, "MYEXTERNALIP", 2048); //Creates Client. Prams: DisplayHandler, String IP - The servers IP, int port - Servers port
        this.client.start();
        this.setCurrentDisplay(dispMMenu);
        this.onOpen();
        this.client.callHost();
        System.out.println("Done");
        //this.sound.addMidi("finalcountdown", "test.mid");
        //this.sound.playMid("finalcountdown", true);
    }

0 个答案:

没有答案