【问题标题】:JAVA - Difficulties with a simple server seeing the clientsJAVA - 简单服务器查看客户端的困难
【发布时间】:2010-10-19 02:07:24
【问题描述】:

我正在尝试制作一个通过 TCP 网络的简单游戏。

服务器在 Server.java 中执行类似的操作来检查连接:

try
{
    server = new ServerSocket(port);
    System.out.println("Server started on port " + port);

    while (true)
    {
        socket = server.accept();
        System.out.println("A new player has joined the server.");
        new Server(socket).start();
    }
}

并在 Player.java 中创建一个新客户端:

socket = new Socket(hostname, port);

现在,这一切正常,但我需要服务器将播放器的实例添加到数组列表中,并能够向所有这些实例发送某些数据。它们都有主要方法,因此一台计算机可以只运行服务器,并通过运行 Player.java 让其他 4 台计算机连接到它。如果 Player 所做的只是创建一个新的套接字,那么服务器应该如何与每个 Player 交互?

【问题讨论】:

  • 播放器在哪里? -- 客户端还是服务器?

标签: java networking sockets tcp


【解决方案1】:

试试这个:

Server client = new Server(socket);
clients.add(client);
client.start();

其中clients 的类型为List<Server>。然后,将sendMessage 方法(或其他)添加到您的Server 类中。那么:

for (Server client : clients) {
    client.sendMessage("...");
}

希望这会有所帮助! (顺便说一句,我将变量称为clientclients 有一个明显的原因。它们实际上是传入客户端的抽象,而不是服务器本身,即使Server 中的代码实际上是用于与所述客户端交互的服务器.)

【讨论】:

    【解决方案2】:

    server.accept() 方法返回Socket 的对象。 Socket类有一个方法getOutputStream(),你可以使用这个流来发送消息。

    【讨论】:

    • 问题是我需要与 Player 类进行交互。不是 Socket 类。你的建议是我让 ArrayList 充满 Sockets 而不是 Players。
    • 是的,这可能就是您需要做的。请记住,客户端创建的 Player 对象在服务器上根本不存在。
    • @Logan:您需要一种将对象序列化为字节流的方法,您可以通过 OutputStream 发送该字节流,然后由 Player 类接收。然后需要将流中的字节反序列化(“重构”)回对象中。
    • 服务器在socket上写消息的时候,会被Player客户端接收到,从而可以执行任意方法(当然需要写逻辑)。此处提供入门信息java.sun.com/docs/books/tutorial/networking/sockets/index.html
    【解决方案3】:

    我不确定我是否理解这个问题。

    accept 调用将为每个连接的客户端产生不同的返回值(通常表示客户端地址和端口),因此您需要存储它们中的每一个。 然后您可以通过套接字进行交互,Sun 有一个pretty good example in its tutorial

    话虽如此,省去很多麻烦,并考虑一下您期望从游戏中获得的性能。如果您 use JMS and ActiveMQ 进行通信而不是自己搞乱套接字,您可以为自己省去很多麻烦并轻松增加可靠性和可扩展性。

    花时间编写游戏,而不是进行低级套接字编程,除非您正在努力学习。

    【讨论】:

    • +1 很高兴看到森林而不是树木!我非常喜欢你的回答,我正在核对我的答案。 :-P
    • 我认为你的回答很好,不要核对它。我花时间构建套接字(我认为学习很重要),但学会了欣赏将头痛推迟到现有框架的能力。我的程序现在更可靠了(例如,通过了笔记本电脑步行测试)
    • 我会更具体地告诉你。游戏是拼字游戏。服务器需要能够通过 TCP 发送有关每个玩家移动的信息。这些信息本质上是位置和这些位置中的字母。我不能发送这个,因为我只能与 Sockets 交互,而不是 Players。
    • 好的,我会带回我的帖子。 :-) 我完全同意你的评论。
    【解决方案4】:

    让我根据我对他的问题的理解做一些名称重构。

    将现有的 Server.java 重命名为 Player.java

    Player player = new Player(socket);
    players.add(player); // server can use this collection for group notification
    .....
    
    
    class Player implements Runnable {
    
       Player(Socket socket) {
            this.socket = socket;
            new Thread(this).start(); // later you may avoid it by using a threadpool executor. 
       }
    
    
       public void run() {
            while(running) {
                // read and write data from client machines.
                // use wait() appropriately
            }
       }
    
    }
    

    如果服务器想要通知所有玩家,它可以调用玩家对象上的一个方法,该方法进一步完成向客户端发送数据所需的工作。

    最后将现有的 Player.java 重命名为 GameLauncher.java。

    在进行了这个简单的“重命名”重构之后,您可能会获得更多的把握。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-03
      • 1970-01-01
      • 1970-01-01
      • 2012-03-12
      • 1970-01-01
      • 1970-01-01
      • 2013-03-17
      • 1970-01-01
      相关资源
      最近更新 更多