简体   繁体   English

是否可以将小程序用作Java的服务器?

[英]Is it possible to use an applet as a server with Java?

I'm just getting into networking and I'm quite confused about how I can use a server from a server hosting company for a game. 我刚刚进入网络,对于如何使用服务器托管公司的服务器进行游戏感到非常困惑。 At the moment, the program allows a user to host the server from their computer and it works to some degree. 目前,该程序允许用户从其计算机托管服务器,并且在一定程度上可以正常工作。 The only problem is that when my friends connect to the game from other states their ping is super high and they lag horribly. 唯一的问题是,当我的朋友从其他国家/地区连接到游戏时,他们的ping值非常高,并且非常落后。

I'm now using a site that gives out free web hosting space. 我现在正在使用一个提供免费网络托管空间的网站。 I've believe I've jumped through most of the permission hoops that I need in order to use sockets and the applet works just like it does while running on my computer. 我相信我已经跳过了使用套接字所需的大多数权限限制,并且applet的运行方式与在计算机上运行时的运行方式一样。

Below is an excerpt from the Game class. 以下是Game类的摘录。 If I use InetAddress.getLocalHost().getHostAddress() to get the IP, it gets the IP from the user who is using the client and makes them the server host. 如果我使用InetAddress.getLocalHost()。getHostAddress()来获取IP,它将从使用客户端的用户那里获取IP,并将其作为服务器主机。 This works, but it doesn't solve my problem of lag. 这行得通,但是并不能解决我的滞后问题。

    Game.java

    public synchronized void start() {
    running = true;

    thread = new Thread(this, NAME + "_main");
    thread.start();

    if (JOptionPane.showConfirmDialog(this, "Do you want to run the server") == 0) {
        socketServer = new GameServer(this);
        socketServer.start();
    }


    this.ipAddress = "31.170.163.198";
    //this.ipAddress = InetAddress.getByName(ipAddress).toString();

    System.out.println("IP: " + this.ipAddress);
    socketClient = new GameClient(this, this.ipAddress);//Inet4Address.getLocalHost().getHostAddress());    

    try {
        Player.setIp(Inet4Address.getLocalHost().getHostAddress());
    } catch (UnknownHostException e) {
        e.printStackTrace();
    }
    socketClient.start();
}

I want the server that contains the jar to host the server. 我希望包含jar的服务器托管该服务器。 We all ping test each other and we mostly all get timed out, however, when we ping the server's ip we all get decent ping. 我们所有人都相互ping测试,并且大多数人都超时了,但是,当我们ping服务器的ip时,我们都得到了不错的ping。 When I enter the Server's IP (I find this info in the control panel) manually the server/client fail to make a connection. 当我手动输入服务器的IP(在控制面板中找到此信息)时,服务器/客户端无法建立连接。 I've tried using both the website IP and the server IP that are provided. 我尝试使用提供的网站IP和服务器IP。 I've also tried using the applet.getCodeBase().getHost() in order to retrieve the IP from the server but that IP failed to send/receive data as well. 我还尝试使用applet.getCodeBase()。getHost()以便从服务器检索IP,但是该IP也无法发送/接收数据。

Is what I'm trying to do possible? 我想做的事可能吗? Is the server blocking me from using it in that way? 服务器是否阻止了我以这种方式使用它? Do I need to rewrite the whole program and look into java servlets to achieve my goal? 我是否需要重写整个程序并查看java servlet以实现我的目标?

I apologize if the question is silly. 我很抱歉这个问题很愚蠢。 I've been working on this for the past 3-4 days with very little progress. 在过去的3-4天中,我一直在为此工作,但进展甚微。 I've searched around a bit on using a server in this manner and I've found very little on the topic. 我已经以这种方式使用服务器进行了一些搜索,但在该主题上我发现得很少。

Below are some excerpts from other relevant pieces of code. 以下是其他相关代码段的摘录。

GameClient.java

package fraccas.java2dgame.net;


public class GameClient extends Thread {

private InetAddress ipAddress;
private DatagramSocket socket;
private Game game;
public long lastPing = 0;
public static int ping = 0;

public GameClient(Game game, String ipAddress) {
    this.game = game;
    try {
        this.socket = new DatagramSocket();
        this.ipAddress = InetAddress.getByName(ipAddress);
        System.out.println("IP: " + InetAddress.getByName(ipAddress));
    } 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);
            if (packet != null)
            {
                long current = System.currentTimeMillis();
                ping = (int) (current - lastPing);
                lastPing = current;
            }
        } 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();
    PacketTypes type = Packet.lookupPacket(message.substring(0, 2));
    Packet packet = null;
    switch (type) {
    default:
    case INVALID:
        break;
    case LOGIN:
        packet = new Packet00Login(data);
        handleLogin((Packet00Login) packet, address, port);
        break;
    case DISCONNECT:
        packet = new Packet01Disconnect(data);
        System.out.println("[" + address.getHostAddress() + ":" + port + "] "
                + ((Packet01Disconnect) packet).getUsername() + " has left the world...");
        game.level.removePlayerMP(((Packet01Disconnect) packet).getUsername());
        break;
    case MOVE:
        packet = new Packet02Move(data);
        handleMove((Packet02Move) packet);
    }
}

public void sendData(byte[] data) {
    //if (!game.isApplet) {
        DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, 3333);
        try {
            socket.send(packet);
        } catch (IOException e) {
            e.printStackTrace();
        }
   //}
}

private void handleLogin(Packet00Login packet, InetAddress address, int port) {
    System.out.println("[" + address.getHostAddress() + ":" + port + "] " + packet.getUsername()
            + " has joined the game...");
    PlayerMP player = new PlayerMP(game.level, packet.getX(), packet.getY(), packet.getUsername(), address, port);
    game.level.addEntity(player);
}

private void handleMove(Packet02Move packet) {
    this.game.level.movePlayer(packet.getUsername(), packet.getX(), packet.getY(), packet.getNumSteps(),
            packet.isMoving(), packet.getMovingDir());
}

} }

GameServer.java

package fraccas.java2dgame.net;


public class GameServer extends Thread {

private DatagramSocket socket;
private Game game;
private List<PlayerMP> connectedPlayers = new ArrayList<PlayerMP>();

public GameServer(Game game) {
    this.game = game;
    try {
        this.socket = new DatagramSocket(3333);
    } 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();
    PacketTypes type = Packet.lookupPacket(message.substring(0, 2));
    Packet packet = null;
    switch (type) {
    default:
    case INVALID:
        break;
    case LOGIN:
        packet = new Packet00Login(data);
        System.out.println("[" + address.getHostAddress() + ":" + port + "] "
                + ((Packet00Login) packet).getUsername() + " has connected...");
        PlayerMP player = new PlayerMP(game.level, 100, 100, ((Packet00Login) packet).getUsername(), address, port);
        this.addConnection(player, (Packet00Login) packet);
        break;
    case DISCONNECT:
        packet = new Packet01Disconnect(data);
        System.out.println("[" + address.getHostAddress() + ":" + port + "] "
                + ((Packet01Disconnect) packet).getUsername() + " has left...");
        this.removeConnection((Packet01Disconnect) packet);
        break;
    case MOVE:
        packet = new Packet02Move(data);
        this.handleMove(((Packet02Move) packet));
    }
}

public void addConnection(PlayerMP player, Packet00Login packet) {
    boolean alreadyConnected = false;
    for (PlayerMP p : this.connectedPlayers) {
        if (player.getUsername().equalsIgnoreCase(p.getUsername())) {
            if (p.ipAddress == null) {
                p.ipAddress = player.ipAddress;
            }
            if (p.port == -1) {
                p.port = player.port;
            }
            alreadyConnected = true;
        } else {
            // relay to the current connected player that there is a new
            // player
            sendData(packet.getData(), p.ipAddress, p.port);

            // relay to the new player that the currently connect player
            // exists
            //packet = new Packet00Login(p.getUsername(), p.x, p.y);
            Packet00Login packetNew = new Packet00Login(p.getUsername(), p.x, p.y);
            sendData(packetNew.getData(), player.ipAddress, player.port);
        }
    }
    if (!alreadyConnected) {
        this.connectedPlayers.add(player);
    }
}

public void removeConnection(Packet01Disconnect packet) {
    this.connectedPlayers.remove(getPlayerMPIndex(packet.getUsername()));
    packet.writeData(this);
}

public PlayerMP getPlayerMP(String username) {
    for (PlayerMP player : this.connectedPlayers) {
        if (player.getUsername().equals(username)) {
            return player;
        }
    }
    return null;
}

public int getPlayerMPIndex(String username) {
    int index = 0;
    for (PlayerMP player : this.connectedPlayers) {
        if (player.getUsername().equals(username)) {
            break;
        }
        index++;
    }
    return index;
}

public void sendData(byte[] data, InetAddress ipAddress, int port) {
    //if (!game.isApplet) {

        DatagramPacket packet = new DatagramPacket(data, data.length, ipAddress, port);
        try {
            this.socket.send(packet);
        } catch (IOException e) {
            e.printStackTrace();
        }
    //}
}

public void sendDataToAllClients(byte[] data) {
    for (PlayerMP p : connectedPlayers) {
        sendData(data, p.ipAddress, p.port);
    }
}

private void handleMove(Packet02Move packet) {
    if (getPlayerMP(packet.getUsername()) != null) {
        int index = getPlayerMPIndex(packet.getUsername());
        PlayerMP player = this.connectedPlayers.get(index);
        player.x = packet.getX();
        player.y = packet.getY();
        player.setMoving(packet.isMoving());
        player.setMovingDir(packet.getMovingDir());
        player.setNumSteps(packet.getNumSteps());
        packet.writeData(this);
    }
}

The applet does not have any errors in the console at the moment. 该小程序目前在控制台中没有任何错误。 It simply does not send/receive the data. 它只是不发送/接收数据。

http://critterisland.bugs3.com/public_html/index.html (Applet Link) http://gyazo.com/a91401545b1a741f2b9fc86471bd5762 (Image of Applet) http://critterisland.bugs3.com/public_html/index.html(Applet链接) http://gyazo.com/a91401545b1a741f2b9fc86471bd5762 (Applet的图片)

Thanks for you time, Fraccas 感谢您的时间,Fraccas

The problem is that you're using a web host which is only able to provide the files to users as opposed to actually being able to run the software you've created. 问题是您使用的是Web主机,该主机只能向用户提供文件,而不是实际能够运行您创建的软件。

To run your software independently in the way you're wanting, your easiest option is to rent a virtual private server (VPS) which is located appropriately for your users. 要以所需的方式独立运行软件,最简单的选择是租用适合用户的虚拟专用服务器(VPS)。 However, you'll need to be able to do some basic configuration on the VPS (such as install Java), and then run your server as a console application. 但是,您将需要能够在VPS上进行一些基本配置(例如安装Java),然后将服务器作为控制台应用程序运行。

Not much code needs to be changed to get it working. 无需更改太多代码即可使其工作。 You could use the same jar file for both the server and the client by adding a command line argument which only starts the server (ie "-server"). 通过添加仅启动服务器的命令行参数(即“ -server”),可以为服务器和客户端使用相同的jar文件。 From the server computer/VPS you would then start the server by running "java -jar CritterIslandTest.jar -server" which then only starts the server and handles communication. 然后,从服务器计算机/ VPS运行“ java -jar CritterIslandTest.jar -server”启动服务器,然后仅启动服务器并处理通信。 If the command line argument is not found you can then continue with the GUI logic. 如果找不到命令行参数,则可以继续使用GUI逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM