Sending selfmade objects with Java sockets - java

I'm trying to send an ArrayList from a server to a client, but it doesn't work. The server does send ints. If the client send the list, it works too.
Here is the object i try to send (only the fields)
public class DrawingPoint implements Serializable
{
private double x;
private double y;
private boolean paint;
Color c;
private int dikte;
boolean gum;
public DrawingPoint(double x, double y, boolean paint, Color c, int dikte,
boolean gum) {
super();
this.x = x;
this.y = y;
this.paint = paint;
this.c = c;
this.dikte = dikte;
this.gum = gum;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public boolean isPaint() {
return paint;
}
public int getDikte() {
return dikte;
}
//getters and setters
}
Here is the code for the server and client
server (this isn't the server but this class recieves and sends stuff. The server makes an array with these object and it let's it send.)
package MultiplayerPaint.socket.server;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.Socket;
import java.util.ArrayList;
import MultiplayerPaint.DrawingPoint;
public class ThreadClass extends Thread implements Runnable, Serializable{
transient Socket socket;
transient Server server;
private transient ObjectInputStream inputFromClient;
private transient ObjectOutputStream outputToClient;
public ArrayList<DrawingPoint> list = new ArrayList<>();
String name;
public int nummer;
transient private boolean changed = false;
public ThreadClass(Socket socket, Server server, int nummer)
{
this.server = server;
this.nummer = nummer;
try {
inputFromClient = new ObjectInputStream(socket.getInputStream());
outputToClient = new ObjectOutputStream(socket.getOutputStream());
runOnce();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
while(true)
{
try {
Thread.sleep(1000/5);
ArrayList<DrawingPoint> l = (ArrayList<DrawingPoint>) inputFromClient.readObject();
list = l;
changed = true;
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
}
public void runOnce()
{
try {
outputToClient.writeInt(nummer);
outputToClient.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean isChanged() {
return changed;
}
public void setChanged(boolean changed) {
this.changed = changed;
}
public void sending(ThreadClass[] sturen) {
try {
for(ThreadClass t : sturen)
{
outputToClient.writeObject(t);
}
outputToClient.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is the client
package MultiplayerPaint.socket;
import java.awt.Color;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import MultiplayerPaint.DrawingPoint;
import MultiplayerPaint.PaintModel;
import MultiplayerPaint.socket.server.Server;
import MultiplayerPaint.socket.server.ThreadClass;
public class Client
{
private ObjectInputStream inputFromClient;
private ObjectOutputStream outputToClient;
int aantal= -1;
int nummer;
public Client(final PaintModel m)
{
try {
Socket socket = new Socket(Server.HOST, Server.PORT);
outputToClient = new ObjectOutputStream(socket.getOutputStream());
inputFromClient = new ObjectInputStream(socket.getInputStream());
nummer = inputFromClient.readInt();
m.nummer = nummer;
} catch (IOException e1) {
e1.printStackTrace();
}
Thread sturen = new Thread(new Runnable() {
#Override
public void run() {
try {
while(true)
{
ArrayList<DrawingPoint> l = new ArrayList<>();
l.addAll(m.getPoints());
outputToClient.writeObject(l);
outputToClient.flush();
aantal = m.getPoints().size();
Thread.sleep(1000/5);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
sturen.start();
Thread ontvangen = new Thread(new Runnable() {
#Override
public void run() {
while(true)
{
try {
ArrayList<ThreadClass> l = new ArrayList<>();
for(int i = 0; i< 4; i++)
{
l.add((ThreadClass) inputFromClient.readObject());
}
Iterator<ThreadClass> it = l.iterator();
while(it.hasNext())
{
ThreadClass t = it.next();
if(t.nummer == nummer)
{
System.out.println(t.nummer + " " + t.list.size());
for(DrawingPoint p: t.list)
{
if(p == null) System.out.println("null");
else System.out.println(t.nummer + " X " + p.getX() + " Y " + p.getY());
}
continue;
}
System.out.println(t.nummer + " " + t.list.size());
m.otherPoints.put(t.nummer, t.list);
Thread.sleep(1000/5);
}
}
catch (Exception e1)
{
e1.printStackTrace();
}
}
}
});
ontvangen.start();
}
}

To send objects over sockets I would reckommend you to serialize your objects first and send them, after that when your objects are received they are deserialized.
For example I convert my objects to JSON format and save it in a string, send the string to server, the server deserializes it to a java object then answers again with a serialized object and so on.
//Client side
Person person;
String stringJSON = serializer.serialize( person );
socket.getOutputStream().println(stringJSON);
//Server Side
String stringJSON = socket.getInputStream().readLine();
Person person = JSONDeserializer.deserialize( stringJSON )
I find this way much easier, if intrested I use this to serialize/desrialize http://flexjson.sourceforge.net/
By the way you have to provide setters and getters for your objects.

Related

java.io.EOFException when using sockets with blockchain in java

i have to do a practice in my uni, it must create a blockchain using sockets and serialization in a "simple way". But when exiting the loop (typing "NO") It creates a EOF exception that i cannot solve, while closing the socket(s.close()). i would appreciate some help, i am not vry good at java. here are my classes.
Client
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client implements Runnable{
public static void main(String[] args) throws Exception {
(new Thread(new Client())).start();
}
public static MedicalReport createReport(){
return new MedicalReport(10,"pepe","id","record");
}
#Override
public void run() {
// int port = 12345;
// String computer = "localhost";
try{
Socket s = new Socket("localhost", 12348);
ObjectOutputStream p = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
/* PrintWriter print = new PrintWriter(s.getOutputStream());
print.println("ready");
print.flush();*/
//manda informe al servidor serializado y espera respuesta
boolean stop = false;
while(!stop){
try{
MedicalReport report = createReport();
p.writeObject(report);
p.flush();
p.reset();
System.out.println("Do you want to continue? Yes or No");
Scanner in1 = new Scanner (System.in);
String answer="";
if(in1.hasNextLine())
answer = in1.nextLine();
if(!answer.equalsIgnoreCase("yes")){
System.out.println(report);
stop = true;
}
}
catch(Exception e){
System.out.println(e);
}
}
try{
s.close();
}
catch(Exception e){
System.out.println(e);
}
}catch(Exception e){
System.out.println(e);
}
}
}
SERVER
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
public class Server {
public static void main(String[] args)
throws Exception
{
ArrayList<Block> blockChain = new ArrayList<>();
try{
ServerSocket ss = new ServerSocket(12348);
Socket s = ss.accept();
ObjectOutputStream out = new ObjectOutputStream(s.getOutputStream());
ObjectInputStream in = new ObjectInputStream(s.getInputStream());
/* Scanner scanner = new Scanner(s.getInputStream());
String text = scanner.nextLine();*/
int i = 0;
int previousHash = 0;
while (i != 20){
MedicalReport rp = (MedicalReport)in.readObject();
Block block = new Block(rp,previousHash);
blockChain.add(block);
System.out.println("Block " + blockChain.size() + " added to blockchain");
System.out.println(blockChain.get(i));
previousHash = block.getBlockHash();
System.out.println(blockChain);
i++;
}
try{
ss.close();
}
catch(Exception e){
System.out.println(e);
}
}catch(Exception e){
System.out.println(e);
}
}
}
It looks like the error is while closing the socket, any idea?
EDIT REST OF THE CODE
MEDICAL REPORT
import java.io.Serializable;
public class MedicalReport implements Serializable {
private int age;
private String name;
private String id;
private String record;
private static final long serialVersionUID = 1L;
public MedicalReport(){super();}
public MedicalReport(int age, String name, String id, String record) {
super();
this.age = age;
this.name = name;
this.id = id;
this.record = record;
}
public String getRecord(){
return this.record;
}
public String toString(){
return this.name + ". \n" + this.age + ". \n" + this.id + ". \n" + this.record;
}
}
BLOCK
public class Block {
private int blockHash;
private int previousHash;
private MedicalReport report;
//Block Constructor.
public Block(MedicalReport report,int previousHash ) {
this.previousHash = previousHash;
this.report = report;
this.blockHash = report.hashCode();
}
public int getPreviousHash() {
return previousHash;
}
public MedicalReport getReport() {
return report;
}
public int getBlockHash() {
return blockHash;
}
}
EDIT 2
FIRST QUESTION SOLVED. Now i get this error when exiting the loop:
java.net.SocketException: Connection reset by peer: socket write error
readObject() throws EOFEzception when the peer has closed the connection. This is normal. Catch it and stop reading. There is no problem here to solve.
IMPORTANT: As EJP said EOFException is normal and you can control the flow of your code with it but if you still want to know how to do in the way you asked here it is. REMEMBER THIS IS JUST FULFILL YOUR QUESTION AND NOT ADVISED TO DO SO.
On Server Class
Replace
MedicalReport rp = (MedicalReport)in.readObject();
With
MedicalReport rp;
if((rp = (MedicalReport)in.readObject())==null) break;
On Client Class
ADD
p.writeObject(null);
Just above the s.close(); statement
You must know that when a peer close the connection normally then
read() returns -1,
readLine() returns null,
readXXX() throws EOFException for any other XXX
And A write will throw an IOException

Socket sends message only once

Code below works and sends message at scheduled time but I think it isn't a good solution to open new socket every time timer executes scheduled task. What I would like is to open socket in run method only once and access it in SendMessage class whenever new instance of class is made in timer. That way it doesn't work, it only sends one message and then stops sending. Also I would be happy for some critics about code or tips for making it thread safe.
public class Client implements Runnable{
// Client Constructor here
#Override
public void run(){
//SENDS ONLY ONE MESSAGE
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
Timer timer = new Timer();
timer.schedule(new SendMessage(), 0, 1000/mps);
}
private class SendMessage extends TimerTask{
private int id;
#Override
public void run() {
try
{ // THIS WORKS FINE, SENDS MESSAGES AT SCHEDULED TIME
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
OutputStream outToServer = pitcherSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeInt(id);
out.flush();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
EDIT: WHOLE CODE
CLIENT
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class Pitcher implements Runnable{
private int port;
private int mps;
private int size;
private String hostname;
private List<Integer> messageIds = Collections.synchronizedList(new ArrayList<Integer>());
private Socket pitcherSocket;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Pitcher(int port, int mps, int size, String hostname) {
this.port = port;
this.mps = mps;
this.size = size;
this.hostname = hostname;
}
#Override
public void run(){
System.out.println("Pitcher running...");
System.out.println();
Timer timer = new Timer();
timer.schedule(new SendMessage(), 0, 1000/mps);
timer.schedule(new DisplayStatistics(), 0, 1000/mps);
}
//Nested class that sends messages
private class SendMessage extends TimerTask{
private int numberOfSentMessages = 0;
private int id;
#Override
public void run() {
try {
pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
OutputStream outToServer = pitcherSocket.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
//send message size
out.writeInt(size);
//message id is same as number of the sent message
id = numberOfSentMessages + 1;
out.writeInt(id);
messageIds.add(id);
//get system timestamp
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest-
byte[] rest = new byte[size - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytse) - timestamp(8 bytes)
out.write(rest);
out.flush();
numberOfSentMessages++;
InputStream inFromServer = pitcherSocket.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
Integer catcherMessageSize = in.readInt();
Integer catcherId = in.readInt();
long catcherTimestamp = in.readLong();
System.out.println("Sent message: " + size + " " + id + " " + currentTimestamp + "...");
System.out.println("Received message: " + catcherMessageSize + " " + catcherId + " " + catcherTimestamp + "...");
System.out.println();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
}
SERVER
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class Catcher implements Runnable{
private int port;
private String bind;
private ServerSocket serverSocket;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Catcher(int port, String bind) {
this.port = port;
this.bind = bind;
}
#Override
public void run() {
System.out.println("Catcher running...");
System.out.println();
try {
serverSocket = new ServerSocket(port, 100, InetAddress.getByName(bind));
}
catch (IOException e1) {
e1.printStackTrace();
}
while(true){
try
{
Socket server = serverSocket.accept();
DataInputStream in = new DataInputStream(server.getInputStream());
Integer pitcherMessageSize = in.readInt();
Integer pitcherId = in.readInt();
long pitcherTimestamp = in.readLong();
DataOutputStream out = new DataOutputStream(server.getOutputStream());
//message id and size are sent back
out.writeInt(pitcherMessageSize);
out.writeInt(pitcherId);
//send back current time
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest
byte[] rest = new byte[pitcherMessageSize - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytes) - timestamp(8 bytes)
out.write(rest);
out.flush();
System.out.println("Received message: " + pitcherMessageSize + " " + pitcherId + " " + pitcherTimestamp + "...");
System.out.println("Sent message: " + pitcherMessageSize + " " + pitcherId + " " + currentTimestamp + "...");
System.out.println();
//server.close();
}
catch(SocketTimeoutException s){
System.out.println("Socket timed out!");
break;
}
catch(IOException e){
e.printStackTrace();
break;
}
}
}
}
Have you thought about making both socket and the DataOutputStream member variables of SendMessage. This is some code to give you a rough start. You will probably want to put some enhancements like checking whether the socket is open and being able to create a new one if the current one is closed...
private class SendMessage extends TimerTask {
private int id = 10;
private Socket pitchSocket;
private DataOutputStream out;
public SendMessage(Socket socket) {
this.pitchSocket = socket;
try{
out = new DataOutputStream(pitchSocket.getOutputStream());
} catch(IOException e) {
e.printStackTrace();
}
}
#Override
public void run() {
try {
out.writeInt(id);
out.flush();
} catch(IOException e) {
e.printStackTrace();
}
}
}
After being able to view the whole code I think that you definitely have some threading issues, though I think they are more heavily on the server side rather than the client side. Your server is single threaded. That means that you can only deal with one request at a time. You want a multithreaded server. I've refactored your code to create an example of Catcher which is multithreaded. I'm using the Thead class to do all of this which may be a little old fashioned. You might want to take a look at java.util.concurrent, they will probably have a more up to date.
package clientserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class Catcher implements Runnable{
private int port;
private String bind;
private ServerSocket serverSocket;
public Catcher(int port, String bind) {
this.port = port;
this.bind = bind;
}
#Override
public void run() {
System.out.println("Catcher running...");
System.out.println();
try {
serverSocket = new ServerSocket(port, 100, InetAddress.getByName(bind));
}
catch (IOException e1) {
e1.printStackTrace();
}
while(true){
try
{
new Thread(new CatcherHandler(serverSocket.accept())).start();
Thread.sleep(1000);
}
catch(SocketTimeoutException s){
System.out.println("Socket timed out!");
break;
}
catch(IOException e){
e.printStackTrace();
break;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] argv){
new Thread( new Catcher(8093, "localhost")).start();;
}
}
class CatcherHandler implements Runnable{
Socket server;
DataOutputStream out;
DataInputStream in;
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public CatcherHandler(Socket server) {
super();
this.server = server;
try {
in = new DataInputStream(server.getInputStream());
out = new DataOutputStream(server.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void run() {
try{
if(in.available() > 0){
Integer pitcherMessageSize = in.readInt();
Integer pitcherId = in.readInt();
long pitcherTimestamp = in.readLong();
//message id and size are sent back
out.writeInt(pitcherMessageSize);
out.writeInt(pitcherId);
//send back current time
long currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest
byte[] rest = new byte[pitcherMessageSize - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytes) - timestamp(8 bytes)
out.write(rest);
out.flush();
System.out.println("Received message: " + pitcherMessageSize + " " + pitcherId + " " + pitcherTimestamp + "...");
System.out.println("Sent message: " + pitcherMessageSize + " " + pitcherId + " " + currentTimestamp + "...");
System.out.println();
Thread.sleep(1000);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{}
//server.close();
}
}
Additionally I refactored your client to be able to use one socket and be tread safe. Now SendMessage takes in a DataInputStream and a DataOutputSteam as it's arguments.
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class Pitcher implements Runnable{
private int port;
private int mps;
private int size;
private String hostname;
private List<Integer> messageIds = Collections.synchronizedList(new ArrayList<Integer>());
private Socket pitcherSocket;
private DataOutputStream out;
private DataInputStream in;
//constatns, integer is 4 bytes, long is 8 bytes
private static final int INT_SIZE = 4;
private static final int LONG_SIZE = 8;
public Pitcher(int port, int mps, int size, String hostname) {
this.port = port;
this.mps = mps;
this.size = size;
this.hostname = hostname;
try {
this.pitcherSocket = new Socket(InetAddress.getByName(hostname), port);
out = new DataOutputStream(pitcherSocket.getOutputStream());
in = new DataInputStream(pitcherSocket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] argv) throws Exception{
for(int i = 0; i < 10; i++){
new Thread(new Pitcher(8093, 1, 200, "localhost")).start();
Thread.sleep(1000);
}
Thread.sleep(10000);
}
#Override
public void run(){
System.out.println("Pitcher running...");
System.out.println();
Timer timer = new Timer();
timer.schedule(new SendMessage(out, in), 0, 1000);
//timer.schedule(new DisplayStatistics(), 0, 1000);
}
//Nested class that sends messages
private class SendMessage extends TimerTask{
private int numberOfSentMessages = 0;
private int id;
private DataOutputStream out;
private DataInputStream in;
public SendMessage(DataOutputStream out, DataInputStream in){
this.out = out;
this.in = in;
}
#Override
public void run() {
try {
long currentTimestamp = 0L;
synchronized(out){
//send message size
out.writeInt(size);
//message id is same as number of the sent message
id = numberOfSentMessages + 1;
out.writeInt(id);
messageIds.add(id);
//get system timestamp
currentTimestamp = System.currentTimeMillis();
out.writeLong(currentTimestamp);
//fill in the rest-
byte[] rest = new byte[size - 2 * INT_SIZE - LONG_SIZE]; //message size(default 300 bytes) - size(4 bytes) - message id(4 bytse) - timestamp(8 bytes)
out.write(rest);
out.flush();
}
numberOfSentMessages++;
long catcherTimestamp = 0L;
Integer catcherMessageSize;
Integer catcherId;
synchronized(in){
catcherMessageSize = in.readInt();
catcherId = in.readInt();
catcherTimestamp = in.readLong();
}
System.out.println("Sent message: " + size + " " + id + " " + currentTimestamp + "...");
System.out.println("Received message: " + catcherMessageSize + " " + catcherId + " " + catcherTimestamp + "...");
System.out.println();
Thread.sleep(1000);
}catch(IOException e)
{
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
The Java Socket class is not thread safe. To have multiple threads access the same Socket object you would need to synchronize their actions. This could be done by providing all your SendMessage-threads with a common object that would then act as a lock. You would need an object for each socket operation you are planning to use (e.g. read and write). Then, refactor every action that does a call to the Socket object into separate methods and synchronize them around that object. E.g. for the read operation you could have a method called read() inside SendMessage that calls Socket.read and synchronize this method around the lock-object for read.
private class SendMessage extends TimerTask{
private Object readLock;
private Socket socket;
public SendMessage(Object readLock, Socket socket) {
this.readLock = readLock;
this.socket = socket;
}
public void readFromSocket() {
synchronized(readLock) {
socket.read();
}
}
#Override
public void run() {
readFromSocket();
// do other stuff
}
}

How to create a java Server that accepts client connections and then build a relay connection for a client pair

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);
}
}
}

Java network object serialization

Im trying to send an object from client to server and one of the object states is a vector and the other is a string. I can access the string on the Server side, but the vector contents is zero on the server side..Can someone help me out please..
// Server
import java.net.*;
import java.util.Vector;
import java.io.*;
public class SimpleServer {
public static void main(String args[]) {
int port = 2002;
try {
System.out.println("Hello");
ServerSocket ss = new ServerSocket(port);
Socket s = ss.accept();
System.out.println("Hello 2");
InputStream is = s.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
testobject to = (testobject)ois.readObject();
System.out.println("Vector size : " + to.vectorX.size() + " and object.id : "
+ to.id);
/* if (to != null) {
for(int i = 0; i < to.vectorX.size(); ++i )
System.out.println("Output 1 : " + to.vectorX.elementAt(i));
} */
is.close();
s.close();
ss.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// Client
import java.net.*;
import java.io.* ;
import java.util.Vector;
public class SimpleClient {
protected static Vector<String> vectorX = new Vector<String>();
public SimpleClient(){
vectorX.addElement("hello");
vectorX.add("goodbye");
vectorX.add("finally");
}
public static void main(String args[]) {
try {
new SimpleClient();
Socket s = new Socket("localhost", 2002);
OutputStream os = s.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
testobject to = new testobject(1, "theID", vectorX );
System.out.println(vectorX.size());
oos.writeObject(to);
// oos.writeObject(new String("another object from the client"));
oos.close();
os.close();
s.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
//testobject
import java.net.*;
import java.io. * ;
import java.util.Vector;
class testobject implements Serializable {
int value;
String id;
Vector<String> vectorX;
public testobject(int v, String s, Vector<String> vector) {
this.value = v;
this.id = s;
this.vectorX = new Vector<String>();
}
}
The constructor for your testobject is not using the vector argument. It is rather assigning the vectorX ivar to a new instance, ignoring the parameter provided by the caller:
public testobject(int v, String s, Vector<String> vector) {
this.value = v;
this.id = s;
this.vectorX = new Vector<String>(); // This is bad
}
You should instead use:
public testobject(int v, String s, Vector<String> vector) {
this.value = v;
this.id = s;
this.vectorX = vector;
}
Note: It's not common for class names in Java to be all lowercase, or to start with a lowercase letter. As an aside, I think you should rename your class to TestObject.

How do I print XML sended or received in Apache XML-RPC

I'm running a simple client/server XML-RPC app to understand better the Apache XMLRPC library.
But I would like to be able to print or debug the XML output that the client sends and the XML received at server. How could I find these data??
//StartServer.java
public class StartServer {
public static void main(String args[]) throws Exception {
Server server = new Server();
}
}
//Server.java
import org.apache.xmlrpc.server.PropertyHandlerMapping;
import org.apache.xmlrpc.server.XmlRpcServer;
import org.apache.xmlrpc.server.XmlRpcServerConfigImpl;
import org.apache.xmlrpc.webserver.WebServer;
public class Server {
private static final int port = 3000;
public Server() throws Exception {
WebServer webServer = new WebServer(port);
XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer();
PropertyHandlerMapping phm = new PropertyHandlerMapping();
phm.addHandler("reply", ReplyClass.class);
xmlRpcServer.setHandlerMapping(phm);
XmlRpcServerConfigImpl serverConfig =
(XmlRpcServerConfigImpl) xmlRpcServer.getConfig();
serverConfig.setEnabledForExtensions(true);
serverConfig.setContentLengthOptional(false);
webServer.start();
}
}
//ReplyClass.java
public class ReplyClass {
public int reply(Object params[]){
for(int i = 0; i< params.length; i++){
System.out.println( "Params :"+params[i].toString());
}
return 0;
}
public int foo(int x){
System.out.println("foo : "+ x);
return 1;
}
}
//XMLRPCtest
import java.net.URL;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.client.XmlRpcLocalTransportFactory;
import org.apache.xmlrpc.client.XmlRpcCommonsTransportFactory;
public class XMLRPCtest {
private XmlRpcClient client;
public XMLRPCtest() {
try {
XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setServerURL(new URL("http://localhost:3000"));
config.setEnabledForExtensions(true);
client = new XmlRpcClient();
client.setConfig(config);
} catch (Exception exception) {
exception.printStackTrace();
}
}
public Object execute(String command, Object[] params) {
try {
Object reply = client.execute(command, params);
return reply;
} catch (XmlRpcException e) {
e.printStackTrace();
return null;
}
}
public static void main(String args[]) {
try {
XMLRPCtest client = new XMLRPCtest();
int data[] = {};
Object[] params = new Object[]{1};
Integer result = (Integer) client.execute("reply.foo", params);
System.out.println("Result: " + result);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}

Categories

Resources