Witam.
Piszę grę z komunikacją klient <--> serwer opartą na wątkach. Podczas połączenia klienta z serwerem, serwer uruchamia dla niego wątek tworząc w konstruktorze ObjectInputStream i ObjectOutputStream potrzebne do serializacji. Klient wysyła obiekt do serwera a ten odbiera go w konkretnym wątku i wypisuje na konsolę.
Problem zaczyna się kiedy połączy się dwóch klientów, uruchomią się dwa wątki z osobnymi stworzonymi w konstruktorze kanałami komunikacyjnymi. Pierwszy klient wykonuje dowolną ilość akcji(po wykonaniu wysyłam obiekt do serwera), wątek odbiera obiekt i wypisuje na konsole pola zdeserializowanego obiektu. Potem przełączam okno na drugiego klienta i wykonuje akcje lecz dochodzi tylko jeden obiekt i następuje zawieszenie, w niektórych przypadkach dostaje wyjątki:
java.io.StreamCorruptedException: invalid type code: 00
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at siec.Server.readSerializedObject(Server.java:125)
at siec.Server.run(Server.java:144)
oraz
IOException
klasa serwera:
package siec;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server extends Thread {
public static final int PORT = 5000;
public static final String IP = "127.0.0.1";
static InetAddress addr = null;
static ServerSocket serverSocket = null;
static Socket socket = null;
static BufferedReader in = null;
PrintWriter out = null;
static ObjectOutputStream oos = null;
static ObjectInputStream ois = null;
private int PLAYER_ID = 0;
private int players = 0;
public Server() {
// /////////////
}
public void updatePlayerId(String playerId) {
if (playerId.compareTo("1") == 0)
PLAYER_ID = 1;
if (playerId.compareTo("2") == 0)
PLAYER_ID = 2;
System.out.println("Nowy gracz o id: " + PLAYER_ID);
}
public Server(Socket s, String playerId) throws IOException {
socket = s;
updatePlayerId(playerId);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.err.println("-->Stworzono BufferedReader dla wątku");
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
System.err.println("-->Stworzono PrintWriter dla wątku");
oos = new ObjectOutputStream(socket.getOutputStream());
System.err.println("-->Stworzono ObjectOutputStream dla wątku");
ois = new ObjectInputStream(socket.getInputStream());
System.err.println("-->Stworzono ObjectInputStream dla wątku");
start();
System.err.println("-->Stworzono wątek dla klienta o id: " + PLAYER_ID);
}
public ServerSocket startServer(ServerSocket serverSocket, int port) {
try {
serverSocket = new ServerSocket(port);
System.err.println("-->Serwer wystartował");
} catch (IOException e) {
System.err.println("-->Błąd startu servera");
}
return serverSocket;
}
/*
* public Socket acceptConnection(ServerSocket serverSocket, Socket socket)
* throws IOException { //serverSocket = new ServerSocket(port); try {
* socket = serverSocket.accept();
* System.err.println("Przyjeto połączenie o id: " + socket); } catch
* (Exception e) { //System.err.println("-->Błąd przyjmowania połączenia");
* } return socket; }
*/
public void addPlayer() {
this.players++;
}
public String getPlayers() {
return "" + this.players;
}
public String readData(Socket socket) throws IOException {
String data = null;
try {
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
data = in.readLine();
} catch (IOException e) {
System.err.println("-->Błąd czytania danych");
}
return data;
}
public void writeData(Socket socket, String data) throws IOException {
try {
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
out.println(data);
} catch (IOException e) {
System.err.println("-->Błąd wysyłania");
}
}
public static void writeSerializedObject(Gamer gamer) {
try {
oos.writeObject(gamer);
oos.flush();
oos.reset();
} catch (IOException e) {
System.err.println("Błąd wysyłania obiektu");
}
}
public Gamer readSerializedObject() throws IOException,
ClassNotFoundException {
Gamer gamer = null;
try {
gamer = (Gamer) ois.readObject();
} catch (IOException e) {
System.out.println("Błąd odczytu obiektu");
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.out
.println("Błąd ClassNotFoundException podczas czytania obiektu");
}
return gamer;
}
@Override
public void run() {
Gamer gamer = null;
Gamer gamerToSend = null;
String data = null;
while (true) {
try {
gamer = readSerializedObject();
// data = readData(socket);
if (gamer != null) {
if (gamer.getGamerId() == 1)
System.out.println("Gracz 1: " + socket.getPort()
+ " " + gamer.toString());
if (gamer.getGamerId() == 2)
System.out.println("Gracz 2: " + socket.getPort()
+ " " + gamer.toString());
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
}
package siec;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerManager {
final static int PORT = 5000;
final String IP = "127.0.0.1";
static ServerSocket serverSocket = null;
static Server server = new Server();
static ByteArrayInputStream baisThread = null;
static ObjectInputStream oisThread = null;
static ByteArrayOutputStream baosThread = null;
static ObjectOutputStream oosThread = null;
public static void main(String[] args) throws IOException, ClassNotFoundException {
baosThread = new ByteArrayOutputStream();
oosThread = new ObjectOutputStream(baosThread);
baisThread = new ByteArrayInputStream(baosThread.toByteArray());
oisThread = new ObjectInputStream(baisThread);
serverSocket = server.startServer(serverSocket, PORT);
try {
while(true) {
Socket socket = serverSocket.accept();
System.err.println("-->Nowe połączenie " + socket);
server.addPlayer();
new Server(socket, server.getPlayers());
server.writeData(socket, server.getPlayers());
}
} catch (IOException e) {
System.err.println("-->Błąd przyjmowania połącznenia");
}
}
}
Klient posiada te same metody co serwer więc nie ma sensu wklejać tyle kodu.
Chciałbym zadać przy okazji kolejne pytanie.
Otóż jeśli komunikacja klient <-->serwer<-->klient działałaby, jak mogę przesłać odebrany obiekt od pierwszego klienta w pierwszym wątku do drugiego wątku aby ten mógł wysłać go do drugiego klienta(wszystko za pośrednictwem serwera) ?
Z góry dziękuje za pomoc.