Java sockets游戏服务器调整

Java sockets游戏服务器调整,java,sockets,Java,Sockets,我正在制作一个多人游戏,我正在为服务器使用java套接字,服务器运行得很好,但我认为需要对解析/处理请求的方式进行一些调整 我想知道是否有更好的方法来解析请求,而不是像我现在这样用(,)逗号分隔输入行 客户端和服务器之间发送的数据是否应该以某种方式加密?只是一个小的加密来混淆嗅探器眼睛上的请求。最好的方法是什么 关于线程安全,Collections.synchronizedList和synchronized块在迭代中可以吗?还是有更好/更干净的方法 最后,是否有java sockes库可以完成上

我正在制作一个多人游戏,我正在为服务器使用java套接字,服务器运行得很好,但我认为需要对解析/处理请求的方式进行一些调整

  • 我想知道是否有更好的方法来解析请求,而不是像我现在这样用(,)逗号分隔输入行

  • 客户端和服务器之间发送的数据是否应该以某种方式加密?只是一个小的加密来混淆嗅探器眼睛上的请求。最好的方法是什么

  • 关于线程安全,Collections.synchronizedList和synchronized块在迭代中可以吗?还是有更好/更干净的方法

  • 最后,是否有java sockes库可以完成上述所有工作?如果是这样的话,我应该使用它,或者这对于一个小型的JavaSokets游戏服务器来说是一种过度使用

  • 还有什么我需要改进的吗

  • 谢谢:)

    下面是我的服务器的基本结构

    public class Servidor extends Thread {
    
        private ServerSocket serverSocket;
        public static boolean LISTENING = true;
        private final List<Client> clients = Collections.synchronizedList(new ArrayList<Client>());
        private final List<Game> games = Collections.synchronizedList(new ArrayList<Game>());
    
        public Servidor() {
            try {
                serverSocket = new ServerSocket(SERVER_PORT);
            } catch (IOException e) {
                Log.add("error starting server: " + e);
            }
        }
    
        @Override
        public void run() {
    
            // Wait for players to connect
            while (LISTENING) {
                try {
                    Client c = new Client(serverSocket.accept());
                    clients.add(c);
                    c.start();
                } catch (IOException e) {}
            }
        }
    
    
    
        class Client extends Thread {
    
            private Socket socket;
            private PrintWriter out;
            private BufferedReader in;
            private boolean loggedin;
            private Player player;
            private Game game;
    
    
            public Cliente(Socket sock) {
                socket = sock;
                try {
                    out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8")), true);
                    in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
                } catch (IOException e) {
                    Log.add("error connecting to player!");
                }
            }
    
    
            /* Send to this player */
            public void send(String s) {
                out.println(s);
            }
    
            /* Send to all players on the server */
            public void boardcast(String s) {
                synchronized (clients) {
                    for (Client c : clients) {
                        c.send(s);
                    }
                }
            }
    
            /* Get player by ID */
            private Player getPlayerByID(int playerID) {
                synchronized (clients) {
                    for (Client c : clients) {
                        if (c.player != null) {
                            if (c.player.getID() == playerID) {
                                return c.player;
                            }
                        }
                    }
                }
                return null;
            }
    
            /* Split inputLine */
            private String[] splitInput(String input, int argsNumber) {
                String[] args = null;
    
                try {
                    args = input.split(",", -1);
    
                    if (args.length != argsNumber) {
                        args = null;
                    }
                } catch (Exception ex) {
                    Log.add("error splitting input");
                } finally {
                    return args;
                }
            }
    
            @Override
            public void run() {
                char cmd;
                String inputLine, outputLine;
                String[] args;
    
                try {
                    loop:
                    while ((inputLine = in.readLine()) != null) {
    
                        // check if inputLine have 2 chars (CMD_TYPE:)
                        if (inputLine.length() < 2) {
                            kickPlayer();
                            break loop;
                        }
    
                        // get CMD
                        cmd = inputLine.charAt(0);
    
                        // remove (CMD_TYPE:) from inputLine
                        inputLine = inputLine.substring(2);
    
                        // check e player is logged (L:username,password)
                        if (!loggedin) {
    
                            // check if the input string have 2 arguments
                            if ((args = splitInput(inputLine, 2)) == null) {
                                kickPlayer();
                                break loop;
                            }else{
    
                                // ... TESTE LOGIN ON DATABASE ...
    
                                // set player data
                                player = new Player(query.getInt("player_id"), query.getString("username"), query.getInt("level"))
    
                            }
    
                        }else{
                            // Commands
                            switch (cmd) {
    
                                // P:CARD_ID,TARGET_ID eg:(P:5:3)
                                case CMD_PLAY: 
    
                                    // check if the input string have 2 arguments
                                    if ((args = splitInput(inputLine, 2)) == null) {
                                        kickPlayer();
                                        break loop;
                                    } else {
    
                                        // ... VALIDATE OTHER PARAMETERS ...
    
                                        // update game
                                        game.addCard(args[0], args[0]);
    
                                        // update players
                                        boardcast(CMD_PLAY + ":" + player.getID+ "," + game.LastCard());
    
                                    }
    
                                    break;
    
                                    // ... TEST OTHER COMMANDS ...
    
                                default:
                                    Log.add("invalid command";
                                    break loop;
                            }
                        }
                    }
    
                } catch (IOException e) {
                        Log.add("connection lost";
                } finally {
                        removeClient();
                }
            }
        }
    }
    
    公共类服务扩展线程{
    私有服务器套接字服务器套接字;
    公共静态布尔侦听=true;
    私有最终列表客户端=Collections.synchronizedList(新的ArrayList());
    private final List games=Collections.synchronizedList(新的ArrayList());
    公共服务商(){
    试一试{
    serverSocket=新的serverSocket(服务器端口);
    }捕获(IOE异常){
    添加(“启动服务器时出错:+e”);
    }
    }
    @凌驾
    公开募捐{
    //等待玩家连接
    边听{
    试一试{
    客户端c=新客户端(serverSocket.accept());
    添加(c);
    c、 start();
    }捕获(IOE){}
    }
    }
    类客户端扩展线程{
    专用插座;
    私人打印输出;
    中的私有缓冲区读取器;
    私有布尔loggedin;
    私人玩家;
    私人游戏;
    公共客户(插座插座){
    插座=插座;
    试一试{
    out=新的PrintWriter(新的BufferedWriter(新的OutputStreamWriter(socket.getOutputStream(),“UTF-8”)),true);
    in=新的BufferedReader(新的InputStreamReader(socket.getInputStream(),“UTF-8”);
    }捕获(IOE异常){
    添加(“连接到播放器时出错!”);
    }
    }
    /*发送给这个玩家*/
    公共无效发送(字符串s){
    out.println(s);
    }
    /*发送给服务器上的所有玩家*/
    公共空白广播(字符串s){
    已同步(客户端){
    用于(客户c:客户){
    c、 发送(s);
    }
    }
    }
    /*通过ID获取玩家*/
    私人玩家GetPlayerByd(int-playerID){
    已同步(客户端){
    用于(客户c:客户){
    如果(c.player!=null){
    如果(c.player.getID()==playerID){
    返回c.player;
    }
    }
    }
    }
    返回null;
    }
    /*分割输入线*/
    私有字符串[]拆分输入(字符串输入,int argsNumber){
    字符串[]args=null;
    试一试{
    args=input.split(“,”,-1);
    if(args.length!=argsNumber){
    args=null;
    }
    }捕获(例外情况除外){
    添加(“错误拆分输入”);
    }最后{
    返回args;
    }
    }
    @凌驾
    公开募捐{
    char-cmd;
    字符串输入行、输出行;
    字符串[]args;
    试一试{
    循环:
    而((inputLine=in.readLine())!=null){
    //检查inputLine是否有2个字符(CMD\u类型:)
    if(inputLine.length()<2){
    kickPlayer();
    断环;
    }
    //获取命令
    cmd=inputLine.charAt(0);
    //从输入行中删除(CMD_TYPE:)
    inputLine=inputLine.子字符串(2);
    //检查e播放器是否已登录(L:用户名、密码)
    如果(!loggedin){
    //检查输入字符串是否有2个参数
    if((args=splitInput(inputLine,2))==null){
    kickPlayer();
    断环;
    }否则{
    //…测试登录数据库。。。
    //设置播放器数据
    player=新玩家(query.getInt(“玩家id”)、query.getString(“用户名”)、query.getInt(“级别”))
    }
    }否则{
    //命令
    开关(cmd){
    //卡片ID,目标ID,例如:(P:5:3)
    案例CMD_播放:
    //检查输入字符串是否有2个参数
    if((args=splitInput(inputLine,2))==null){
    kickPlayer();
    断环;
    }否则{
    //…验证其他参数。。。
    //更新游戏
    game.addCard(args[0],args[0]);
    //更新玩家
    boardcast(CMD_PLAY+“:“+player.getID+”,“+game.LastCard());
    }
    打破
    //…测试其他命令。。。
    违约
    
    class ClientHandler
    {
       public void run()
       {
          while(isConnected())
             messageRouter.handleMessage(getNextMessage());
       }
    }
    
    interface MessageHandler
    {
       public boolean canHandle(Message m);
       public void handleMessage(Message m);
    }
    
    
    class MessageRouter
    {
       private List<MessageHandler> handlers;
    
       public void handleMessage(Message msg)
       {
          for(MessageHandler m : handlers)
          {
             if(m.canHandle(msg))
             {
                m.handle(msg);
                return;
             }
          }
          throw UnsupportedMessage();
       }
    }