0

I'm creating simple peer to peer game. Currently I'm working on Server/Client(Node) side. I occured strange problem, I can create ObjectOutputStream from socket, but program stops at creation of ObjectInputStream. To store sockets and create streams I'm using my own class(code below). What I'm doing wrong ?

public void run() {
    try {
        while (this.listen) {

            temp = serverSocket.accept();
            sockList.addSocket(temp);
            sockList.addObjOutStrm(temp);
            sockList.addObjInStrm(temp); // <------------------------ program stops


            setChanged();
            notifyObservers(temp);

            System.out.println("SERVER: Dodalem uzytkownika, oto pelna lista:\n\n"
                            + sockList + "\n");

            synchronized (sockList) {
                for (ObjectOutputStream oos : sockList.getOOSList()) {
                    oos.writeObject(sockList.extractToString());
                }
            }
        }
    } catch (IOException e) {
        System.err.println("SERVER: Błąd I/O serwera podczas nasluchu");
        //e.printStackTrace();
    }
}

My Own class to store sockets and streams:

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SocketList {
    private List<ObjectOutputStream> obOutStrList;
    private List<ObjectInputStream> obInStrList;
    private List<Socket> sockList;

    private int maxUsers;
    private int currentUsers;

    public SocketList() {
        obOutStrList = Collections
                .synchronizedList(new ArrayList<ObjectOutputStream>());
        obInStrList = Collections
                .synchronizedList(new ArrayList<ObjectInputStream>());
        sockList = Collections.synchronizedList(new ArrayList<Socket>());

        maxUsers = 4;
        currentUsers = 0;
    }

    synchronized public void addSocket(Socket sock) {
        if (sockList.size() < 4) {
            sockList.add(sock);
            currentUsers++;
        } else {
            System.out.println("sockList: Blad max uzytkownikow");
        }
    }

    synchronized public void addObjOutStrm(Socket sock) {
        try {
            obOutStrList.add(new ObjectOutputStream(sock.getOutputStream()));
        } catch (IOException e) {
            System.out.println("Problem z uzyskaniem strumienia wyjsciowego dla " + sock.getInetAddress().getHostAddress().toString());
            e.printStackTrace();
        }
    }

    synchronized public void addObjInStrm(Socket sock) {
        try {
            obInStrList.add(new ObjectInputStream(sock.getInputStream()));
        } catch (IOException e) {
            System.out.println("Problem z uzyskaniem strumienia wejsciowego dla " + sock.getInetAddress().getHostAddress().toString());
            e.printStackTrace();
        }
    }

    synchronized public void removeSock(Socket s) {
        if (sockList.contains(s)) {
            System.out.println("SOCKETLIST: Usuwam " + s.toString());
            sockList.remove((Socket) s);
        }
    }

    synchronized public List<Socket> getSockList() {
        return sockList;
    }

    synchronized public List<ObjectOutputStream> getOOSList() {
        return obOutStrList;
    }

    synchronized public List<ObjectInputStream> getOISList() {
        return obInStrList;
    }

    public String toString() {
        return sockList.toString();
    }

    public String[] extractToString() {
        String[] retArr = new String[currentUsers];

        for (int i = 0; i < sockList.size(); i++)
            retArr[i] = sockList.get(i).getInetAddress().getHostAddress()
                    .toString();

        return retArr;
    }

}

1 Answer 1

1

Are you sure, you want to do this? Reading an writing objects is not very portable, use some kind of protocol with a data structure like XML or JSON for communication. This is far more portable.
To your problem:

new ObjectInputStream(sock.getInputStream())

will block and wait until the header has been written to the stream, as the JavaDoc states:

This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.

Overall, I strongly suggest you a different architecture, use multi-threading to handle the client connections on the server, possibly using a thread pool and maybe even message queues. See package java.util.concurrent for all you need for this.

Have a look here, for a start: http://tutorials.jenkov.com/java-multithreaded-servers/multithreaded-server.html

Sign up to request clarification or add additional context in comments.

4 Comments

"portable" ? as in, it would be difficult to write a client or server for the game in another language and still be compatible with the java client/server? i think that's a little silly and unnecessary to state in the scope of the OP's question, but i may be misunderstanding you.
Yes, Multi-threading to handle each client is what I forgot about. Thanks for tip, and about sending object - I'm not sure it will stay as that, it's prototype of my project so everything may be changed. At now I want to keep it as simple as possible.
@AlexLynch: I do not consider it as a silly statement, else I would not have made it. Maybe I have chosen the wrong word to catch all the possible problems you will face when using ByteOutputStream/ByteInputStream for Client/Server communication. And this does not only mean portability between different languages, but also between different Java versions and object versions and much more.
@UdoKlimaschewski Surely you mean ObjectOutputStream, not ByteOutputStream, whatever that is?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.