views:

740

answers:

4

I'm very new to Java, and I'm trying to modify an example of a socket server to power a flash-based game. To allow flash to connect to the server, I need to serve up a policy file.

I've never coded a server application before, so I'm not too familiar with the things which need to happen.

Anyway, I have made it so that it outputs the file, but for some reason it does so 10 times.

I need to close the thread before it continues to do it again. Below is the code I have, with a comment where I need to close the thread.

import java.io.*;
import java.net.*;
import java.util.Random;

public class Main {

  private static int port=4041, maxConnections=0;
  // Listen for incoming connections and handle them
  public static void main(String[] args) {
    int i=0;

    try{
      ServerSocket listener = new ServerSocket(port);
      Socket server;

      while((i++ < maxConnections) || (maxConnections == 0)){
        doComms connection;

        server = listener.accept();
        doComms conn_c= new doComms(server);
        Thread t = new Thread(conn_c);
        t.start();
      }
    } catch (IOException ioe) {
      System.out.println("IOException on socket listen: " + ioe);
      ioe.printStackTrace();
    }
  }

}

class doComms implements Runnable {
    private Socket server;
    private String line,input;

    doComms(Socket server) {
      this.server=server;
    }

    public void run () {

        char EOF = (char)0x00;
      input="";

      try {
        // Get input from the client
        DataInputStream in = new DataInputStream (server.getInputStream());
        PrintStream out = new PrintStream(server.getOutputStream());

        while((line = in.readLine()) != null && !line.equals(".")) {
          input=input + line;
          if(line.trim().equals("h")){

              out.println("h"+EOF);

          }
          else if(line.trim().equals("i")){

               Random randomGenerator = new Random();
               int randomInt = randomGenerator.nextInt(4);

              out.println("b"+randomInt+EOF);


          }
          else if(line.trim().equals("c")){ System.out.println("Player collision.");}
          else if (line.trim().equals("<policy-file-request/>")) {
            out.println("<?xml version=\"1.0\"?>\n<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\"&gt;&lt;cross-domain-policy&gt;\n&lt;site-control permitted-cross-domain-policies=\"all\"/>\n<allow-access-from domain=\"*\"/>\n</cross-domain-policy>"+EOF);
            System.out.println("Responded to policy request");
            // I need to close the thread / disconnect the client here.
          }
          else System.out.println("Unknown command: "+line.trim());

        }
        server.close();
      } catch (IOException ioe) {
        System.out.println("IOException on socket listen: " + ioe);
        ioe.printStackTrace();
      }
    }
}

Also, a small extra thing, in NetBeans, it underlines "import java.io.*;" and says incorrect package, but it still works fine.

Edit: I've worked out that the reason it sends it 10 times is that it is receiving 10 lines in a single send operation. I have tried adding a "return;" under where it sends the policy XML, but it still doesn't seem to d/c the client. I should also note than I am intending for this to be a multiplayer server, so I need to keep the socket open and just close one thread.

+2  A: 

At first glance, your run() method looks like it should terminate normally. I suspect your loop:

while((i++ < maxConnections) || (maxConnections == 0)){

Since maxConnections is initialized to 0 and is never incremented, the loop seems to run infinitely and create many threads - probably as many as the socket can accept listeners. And then it breaks out from the loop with an IOException. Is this what's actually happening?

Update: apparently not... out of ideas for now.

Péter Török
No, it should block on listener.accept and create one thread for each request.
abc
+1 for reading all the code
stacker
A: 

Your code makes sense. What is your input? If you have 10 lines saying "<policy-file-request/>" , then indeed it will print the file 10 times. What about all the other if clauses you have there? In each one you print something + EOF, but surely you just want to print one response per request. Also your 'input' variable is unused.

abc
I need the flash client to remain connected, as it's a game, and these are its basic multiplayer packets. Unfortunately flash requires I serve a policy file from the same host to allow further communication.
Alex
A: 

The thread will die after you return from doComms.run(). Please capitalize the start of class names in Java: it should be DoComms, just to make the code easier to follow for other Java programmers.

To close the connection, your call to server.close() should do it. To make sure the output is sent fully first, you should call close() or flush() on your PrintStream before you call Socket.close().

What input are you sending? It looks like if you only send <policy-file-request/> once from the client, you'll only get the file once.

Not sure about NetBeans, but is it complaining that you don't have a package specified at the top of your .java file? Try adding the following package declaration, with the path relative to the top of the NetBeans project:

package my.path.to.this.directory;
Harold L
A: 

I'd suggest running both the server and the client in a debugger and stepping through the execution to see what happens at each point in time. This will help you confirm the expected values at every point. Eclipse and other Java IDEs have pretty good (and easy-to-use) debuggers.

As far as your code:

  1. I would do line.trim() once for each loop iteration, instead of trim()'ing repeatedly and unnecessarily creating extra objects.
  2. Make sure the client and server both flush() the Socket's OutputStream after each request/response. If the socket's OutputStream has not been flushed, the InputStream on the other end of the connection may block waiting for input, while the OutputStream blocks waiting to fill its buffer.
  3. What does the code in the client look like? Are you sure it's sending a null or "." to close the connection? Do you need to trim() before checking for a "."
  4. As others have mentioned, your code does not follow typical Java coding conventions. I'd suggest getting up to speed by reading the published code conventions for Java.
rob