I am attempting to send a BufferedImage over a socket sever to another client. Ill post my code below. When I run the server and the connect to the server with the sending client, and receiving client, everything just sits there. The server shouldn't even be receiving anything unless it has already printed "name is attempting to connect to: " which it doesn't it just sits there. I don't know why it doesn't do anything at all.
Client that sends: http://pastebin.com/X4z55Hdp
Client that receives: http://pastebin.com/MB9qEyGy
Server Source that sends and recieves:
package core;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import utilities.Tools;
public class Node implements Runnable {
private String name;
private Socket socket;
private boolean isApp;
public Node(Socket s, String name) {
this.setName(name);
this.setSocket(s);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public void run() {
while (true) {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
PrintWriter out = new PrintWriter(socket.getOutputStream(),
true);
if (in.readLine() != null) {
// Tools.log("[INPUT] " + in.readLine());
String i = in.readLine();
if (i.contains("set name ")) {
String n = i.replace("set name ", "");
Tools.log("Changing " + name + " to " + n);
this.name = n;
if (n.contains("_app")) {
this.isApp = true;
}
} else {
String toFind = name + "_app";
if (isApp)
toFind = name.replace("_app", "");
Tools.log(name + " is attempting to connect to: "
+ toFind);
for (Node n : Server.nodes) {
if (n.getName().equals(toFind)) {
Tools.log(n.getName() + " found, sending data");
ObjectOutputStream outToNode = new ObjectOutputStream(
n.getSocket().getOutputStream());
ObjectInputStream inFromClient = new ObjectInputStream(
socket.getInputStream());
BufferedImage img = (BufferedImage) inFromClient
.readObject();
if (img != null) {
outToNode.writeObject(img);
}
}
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The BufferedImage must be serialized. You can convert the image in to a byte array and once it reads the byte array, convert it back in to an image.
The sender is undoubtedly getting a NotSerializableException when calling writeObject() with a BufferedImage, because BufferedImage doesn't implement Serializable. Therefore you can't get one from a readObject() call either. You'll have to turn the BufferedImage into bytes for sending, and back again when receiving. Have a look at javax.imageio for one way to do this.
Related
I am using C# to create a client socket that should connect with a Java socket server. But no matter what I try the code always manages to send some sort of message, but for the Java server it's completely empty.
This is the C# client code:
using Godot;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class Scanning: Control
{
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
string toSend = "Handshake:Interface";
IPEndPoint serverAddress = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 429);
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clientSocket.Connect(serverAddress);
// Sending
int toSendLen = System.Text.Encoding.ASCII.GetByteCount(toSend);
byte[] toSendBytes = System.Text.Encoding.ASCII.GetBytes(toSend);
byte[] toSendLenBytes = System.BitConverter.GetBytes(toSendLen);
clientSocket.Send(toSendLenBytes);
clientSocket.Send(toSendBytes);
Console.WriteLine("Client received: " + rcv);*/
clientSocket.Close();
}
}
Java code that is responsible for working with the client:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
public class ClientHandler {
public PrintWriter out;
public BufferedReader in;
public Socket clientSocket;
public Thread thread;
public ClientHandler(Socket client) {
clientSocket = client;
System.out.println("Processing connection from " + clientSocket.getInetAddress());
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"));
ArrayList<String> cmdBuffer = new ArrayList<String>();
while (!Main.test.get()) {
String msg = in.readLine();
if(msg.startsWith("Handshake")) {
System.out.println("LOG: " + msg);
String[] work = msg.split(":");
if (!MessageChannel.clients.contains(work[1])) {
respond("1/I/Handshake successful for/" + work[1]);
respond("Connected: " + MessageChannel.clients);
MessageChannel.buffer.put(work[1], cmdBuffer);
MessageChannel.clients.add(work[1]);
}
} else if (msg.startsWith("Disconnect")) {
System.out.println("LOG: " + msg);
String[] work = msg.split(":");
MessageChannel.clients.remove(work[1]);
MessageChannel.buffer.remove(work[1]);
out.println("I/Disconnected/" + work[1]);
} else if(msg.startsWith("List")) {
System.out.println("LOG: " + msg);
respond("0/Connected: " + MessageChannel.clients);
} else {
String[] work = msg.split(":");
if (MessageChannel.clients.contains(work[0])){
if (work[1].equals("Lookup")) {
out.println(MessageChannel.buffer.get(work[0]).size() +"/Lookup:");
for (String e : MessageChannel.buffer.get(work[0])) {
out.println(e);
}
MessageChannel.buffer.replace(work[0], new ArrayList<String>());
} else {
System.out.println("LOG: " + msg);
MessageChannel.buffer.get(work[1]).add(work[2]);
respond("0/I/Success");
}
}
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
thread.start();
}
public void respond(String msg) {
out.println(msg);
System.out.println("LOGR: " + msg);
}
}
How can I fix that? Thanks in advance!
Can someone please resolve this issue.
Using JDK 1.8, I am trying to build a very simple chat application in Java using Sockets. In my client class as soon as following line executes
Message returnMessage = (Message) objectInputStream.readObject();
it throws exception.
Exception in thread "main" java.io.OptionalDataException
I am writing only objects of type Message to the stream and reading objects of type Message, since i wrote once, i dont think i am doing anything wrong in reading them in sequence.
Q. Also please let me know what is the best way to debug this type of application, how to hit the breakpoint in server while running client ?
Client
package com.company;
import sun.misc.SharedSecrets;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException{
Socket socket = new Socket("localhost", Server.PORT);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String readerInput = bufferedReader.readLine();
String[] readerInputTokens = readerInput.split("\u0020");
if(readerInputTokens.length != 2) {
System.out.println("Usage: Client <integer> <integer>");
} else {
Integer firstNumber = Integer.decode(readerInputTokens[0]);
Integer secondNumber = Integer.decode(readerInputTokens[1]);
Message message = new Message(firstNumber, secondNumber);
objectOutputStream.writeObject(message);
System.out.println("Reading Object .... ");
Message returnMessage = (Message) objectInputStream.readObject();
System.out.println(returnMessage.getResult());
socket.close();
}
}
public static boolean isInteger(String value) {
boolean returnValue = true;
try{Integer.parseInt(value);}
catch (Exception ex){ returnValue = false; }
return returnValue;
}
}
Server
package com.company;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public final static int PORT = 4446;
public static void main(String[] args) throws IOException, ClassNotFoundException {
new Server().runServer();
}
public void runServer() throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(PORT);
System.out.println("Server up & ready for connections ...");
// This while loop is necessary to make this server able to continuously in listning mode
// So that whenever a client tries to connect, it let it connect.
while (true){
Socket socket = serverSocket.accept(); // Server is ready to accept connectiosn;.
// Initialize Server Thread.
new ServerThread(socket).start();
}
}
}
Sever Thread
package com.company;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class ServerThread extends Thread {
private Socket socket = null;
ServerThread(Socket socket){
this.socket = socket;
}
public void run() {
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeChars("\n");
objectOutputStream.flush();
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Message message = (Message) objectInputStream.readObject();
multiplyNumbers(message);
System.out.println("Writing: "+message.toString());
objectOutputStream.writeObject(message);
System.out.println("Message Written");
socket.close();
} catch( IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
private void multiplyNumbers(Message message) {
message.setResult(message.getFirstNumber().intValue() * message.getSecondNumber().intValue());
}
}
Message Class
package com.company;
import java.io.Serializable;
public class Message implements Serializable {
private static final long serialVersionUID = -72233630512719664L;
Integer firstNumber = null;
Integer secondNumber = null;
Integer result = null;
public Message(Integer firstNumber, Integer secondNumber) {
this.firstNumber = firstNumber;
this.secondNumber = secondNumber;
}
public Integer getFirstNumber() {
return this.firstNumber;
}
public Integer getSecondNumber() {
return this.secondNumber;
}
public Integer getResult() {
return this.result;
}
public void setResult(Integer result) {
this.result = result;
}
#Override
public String toString() {
return "Message{" +
"firstNumber=" + firstNumber +
", secondNumber=" + secondNumber +
", result=" + result +
'}';
}
}
objectOutputStream.writeChars("\n");
Why are you writing a newline to an ObjectOutputStream? You're never reading it. Don't do that. Remove this wherever encountered.
I am creating a socket connection with a client utilizing android studio. I can successfully make a connection between the mobile device and the server, and my first debug message (Log.d("While Debugger", line)) successfully shows the input data from the server. However, the arraylist does not appear to adding the results, and my other debug messages are not providing any output!
To clarify further, when I call the returnData() method the temperature array is returned as null.
Any help will be much appreciated, and I will do my best to answer any questions asked of what I've written. Thanks!
package com.mycompany.myfirstapp;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
/**
* Created by seank on 15/07/2015.
*/
public class SocketExample {
ArrayList<Double> temperature = new ArrayList<Double>();
public SocketExample() throws IOException {
String serverHostname = new String ("192.168.1.143");
System.out.println ("Attemping to connect to host " +
serverHostname + " on port 10007.");
Socket echoSocket = null;
PrintWriter out = null;
BufferedReader in = null;
Log.d("Here", "Got to the streams");
try {
echoSocket = new Socket(serverHostname, 10007);
in = new BufferedReader(new InputStreamReader(
echoSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + serverHostname);
Log.e("Here","Don't know about host: " + serverHostname);
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for "
+ "the connection to: " + serverHostname);
Log.e("Here","Couldn't get I/O for "
+ "the connection to: " + serverHostname);
System.exit(1);
}
String line;
while( (line = in.readLine()) != null ) {
Log.d("While Debugger", line);
Double value = Double.parseDouble(line);
temperature.add(value);
}
if(temperature.size() == 0) {
Log.d("Numbers", "size = 0");
}
else {
Log.d("Numbers", String.valueOf(temperature.size()));
}
if(String.valueOf(temperature.size()) == null) {
Log.e("Numbers", "The temperature size is a null value");
}
// Close our streams
in.close();
out.close();
echoSocket.close();
}
public ArrayList<Double> returnData() {
return temperature;
}
public static void main(String[] args) throws IOException {
SocketExample socket = new SocketExample();
}
}
I think that, your program is blocking in the while loop, so your next debug is not executed.
You can try to add below code into the your while loop
if(temperature.size() == 0) {
Log.d("Numbers", "size = 0");
}
else {
Log.d("Numbers", String.valueOf(temperature.size()));
}
I want to create a server that can accept multiple connections and then bind 2 clients as a pair and forward the data between these 2 clients. But it is about multiple pairs of clients. I already have multithread server that can create a new thread for each new connected client. The problem for me is that these threads dont know of each other and somehow I have to connect 2 clients to a connection pair.
For now I just create these pair connection as this: I wait for the first client, then I wait for the second client and then open a thread for the input of client 1 that gets forwarded to client 2 and the other way around. This is not usable for multiple clients.
How can I do this decent?
The way I see it, a client would need to
establish a TCP(?) connection with your server,
identify itself
give the ID of the other client it wishes to talk to
The first that connects would have to be kept on hold (in some global table in your server) until the second client connects.
Once a pair of clients would have been recognized as interlocutors, you would create a pair of threads to forward the data sent by each client to the other one.
UPDATE: Example
ClientSocket.java
package matchmaker;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class ClientSocket implements Closeable {
private final Socket socket;
private final InputStream in;
private final OutputStream out;
private final String ownId;
private final String peerId;
public ClientSocket(Socket socket) throws IOException {
this.socket = socket;
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
DataInputStream din = new DataInputStream(in);
this.ownId = din.readUTF();
this.peerId = din.readUTF();
}
public ClientSocket(String server, int port, String ownId, String peerId)
throws IOException {
this.socket = new Socket(server, port);
this.socket.setTcpNoDelay(true);
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
this.ownId = ownId;
this.peerId = peerId;
DataOutputStream dout = new DataOutputStream(out);
dout.writeUTF(ownId);
dout.writeUTF(peerId);
}
public String getOwnId() {
return ownId;
}
public String getPeerId() {
return peerId;
}
public InputStream getInputStream() {
return in;
}
public OutputStream getOutputStream() {
return out;
}
#Override
public void close() throws IOException {
socket.close();
}
}
Matchmaker.java: the server
package matchmaker;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Matchmaker extends Thread {
private static final Logger LOG
= Logger.getLogger(Matchmaker.class.getName());
private final int port;
private final Map<ClientPair,ClientSocket> waiting = new HashMap<>();
public static void main(String[] args) {
try {
int port = 1234;
int st = 0;
for (String arg: args) {
switch (st) {
case 0:
switch (arg) {
case "-p":
st = 1;
break;
default:
System.out.println("Unknown option: " + arg);
return;
}
break;
case 1:
port = Integer.parseInt(arg);
st = 0;
break;
}
}
Matchmaker server = new Matchmaker(port);
server.start();
server.join();
} catch (InterruptedException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
private Matchmaker(int port) {
this.port = port;
setDaemon(true);
}
#Override
public void run() {
try {
ServerSocket server = new ServerSocket(port);
while (true) {
ClientSocket socket = new ClientSocket(server.accept());
ClientPair pair = new ClientPair(
socket.getOwnId(), socket.getPeerId());
ClientSocket other;
synchronized(this) {
other = waiting.remove(pair.opposite());
if (other == null) {
waiting.put(pair, socket);
}
}
if (other != null) {
LOG.log(Level.INFO, "Establishing connection for {0}",
pair);
establishConnection(socket, other);
} else {
LOG.log(Level.INFO, "Waiting for counterpart {0}", pair);
}
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
private void establishConnection(ClientSocket socket, ClientSocket other)
throws IOException {
Thread thread = new StreamCopier(
socket.getInputStream(), other.getOutputStream());
thread.start();
thread = new StreamCopier(
other.getInputStream(), socket.getOutputStream());
thread.start();
}
}
StreamCopier.java: a thread that reads from an InputStream and writes to an OutputStream
package matchmaker;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
public class StreamCopier extends Thread {
private static final Logger LOG
= Logger.getLogger(StreamCopier.class.getName());
private final InputStream in;
private final OutputStream out;
public StreamCopier(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
setDaemon(true);
}
#Override
public void run() {
LOG.info("Start stream copier");
try {
for (int b = in.read(); b != -1; b = in.read()) {
out.write(b);
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
} finally {
LOG.info("End stream copier");
try {
out.close();
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
}
ClientPair.java: a pair of client IDs
package matchmaker;
public class ClientPair {
private final String client1;
private final String client2;
public ClientPair(String client1, String client2) {
this.client1 = client1;
this.client2 = client2;
}
public String getClient1() {
return client1;
}
public String getClient2() {
return client2;
}
public ClientPair opposite() {
return new ClientPair(client2, client1);
}
#Override
public int hashCode() {
int hash = 5;
hash = 73 * hash + client1.hashCode();
hash = 73 * hash + client2.hashCode();
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ClientPair other = (ClientPair) obj;
return client1.equals(other.client1) && client2.equals(other.client2);
}
#Override
public String toString() {
return "[" + client1 + "," + client2 + "]";
}
}
ReaderClient.java: a sample client that reads from the socket and writes to standard output
package matchmaker;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ReaderClient {
private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());
public static void main(String[] args) {
try (ClientSocket client
= new ClientSocket("localhost", 1234, "reader", "writer")) {
Reader reader
= new InputStreamReader(client.getInputStream(), "UTF-8");
BufferedReader in = new BufferedReader(reader);
for (String s = in.readLine(); s != null; s = in.readLine()) {
System.out.println(s);
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
WriterClient.java: a sample client that writes to the socket
package matchmaker;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WriterClient {
private static final Logger LOG = Logger.getLogger(ReaderClient.class.getName());
public static void main(String[] args) {
try (ClientSocket client
= new ClientSocket("localhost", 1234, "writer", "reader")) {
Writer writer
= new OutputStreamWriter(client.getOutputStream(), "UTF-8");
PrintWriter out = new PrintWriter(writer);
for (int i = 0; i < 30; ++i) {
out.println("Message line " + i);
}
out.flush();
} catch (IOException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
}
I am wondering why it gets stuck on the following line, but it didn't used to get stuck when I was using a BufferedReader with an InputStreamReader:
input = new ObjectInputStream(socket.getInputStream());
Here is my client code:
import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class MtgTestRunsClient {
private JFrame frame = new JFrame("MTG Test Runs");
private static int PORT = 8901;
private Socket socket;
//private BufferedReader inFromServer;
//private PrintWriter outToServer;
private ObjectInputStream inFromServer;
private ObjectOutputStream outToServer;
private Planeswalker planeswalker;
public MtgTestRunsClient(String serverAddress) throws Exception {
// Setup networking
socket = new Socket(serverAddress, PORT);
//inFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//outToServer = new PrintWriter(socket.getOutputStream(), true);
inFromServer = new ObjectInputStream(socket.getInputStream());
outToServer = new ObjectOutputStream(socket.getOutputStream());
planeswalker = new BUGDelverPlaneswalker();
planeswalker.setOutputToServer(outToServer);
// Frame content
JPanel contentPane = new JPanel(new BorderLayout());
frame.setContentPane(contentPane);
frame.getContentPane().add(planeswalker.getStatusBar(), BorderLayout.SOUTH);
frame.getContentPane().add(planeswalker, BorderLayout.CENTER);
}
public void play() throws Exception {
//String response;
Object response;
try {
//response = inFromServer.readLine();
response = inFromServer.readObject();
if (response instanceof String ){
if( ((String)response).startsWith("WELCOME")) {
char mark = ((String)response).charAt(8);
frame.setTitle("MTG Test Runs - Player " + mark);
}
}
while (true) {
//response = inFromServer.readLine();
response = inFromServer.readObject();
if (response instanceof String ){
if (((String)response).startsWith("OPPONENT_MOVED")) {
planeswalker.getStatusBar().setStatusString("Opponent "+((String)response).substring(15), false, true);
} else if (((String)response).startsWith("GAME_OVER")) {
break;
} else if (((String)response).startsWith("MESSAGE")) {
String messageText = ((String)response).substring(8);
planeswalker.getStatusBar().setStatusString(messageText, false, true);
}
}else if(response instanceof Planeswalker){
planeswalker.setOpponent((Planeswalker)response);
}
}
outToServer.writeObject("QUIT");
outToServer.flush();
}
finally {
socket.close();
}
}
private boolean wantsToPlayAgain() {
int response = JOptionPane.showConfirmDialog(frame,
"Want to play again?",
"Tic Tac Toe is Fun Fun Fun",
JOptionPane.YES_NO_OPTION);
frame.dispose();
return response == JOptionPane.YES_OPTION;
}
/**
* Runs the client as an application.
*/
public static void main(String[] args) throws Exception {
while (true) {
String serverAddress = (args.length == 0) ? "localhost" : args[1];
MtgTestRunsClient client = new MtgTestRunsClient(serverAddress);
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setExtendedState(client.frame.getExtendedState()|JFrame.MAXIMIZED_BOTH);
client.frame.setVisible(true);
client.frame.repaint();
client.play();
if (!client.wantsToPlayAgain()) {
break;
}
}
}
}
Here is my server code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* A server for a network multi-player tic tac toe game. Modified and
* extended from the class presented in Deitel and Deitel "Java How to
* Program" book. I made a bunch of enhancements and rewrote large sections
* of the code. The main change is instead of passing data between the
* client and server, I made a TTTP (tic tac toe protocol) which is totally
* plain text, so you can test the game with Telnet (always a good idea.)
* The strings that are sent in TTTP are:
*
* Client -> Server Server -> Client
* ---------------- ----------------
* MOVE (0 <= n <= 8) WELCOME (char in {X, O})
* QUIT VALID_MOVE
* OTHER_PLAYER_MOVED
* VICTORY
* DEFEAT
* TIE
* MESSAGE
*
* A second change is that it allows an unlimited number of pairs of
* players to play.
*/
public class MtgTestRunsServer {
/**
* Runs the application. Pairs up clients that connect.
*/
public static void main(String[] args) throws Exception {
ServerSocket listener = new ServerSocket(8901);
System.out.println("MTG Test Runs Server is Running");
try {
while (true) {
Game game = new Game();
Game.Player player1 = game.new Player(listener.accept(), '1');
Game.Player player2 = game.new Player(listener.accept(), '2');
player1.setOpponent(player2);
player2.setOpponent(player1);
game.currentPlayer = player1;
player1.start();
player2.start();
}
} finally {
listener.close();
}
}
}
/**
* A two-player game.
*/
class Game {
Player currentPlayer;
public synchronized boolean legalMove(Player player, String move) {
if (player == currentPlayer ) {
currentPlayer = currentPlayer.opponent;
currentPlayer.otherPlayerMoved(move);
return true;
}
return false;
}
class Player extends Thread {
char playerNo;
Player opponent;
Socket socket;
//BufferedReader input;
//PrintWriter output;
ObjectInputStream input;
ObjectOutputStream output;
public Player(Socket socket, char playerNumber) {
this.socket = socket;
this.playerNo = playerNumber;
try {
//input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//output = new PrintWriter(socket.getOutputStream(), true);
output = new ObjectOutputStream(socket.getOutputStream());
output.writeObject("WELCOME " + playerNumber);
output.flush();
output.writeObject("MESSAGE Waiting for opponent to connect");
output.flush();
**input = new ObjectInputStream(socket.getInputStream());** // Must do this after constructed ObjectOutputStream above
//output.println("WELCOME " + playerNumber);
} catch (IOException e) {
System.out.println("Player died: " + e);
}
}
/**
* Accepts notification of who the opponent is.
*/
public void setOpponent(Player opponent) {
this.opponent = opponent;
}
/**
* Handles the otherPlayerMoved message.
*/
public void otherPlayerMoved(String move) {
//output.println("OPPONENT_MOVED " + move);
try {
output.writeObject("OPPONENT_MOVED " + move);
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* The run method of this thread.
*/
public void run() {
try {
// The thread is only started after everyone connects.
//output.println("MESSAGE All players connected");
output.writeObject("MESSAGE All players connected");
output.flush();
// Tell the first player that it is her turn.
if (playerNo == '1') {
//output.println("MESSAGE Your move");
output.writeObject("MESSAGE Your move");
output.flush();
}
// Repeatedly get commands from the client and process them.
while (true) {
//String command = input.readLine();
Object command;
try {
command = input.readObject();
if(command instanceof String){
if (((String)command).startsWith("MOVE")) {
String move = ((String)command).substring(5);
if (legalMove(this, move)) {
//output.println("VALID_MOVE");
output.writeObject("VALID_MOVE");
} else {
output.writeObject("MESSAGE INVALID_MOVE");
//output.println("MESSAGE INVALID_MOVE");
}
} else if (((String)command).startsWith("QUIT")) {
return;
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (IOException e) {
System.out.println("Player died: " + e);
} finally {
try {socket.close();} catch (IOException e) {}
}
}
}
}
Straight from the javadoc:
Creates an ObjectInputStream that reads from the specified InputStream. A serialization stream header is read from the stream and verified. This constructor will block until the corresponding ObjectOutputStream has written and flushed the header.
You need to construct the a ObjectOutputStream before the ObjectInputStream. Otherwise you get a deadlock because of the stream header written and read by the constructors.