JAVA - 简单的服务器看到客户端的困难

时间:2021-07-14 23:57:04

I am trying to make a simple game that goes across a TCP network.

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

The server does something like this to check for connections, in Server.java:

服务器执行类似这样的操作来检查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();
    }
}

And to make a new client, in Player.java:

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

socket = new Socket(hostname, port);

Now, this works fine and all, but I need the server to add the instance of the Player to an array list and be able to send all of them certain data. They both have main methods, so one computer can just run the server and have 4 other computers connect to it by running Player.java. If all Player does is create a new socket, how is the Server supposed to interact with each Player?

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

4 个解决方案

#1


I'm not sure I understand the question.

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

The call to accept will produce a different return value for each connecting client (typically representing the client address and port), so you need to store each of them. You can then interact via the sockets, Sun has a pretty good example in its tutorial:

对accept的调用将为每个连接客户端生成不同的返回值(通常表示客户端地址和端口),因此您需要存储每个客户端地址和端口。然后你可以通过套接字进行交互,Sun在其教程中有一个很好的例子:

That being said, save yourself a lot of headache and think over the performance you expect from the game. You can save yourself a lot of trouble and easily add reliability and scalability if you use JMS and ActiveMQ for your communications rather than mess around with sockets yourself.

话虽这么说,让自己避免很多头痛,并考虑你对游戏的期望。如果您使用JMS和ActiveMQ进行通信而不是自己使用套接字,那么您可以省去很多麻烦并轻松添加可靠性和可伸缩性。

Spend your time writing the game, not doing low-level socket programming, unless you're trying to learn.

花时间编写游戏,而不是进行低级套接字编程,除非你想学习。

#2


server.accept() method returns you an object of Socket. Socket class have a method getOutputStream(), you can use this stream to send a message.

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

#3


Try this:

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

where clients has type List<Server>. Then, add a sendMessage method (or whatever) to your Server class. Then:

客户端的类型为List 。然后,将sendMessage方法(或其他)添加到Server类中。然后:

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

Hope this helps! (BTW there is a distinct reason I call the variables client and clients. They're really abstractions for incoming clients, not servers as such, even though the code inside Server is really a server for interacting with said clients.)

希望这可以帮助! (顺便说一下,有一个明显的原因我称之为变量客户端和客户端。它们实际上是传入客户端的抽象,而不是服务器本身,即使Server内部的代码实际上是与所述客户端进行交互的服务器。)

#4


Let me do some name refactorings based on my understanding of his question.

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

Rename existing Server.java to Player.java

将现有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
        }
   }

}

If server wants to notify all players, it can call a method on the player object which further does required work to send data to the client.

如果服务器想要通知所有玩家,它可以调用播放器对象上的方法,该方法还需要将数据发送到客户端。

Finally rename existing Player.java to GameLauncher.java.

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

You might get more grip after doing this simple 'rename' refactorings.

在完成这个简单的“重命名”重构后,您可能会获得更多的抓地力。

#1


I'm not sure I understand the question.

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

The call to accept will produce a different return value for each connecting client (typically representing the client address and port), so you need to store each of them. You can then interact via the sockets, Sun has a pretty good example in its tutorial:

对accept的调用将为每个连接客户端生成不同的返回值(通常表示客户端地址和端口),因此您需要存储每个客户端地址和端口。然后你可以通过套接字进行交互,Sun在其教程中有一个很好的例子:

That being said, save yourself a lot of headache and think over the performance you expect from the game. You can save yourself a lot of trouble and easily add reliability and scalability if you use JMS and ActiveMQ for your communications rather than mess around with sockets yourself.

话虽这么说,让自己避免很多头痛,并考虑你对游戏的期望。如果您使用JMS和ActiveMQ进行通信而不是自己使用套接字,那么您可以省去很多麻烦并轻松添加可靠性和可伸缩性。

Spend your time writing the game, not doing low-level socket programming, unless you're trying to learn.

花时间编写游戏,而不是进行低级套接字编程,除非你想学习。

#2


server.accept() method returns you an object of Socket. Socket class have a method getOutputStream(), you can use this stream to send a message.

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

#3


Try this:

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

where clients has type List<Server>. Then, add a sendMessage method (or whatever) to your Server class. Then:

客户端的类型为List 。然后,将sendMessage方法(或其他)添加到Server类中。然后:

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

Hope this helps! (BTW there is a distinct reason I call the variables client and clients. They're really abstractions for incoming clients, not servers as such, even though the code inside Server is really a server for interacting with said clients.)

希望这可以帮助! (顺便说一下,有一个明显的原因我称之为变量客户端和客户端。它们实际上是传入客户端的抽象,而不是服务器本身,即使Server内部的代码实际上是与所述客户端进行交互的服务器。)

#4


Let me do some name refactorings based on my understanding of his question.

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

Rename existing Server.java to Player.java

将现有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
        }
   }

}

If server wants to notify all players, it can call a method on the player object which further does required work to send data to the client.

如果服务器想要通知所有玩家,它可以调用播放器对象上的方法,该方法还需要将数据发送到客户端。

Finally rename existing Player.java to GameLauncher.java.

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

You might get more grip after doing this simple 'rename' refactorings.

在完成这个简单的“重命名”重构后,您可能会获得更多的抓地力。