views:

202

answers:

4

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

The server does something like this to check for connections, in 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:

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?

A: 

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:

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.)

Chris Jester-Young
+1  A: 

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

Bhushan
The issue is that I need to interact with the Player class. Not the Socket class. What you are suggesting is that I make the ArrayList full of Sockets instead of Players.
Logan Serman
Yep, that's probably what you need to do. Remember that the Player object created by the client does not exist at all on the server.
David Zaslavsky
@Logan: You need a way to serialise your objects into a byte stream, which you send, via the OutputStream, to be received by the Player class. This then needs to deserialise ("reconstitute") the bytes in the stream back into the objects.
Chris Jester-Young
When the server will write a message on socket, it will be received by Player client and thereby you can get any method executed (ofcourse you need to write the logic). Starter info available here http://java.sun.com/docs/books/tutorial/networking/sockets/index.html
Bhushan
+1  A: 

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:

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.

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

Uri
+1 Yay for seeing forests instead of trees! I like your answer so much, I'm nuking mine. :-P
Chris Jester-Young
I think your answer is good, don't nuke it. I have spent my time building sockets (I think it's important to learn), but learned to appreciate the ability to defer the headache to an existing framework. My program is way more reliable now (e.g., passes the walking with a laptop test)
Uri
I will be more specific with you. The game is scrabble. The server needs to be able to send information about each Player's move through TCP. This information is essentially the positions and the letters in those positions. I cannot send this because I can only interact with Sockets, not Players.
Logan Serman
Okay, I'll bring my post back. :-) I agree with your comment totally.
Chris Jester-Young
A: 

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

Rename existing Server.java to 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.

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

Manoj