It's my first time working with sockets, in order to get a better understanding of what's going on I decided to build a client server chat application which can support several users.
At first, I used DataInputStream / DataOutputStream to communicate and everything works well. But I would like to switch to an ObjectStream and that's where the problem occurs. Once I replace all the DataInputStream / DataOutputStream by ObjectInputStream / ObjectOutputStream, I'm no longer able to print the retrieved data.
This is the code that I used before, which works (DataStream) :
SERVER:
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
out.writeUTF("HI FROM SERVER");
while (!socket.isClosed()) {
try {
if (in.available() > 0) {
String input = in.readUTF();
for (ClientThread thatClient : server.getClients()){
DataOutputStream outputParticularClient = new DataOutputStream(thatClient.getSocket().getOutputStream());
outputParticularClient.writeUTF(input + " GOT FROM SERVER");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
CLIENT:
try {
socket = new Socket("localhost", portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
new Thread(()->{
while(!socket.isClosed()){
try {
if (in.available() > 0){
String input = in.readUTF();
System.out.println(getUserName() + " > " + input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
And this is how I tried to perform the same idea with ObjectStream :
SERVER:
try {
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
while (!socket.isClosed()) {
try {
if (in.available() > 0) {
Message input;
try {
input = (Message)in.readObject();
if (input.equals(null)){
System.err.println("SERVER RETRIEVED NULL OBJECT");
}
for (ClientThread thatClient : server.getClients()){
ObjectOutputStream outputParticularClient = new ObjectOutputStream(thatClient.getSocket().getOutputStream());
outputParticularClient.writeObject(input);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
CLIENT:
try {
socket = new Socket(getHost(), portNumber);
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
new Thread(()->{
while(!socket.isClosed()){
try {
if (in.available() > 0){
Message input = null;
try {
input = (Message)in.readObject();
if (input.equals(null)){
System.err.println("CLIENT RETRIEVED NULL OBJECT");
}
System.out.println("CLIENT " + input.toString());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
I feel like it has something to do with this if statement if (in.available() > 0) but I cannot say precisely what's going on.
available() doesn't do what you may think it does and it is almost never useful in production code (and that's particularly true for ObjectInputStream). The reason you don't receive any data is in fact that in.available() always returns 0 as you already suspected.
As noted in the comments, the StreamCorruptedException is caused by writing to an existing ObjectInputStream that has already been written to using another instance of ObjectOutputStream. Cf. the answer StreamCorruptedException: invalid type code: AC for further explanation.
Here is some quick & dirty example code that has a server echoing the messages from two clients. It's not clean but it may give you an idea how to approach your problem:
public class SO56493162 {
private static final class Message implements Serializable {
private static final long serialVersionUID = 1L;
private static int cnt = 0;
private final int id;
public Message(int id) {
++cnt;
this.id = id;
}
public String toString() {
return "Msg from " + id + " : " + cnt;
}
}
private static final class Client implements Runnable {
private InetSocketAddress addr = null;
private int id = -1;
Client(InetSocketAddress addr, int id) {
this.addr = addr;
this.id = id;
}
public void run() {
int timeout = 3000;
Socket s = null;
try {
s = new Socket();
s.connect(addr, timeout);
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
System.out.println("Client " + id + " connected");
while (true) {
Thread.sleep(new Random().nextInt(2000));
Message hello = new Message(id);
oos.writeObject(hello);
oos.flush();
Message reply = (Message) ois.readObject();
System.out.println("Reply: " + reply.toString());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
s.close();
} catch (Exception ignore) {
}
}
}
}
private static final class Server implements Runnable {
private ServerSocket sock = null;
Server(ServerSocket sock) throws IOException {
this.sock = sock;
}
public void run() {
System.out.println("starting server");
try {
while (true) {
final Socket client = sock.accept();
System.out.println("connection accepted");
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
while (!client.isClosed()) {
try {
Message input = (Message) ois.readObject();
oos.writeObject(input);
oos.flush();
} catch (EOFException eof) {
System.err.println("EOF!");
client.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) throws IOException, InterruptedException {
final int port = 9876;
Thread ts = new Thread(new Runnable() {
#Override
public void run() {
try {
new Server(new ServerSocket(port)).run();
} catch (Exception e) {
e.printStackTrace();
}
}
});
ts.setDaemon(true);
ts.start();
InetSocketAddress addr = new InetSocketAddress("localhost", port);
for (int i = 0; i < 2; ++i) {
Client cl = new Client(addr, i);
Thread tc = new Thread(cl);
tc.setDaemon(true);
tc.start();
}
Thread.sleep(10000);
System.err.println("done");
}
}
Related
I am having trouble making a multi client server for a game that i have made. I am able to create a ServerSocket, make a connection and send data through means of a ObjectInputStream and ObjectOutputStream. My problems lies when it comes to multiple clients, from what i understand a new thread needs to be created for each client but the data i would like to send and receive is hard coded into the client class. How would I allow my Client to send changeable data?
Here is my client class:
public class Client extends Thread {
private Server server = new Server();
private Socket connection;
private ObjectOutputStream out;
private ObjectInputStream in;
public Client(Socket connection) {
this.connection = connection;
this.out = server.objOutStream(this.connection);
this.in = server.objInStream(this.connection);
}
public void run() {
while(this.connection.isConnected()) {
//
List<String> list = new ArrayList<String>();
list.add("hello there");
server.sendData(out, list);
//
List<String> recive = new ArrayList<String>();
recive = server.reveiveData(in);
}
}
public Socket getConnection() {
return connection;
}
}
and Here is the server side:
public ServerSocket createServer(Integer serverPort, Integer serverSize) {
ServerSocket server = null;
try {
server = new ServerSocket(serverPort, serverSize);
System.out.println("created server");
} catch (IOException e) {
e.printStackTrace();
}
return server;
}
public Socket makeConnection(ServerSocket server) {
Socket connection = null;
try {
connection = server.accept();
Client client = new Client(connection);
client.start();
System.out.println("connection made with " + connection.getInetAddress().getHostAddress());
} catch (IOException e) {
e.printStackTrace();
}
return connection;
}
public ObjectInputStream objInStream(Socket connection) {
ObjectInputStream in = null;
try {
in = new ObjectInputStream(connection.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
return in;
}
public ObjectOutputStream objOutStream(Socket connection) {
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(connection.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
return out;
}
public void sendData(ObjectOutputStream out, List<String> list) {
try {
out.writeObject(list);
out.flush();
System.out.println("sending " + list);
} catch (IOException e) {
e.printStackTrace();
}
}
public List<String> reveiveData(ObjectInputStream in) {
List<String> list = null;
try {
list = (List<String>) in.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return list;
}
public Socket joinServer(String serverIP, Integer serverPort) {
Socket connection = null;
try {
connection = new Socket(InetAddress.getByName(serverIP), serverPort); System.out.println("joined");
} catch (IOException e) {
e.printStackTrace();
}
return connection;
}
public void stop(Socket connection) {
System.out.println("closing");
try {
if(connection.isInputShutdown() == false) {
connection.getInputStream().close();
}
if(connection.isOutputShutdown() == false) {
connection.getOutputStream().close();
}
if(connection.isConnected() == true) {
connection.close();
}
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}
In my mian class I run this:
try {
if(connection == null) {
connection = server.makeConnection(serverSocket);
in = server.objInStream(connection);
out = server.objOutStream(connection);
}else {
//readlist
List<String> readList = (List<String>) in.readObject();
System.out.println("reciving: " + readList);
//writelist
List<String> writeList = new ArrayList<String>();
writeList.add("hi");
out.writeObject(writeList);
System.out.println("sending: " + writeList);
}
}catch(IOException | ClassNotFoundException e) {
e.printStackTrace();
}
Hello everybody and thanks in advance to those who will read that :
I'm trying to send an ArrayList of an object "Profile" (which I made serializable) but one by one (because at the end the List will be filled by other threads but this is not the matter here).
I'm using a socket between a "clientconnexion" (which is the client) and a "clientprocessor" (which is the server). They are in different threads and at the end they will be on different computers.
When I try to do it with the following code (trying to send 50 profiles) I do receive some of them (like the 20 first, or the 30 first, sometimes even all of them or none...) but the clientconnexion stops receiving the profiles at one time...
Here is the code :
The class Profile :
public class Profile implements Serializable {
private static final long serialVersionUID = 2406276545874892098L;
public int id;
public String name;
public Profile(String name, int id){
this.id=id;
this.name=name;
}
}
The class Server (which accept the connexion and start clientprocessor thread, it only start one thread so it isn't really usefull now but it will be after) :
public class serveur {
private int port;
private String host = "0.0.0.0";
private ServerSocket server = null;
private boolean isRunning = true;
public serveur(String pHost, int pPort){
host = pHost;
port = pPort;
try {
server = new ServerSocket(port, 100, InetAddress.getByName(host));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void open(){
Thread t = new Thread(new Runnable(){
public void run(){
while(isRunning == true){
try {
Socket client = server.accept();
client.setTcpNoDelay(true);
Thread t = new Thread(new clientprocessor(client));
t.start();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
server.close();
} catch (IOException e) {
e.printStackTrace();
server = null;
}
}
});
t.start();
}
public void close(){
isRunning = false;
}
}
The class clientprocessor :
public class clientprocessor implements Runnable {
private Socket client;
private BufferedOutputStream bos=null;
private BufferedInputStream bis=null;
private BufferedWriter writer=null;
private BufferedReader reader=null;
private ArrayList<Profile> profilesToSend;
public clientprocessor (Socket client){
this.client = client;
this.profilesToSend=new ArrayList<>();
for (int i=1; i<51; i++){
this.profilesToSend.add(new Profile("test", i));
}
}
public synchronized Profile getProfile () {
Iterator<Profile> itr = this.profilesToSend.iterator();
if (itr.hasNext()){
Profile P = itr.next();
itr.remove();
return P;
}
return null;
}
public void run (){
try {
bos= new BufferedOutputStream (client.getOutputStream());
bis= new BufferedInputStream (client.getInputStream());
writer=new BufferedWriter(new OutputStreamWriter(bos));
reader=new BufferedReader(new InputStreamReader(bis));
ObjectOutputStream oos=new ObjectOutputStream(bos);
Profile P;
while ((P = this.getProfile())!=null) {
writer.write(0); //when the client receive a zero, e knows he will receive a profile
writer.flush();
oos.writeObject(P);
oos.flush();
System.out.println("clientprocessor : profile written (" + P.name + " " +P.id +")");
int i=reader.read(); //Waiting to receive a one to be sure that the object was received
System.out.println("clientprocessor : integer received : " +i);
}
System.out.println("--------clientprocessor : all profiles sent--------");
writer.write(1); //when the client receive a one he knows he will not receive profiles anymore
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
writer.close();
reader.close();
bis.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The class clientconnexion (which is supposed to be on another computer at the end) :
public class clientconnexion implements Runnable {
private Socket connexion;
private BufferedOutputStream bos=null;
private BufferedInputStream bis=null;
private BufferedWriter writer=null;
private BufferedReader reader=null;
public clientconnexion(String adress, int port) {
try {
connexion = new Socket(adress, port);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
connexion.setTcpNoDelay(true);
bos= new BufferedOutputStream (connexion.getOutputStream());
bis= new BufferedInputStream (connexion.getInputStream());
writer=new BufferedWriter(new OutputStreamWriter(bos));
reader=new BufferedReader(new InputStreamReader(bis));
ObjectInputStream ois = new ObjectInputStream(bis);
int k = reader.read();
String S="clientconnexion : profiles received : ";
while (k==0){
System.out.println("clientconnexion : waiting for an object to read");
Profile P=(Profile)ois.readObject();
S = S + P.name + " " + P.id+ " ; ";
System.out.println(S);
writer.write(1);//the client sends a 1 to the server (clientprocessor)
writer.flush();
k=reader.read();
}
} catch (IOException e) {
System.out.println(e);
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
bis.close();bos.close();reader.close();writer.close();
System.out.println("clientconnexion : streams closed");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
And finally the class test which is launching all that :
public class test {
public static String adresse = "localhost";
public static int port = 9028;
public static void main(String[] args) {
serveur serveur = new serveur ("0.0.0.0",port);
System.out.println("--Test : serveur créé");
serveur.open();
System.out.println("Test : serveur ouvert");
Thread tclient1= new Thread(new clientconnexion(adresse, port));tclient1.start();
}
As you can see I tried to setTCPnoDelay but obviously it wasn't the reason of the problem.
Thanks a lot if you read that and if you can run this code and tell me if you have the same problems...
The problem is in clientprocessor class both ObjectOutputStream and BufferedWriter cannot connect to the same stream. Likewise in clientconnexion class both ObjectInputStream and BufferedReader cannot connect to the same stream. The following changes should work
clientprocessor class
try {
bos= new BufferedOutputStream (client.getOutputStream());
bis= new BufferedInputStream (client.getInputStream());
//writer=new BufferedWriter(new OutputStreamWriter(bos));
reader=new BufferedReader(new InputStreamReader(bis));
ObjectOutputStream oos=new ObjectOutputStream(bos);
Profile P;
while ((P = this.getProfile())!=null) {
//writer.write(0); //when the client receive a zero, e knows he will receive a profile
//writer.flush();
oos.write(0);
oos.flush();
oos.writeObject(P);
oos.flush();
System.out.println("clientprocessor : profile written (" + P.name + " " +P.id +")");
int i=reader.read(); //Waiting to receive a one to be sure that the object was received
System.out.println("clientprocessor : integer received : " +i);
}
System.out.println("--------clientprocessor : all profiles sent--------");
//writer.write(1); //when the client receive a one he knows he will not receive profiles anymore
//writer.flush();
oos.write(1);
oos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//writer.close();
reader.close();
bis.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
clientconnexion class
try {
connexion.setTcpNoDelay(true);
bos= new BufferedOutputStream (connexion.getOutputStream());
bis= new BufferedInputStream (connexion.getInputStream());
writer=new BufferedWriter(new OutputStreamWriter(bos));
//reader=new BufferedReader(new InputStreamReader(bis));
ObjectInputStream ois = new ObjectInputStream(bis);
int k = ois.read();
String S="clientconnexion : profiles received : ";
while (k==0){
System.out.println("clientconnexion : waiting for an object to read");
Profile P=(Profile)ois.readObject();
S = S + P.name + " " + P.id+ " ; ";
System.out.println(S);
writer.write(1);//the client sends a 1 to the server (clientprocessor)
writer.flush();
k=ois.read();
}
} catch (IOException e) {
System.out.println(e);
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
bis.close();
bos.close();
//reader.close();
writer.close();
System.out.println("clientconnexion : streams closed");
} catch (IOException e) {
e.printStackTrace();
}
}
I am getting the broken pipe error while the client stopping the build process and new client connect with server and sending message to the server.
Here my Server code:
public class Server {
ArrayList<ObjectOutputStream> ListOfclientOutputStreams;
public Server() {
ListOfclientOutputStreams = new ArrayList<ObjectOutputStream>();
try {
ServerSocket serverSocket = new ServerSocket(7503);
while(true) {
Socket serverCommunicationSocket;
serverCommunicationSocket = serverSocket.accept();
ObjectOutputStream eachClientobjectOutStream = new ObjectOutputStream(serverCommunicationSocket.getOutputStream());
ListOfclientOutputStreams.add(eachClientobjectOutStream);
Thread threadForSpecificClient = new Thread(new SpecificClient(serverCommunicationSocket));
threadForSpecificClient.start();
System.out.println("Got a connection");
}
}catch(IOException ex) {
ex.printStackTrace();
}
}
private class SpecificClient implements Runnable {
private ObjectInputStream eachClientObjectInputStream;
private Socket sock;
public SpecificClient(Socket specificSocket) {
try {
sock = specificSocket;
eachClientObjectInputStream = new ObjectInputStream(sock.getInputStream());
}catch (IOException ex) {
ex.printStackTrace();
}
}
public void run() {
Message msgObject;
try {
while((msgObject = (Message) eachClientObjectInputStream.readObject()) !=null) {
System.out.println("Client thread on the server read" + msgObject);
broadCast(msgObject);
}
}catch (IOException ex) {
ex.printStackTrace();
}catch(ClassNotFoundException ex){
System.out.println("Unable to read the message object in server");
ex.printStackTrace();
}
}
public void broadCast(Message msgObject) {
Iterator<ObjectOutputStream> iter = ListOfclientOutputStreams.iterator();
try {
while(iter.hasNext()) {
ObjectOutputStream out = iter.next();
out.writeObject(msgObject);
out.flush();
}
}catch(IOException ex) {
System.out.println("Unable to add the Message object to the outputstream in the server");
ex.printStackTrace();
}
}
}
public static void main(String[] args) {
Server server1 = new Server();
}
}
This is my client coding:
public class Client {
private ObjectOutputStream clientOutStream;
private ObjectInputStream clientInStream;
private Socket clientSocket;
public Client() throws InterruptedException {
establishConnection();
createStreams();
Thread threadToRead = new Thread(new Incoming());
threadToRead.start();
}
public void establishConnection() {
try {
int port = Integer.parseInt(Session.port);
clientSocket = new Socket("127.0.0.1", port);
System.out.println("Network connection Established");
}catch (IOException ex) {
ex.printStackTrace();
}
}
public void createStreams() {
try {
clientInStream = new ObjectInputStream(clientSocket.getInputStream());
clientOutStream = new ObjectOutputStream(clientSocket.getOutputStream());
System.out.println("Connection streams established");
}catch (IOException ex) {
ex.printStackTrace();
}
}
private class Incoming implements Runnable {
public void run() {
String personIn;
Message msgObject = new Message();
try
{
personIn=personLoggedIn.getText().toString();
while((msgObject= (Message) clientInStream.readObject()) !=null)
{
//updateWhoIsOnline();
System.out.println("Client is Reading the object from the server");
String postedTo = msgObject.getPostedTo().replace(",", "").replace("[", "").replace("]", "");
System.out.println("Posted To : "+postedTo);
String[] result = postedTo.split(" ");
int len = result.length;
System.out.println("Length : "+len);
System.out.println("First string : "+result[0].toString());
//System.out.println("Second string : "+result[1].toString());
for(int i=0;i<len;i++) {
if(result[i].toString().equals("All") || result[i].toString().equals(personIn) || msgObject.getPostedBy().equals(personIn)) {
chatDetailsViewArea.append(msgObject.getPostedBy() + " ->" + result[i].toString() + ":" + msgObject.getContent() + "\n");
}
}
}
}
catch(IOException ex)
{
System.out.println("Error in figuring out who to post the message to");
ex.printStackTrace();
}
catch(ClassNotFoundException ex)
{
ex.printStackTrace();
}
}
}
}
In my android app, I am sending messages via UDP. I followed this and this.
However, I am not able to send the initial packet from the client to the server. Please let me know if I am doing something wrong in my code below:
class serverCommunicationThread implements Runnable
{
public void run()
{
try {
serverSocket = new DatagramSocket(STATICPORT);
ServerReceiveMessageThread rcvMsgThread = new ServerReceiveMessageThread(serverSocket);
new Thread(rcvMsgThread).start();
} catch (IOException e) {
e.printStackTrace();
}
}
This is the ServerReceiveMessageThread class:
class ServerReceiveMessageThread implements Runnable
{
DatagramSocket clientSocket;
byte[] buffer = new byte[108];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
ServerReceiveMessageThread(DatagramSocket clientSocket)
{
this.clientSocket = clientSocket;
}
#Override
public void run()
{
int counter = 0;
MsgStruct recvMsgStruct = null;
try {
ByteArrayOutputStream baosServer = new ByteArrayOutputStream();
serializeServer = new ObjectOutputStream(baosServer);
clientSocket.receive(packet);
ByteArrayInputStream baosRecv = new ByteArrayInputStream(buffer);
deserializeServer = new ObjectInputStream(baosRecv);
while(true)
{
try {
recvMsgStruct = (MsgStruct) deserializeServer.readObject();
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
boolean retVal = serverSendMessage(clientSocket, recvMsgStruct, baosServer.toByteArray());
} catch (IOException e2) {
e2.printStackTrace();
}
}
}
The serverSendMessage method:
public boolean serverSendMessage(DatagramSocket clientSocket, MsgStruct msgStruct, byte[] buf)
{
MsgStruct recvMsgStruct = new MsgStruct();
recvMsgStruct.pingPong = true;
recvMsgStruct.msgId = msgStruct.msgId;
recvMsgStruct.bufferMsg = msgStruct.bufferMsg;
try {
serializeServer.writeObject(recvMsgStruct);
serializeServer.flush();
DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getByName(mobileIP), STATICPORT);
clientSocket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
The code for the client send/receive is similar to that of the server. I get a NullPointerException here.
serializeClient.writeObject(mobileSendMsgStruct);
public boolean mobileSendMessage(int msgId)
{
MsgStruct mobileSendMsgStruct = new MsgStruct();
mobileSendMsgStruct.bufferMsg = new byte[100];
mobileSendMsgStruct.pingPong = false;
mobileSendMsgStruct.msgId = msgId;
rand.nextBytes(mobileSendMsgStruct.bufferMsg);
try {
sendTime = System.nanoTime();
serializeClient.writeObject(mobileSendMsgStruct); /*I get a NullPointerException here*/
serializeClient.flush();
byte[] sendBuf = baosSend.toByteArray();
DatagramPacket packet = new DatagramPacket(sendBuf, sendBuf.length, InetAddress.getByName(staticIP), STATICPORT);
mobileSocket.send(packet);
outPing.write(Long.toString(sendTime) + ", " + String.valueOf(mobileSendMsgStruct.msgId) + ", " + String.valueOf(mobileSendMsgStruct.bufferMsg) + " | ");
} catch (IOException e1) {
e1.printStackTrace();
return false;
}
return true;
}
Server code:
while (true) {
Socket sock = serv.accept();
try {
new ClientSession(sock, outQueue, activeSessions);
System.out.println("CS");
} catch (IOException e) {
System.out.println("Sock error");
sock.close();
}
}
ClientSession:
class ClientSession extends Thread {
private Socket socket;
private OutboundMessages outQueue;
private ActiveSessions activeSessions;
private ObjectInputStream netIn;
private ObjectOutputStream netOut;
int n = 0;
boolean inGame = false;
boolean ready = false;
Player p;
public ClientSession(Socket s, OutboundMessages out, ActiveSessions as)
throws IOException {
socket = s;
outQueue = out;
activeSessions = as;
netOut = new ObjectOutputStream(socket.getOutputStream());
netOut.flush();
netIn = new ObjectInputStream(socket.getInputStream());
System.out.println("ClientSession " + this + " starts...");
while (true) {
Object nameMsg = null;
try {
nameMsg = netIn.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
if (nameMsg instanceof NameMessage) {
this.setName(((NameMessage) nameMsg).name);
break;
}
}
start();
}
public void run() {
try {
activeSessions.addSession(this);
while (true) {
Object inMsg = null;
try {
try {
inMsg = netIn.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
if (inMsg instanceof ReadyMessage) {
ready = true;
} else if (inMsg instanceof DirMessage) {
p.setDir(((DirMessage)inMsg).dir);
}
}
} finally {
try {
socket.close();
} catch (IOException e) {
}
}
}
public void sendMessage(Message msg) {
try {
if (!socket.isClosed()) {
netOut.writeObject(msg);
netOut.flush();
} else {
throw new IOException();
}
} catch (IOException eee) {
try {
socket.close();
} catch (IOException ee) {
}
}
}
Creating input and output on client side:
public void connect() {
try {
InetAddress serverAddr = InetAddress.getByName(serverName);
try {
System.out.println("Connecting with "
+ serverAddr.getHostName() + ":" + port);
socket = new Socket(serverAddr, port);
try {
System.out.println("Connected to "
+ serverAddr.getHostName());
netOut = new ObjectOutputStream(socket.getOutputStream());
netOut.flush();
netIn = new ObjectInputStream(socket.getInputStream());
netOut.writeObject(new NameMessage(name));
netOut.flush();
} finally {
}
} catch (ConnectException e) {
System.out.println("Cannot connect to server");
} catch (IOException e) {
System.out.println("Input error");
}
} catch (UnknownHostException e) {
System.out.println("Unknown server: " + e.getMessage());
}
}
receiver on client end:
public void run() {
while (true) {
Object a = null;
try {
a = netIn.readObject();
netIn.reset();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (a != null && a instanceof CoordMessage) {
setXY((CoordMessage)a);
}
}
}
Stacktrace:
java.io.StreamCorruptedException: invalid type code: 00
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at twoPlayerClient.Receiver.run(Receiver.java:28)
After creating input and output I keep passing them on to other classes and not creating new ones.
I have read other similar questions but can't find an answer to why this keeps happening.
new ClientSession(sock, outQueue, activeSessions);
I think, there is a new session for each client, and so you cannot use a stream variable, with global scope. Since its used by other session threads also.