How to send an OBJECT over TCP in java? - java

I'm writing a program to send an object from one class to another class. Here is a short sample example of my program to represent the problem. As you can see the object to send from server to client is Student class which has been defined separately in each class(Server/Client). I have examined this code by sending an ArrayList which works fine but when it comes to a class type which defined by myself i'm receiving this error:
Exception in thread "main" java.lang.ClassCastException: ServerSide$1Student cannot be cast to ClientSide$1Student
at ClientSide.main(ClientSide.java:29)
Here is the code for Server side:
import java.io.*;
import java.net.*;
public class ServerSide {
public static void main(String[] args) {
class Student implements Serializable
{
int id;
public Student(int num){id=num;}
public void setID(int num){id=num;}
public void Print(){System.out.println("id = " + id);}
}
try
{
Student a = new Student(3);
ServerSocket myServerSocket = new ServerSocket(9999);
Socket skt = myServerSocket.accept();
try
{
ObjectOutputStream objectOutput = new ObjectOutputStream(skt.getOutputStream());
objectOutput.writeObject(a);
}
catch (IOException e)
{
e.printStackTrace();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
And for the client side is:
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientSide {
public static void main(String[] args)
{
class Student implements Serializable
{
int id;
public Student(int num){id=num;}
public void setID(int num){id=num;}
public void Print(){System.out.println("id = " + id);}
}
try {
Socket socket = new Socket("10.1.1.2",9999);
try {
ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());
try {
Object object =(Student) objectInput.readObject();
Student tmp = (Student) object;
tmp.Print();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Edit:
I moved them to same file and added serialise ID. It works fine.

Having two classes with the same name is not enough. The two classes need to have
the same package
be in the same outer class if any
have the same serialVersionUID.
I suggest you have a single, stand alone class which is common for both the client and the server. In a more complex project you might consider building these common components in a module which both the client and server modules depend on.

You cannot ever deserialize a stream representing an instance of class X into an instance of class Y.
To solve your problem, you need to move the code for the Student class to another file, say Student.java, and use that single class on your client code and on your server code.
Note that if you modify your class, in most cases you will need to redeploy the server (otherwise the client would send the server an stream representing an instance of class that is known only to the client).

You are referencing two different classes. Student which is an inner of ClientSide and Student which is an inner class of ServerSide. You should move the Student class to a different file.

Related

Java variable doesn't get updated by different instances/threads

So I have a pretty complex (for me) project for my uni. I have to essentially create a Spotify-like program using the Event Delivery System with sockets and threads. To put my problem simply, I want to run 3 broker instances at the same time. Broker.java class extends the Node.java class in which there is an ArrayList:
public static ArrayList<Broker> BrokerList= new ArrayList<Broker>();
in which I want to add each broker node as I open it. Until I solve my problem my Broker Main class looks like this and I want to run 3 instances of this main where I manually change the port each time before I run it:
public class BrokMain {
public static void main(String[] args) throws InterruptedException {
Broker brok = new Broker(4446, "localhost");
brok.startServer();
}
}
and the startServer method inside Broker class looks like this:
public void startServer() {
ServerSocket listenerSocket = null;
BrokerList.add(this);
this.brokHash = hashString(ipAddress + Integer.toString(this.port));
try {
listenerSocket = new ServerSocket(port);
while (true) {
System.out.println("Server is up and waiting ");
listenerSocket.accept();
Thread t = new Thread(this);
t.start();
t.join();
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
So clearly in this method I add this broker to the BrokerList, but even if I run 3 different instances of the brokMain, whenever I try to print the size of the list, I get 1. I feel like this is a thread sychronization issue? Any suggestions?

Best way to create an Xmpp connection and passing the Instance without Re-creation

I have class called XmppChatManager which have all the necessary methods like initializingConnection() and sendOneToOneMessage(), other classes that need to use this class need to do something like this:
XmppChatManager xmppchatmanager = new XmppChatManager(this, userId, password);
runOnUiThread(new Runnable() {
public void run() {
Thread thread = new Thread(){
public void run(){
try {
xmppchatmanager.initializingConnection();
} catch (IOException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
} catch (SmackException e) {
e.printStackTrace();
}
}
};
thread.start();
}
});
This is pretty much all I need to get started, the issue i'm having is when I try calling the sendOneToOneMessage() method from the chatClass, I have to get the instance of the created connection because Smack Error will occur if I try reconnecting when the connection is already initiated! So I need to make available the instance of that initiated connection by creating a method called getInstance() I guess this might be simple but I have tried but I'm not getting it. Any one with better way of handling such?
Make your xmppchatmanager be singleton,for example
public class XmppChatManager{
static class Loader{
static XmppChatManager sInstance = new XmppChatManaget();
}
public static XmppChatManager getInstance(){
return Loader.sInstance;
}
}

RMI: Proper synchronization when Server is accessed by multiple clients

I started working with Java RMI a couple of days ago. I am wondering if the following example is properly synchronized.
Consider the following Server class which provides resource strings to clients. It shall never provide the same resource twice, therefor it stores the provided strings in a list. This is the ServerEngine class:
package dummy;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.LinkedList;
public class ServerEngine implements Server {
private final String s1 = "Resource Object 1";
private final String s2 = "Resource Object 2";
private final LinkedList<String> list = new LinkedList<>();
private final int timer = 5000;
public static void main(String[] args) {
try {
String name = "server";
ServerEngine engine = new ServerEngine();
Server stub = (Server) UnicastRemoteObject.exportObject(engine, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind(name, stub);
System.out.println("ServerEngine bound");
} catch (Exception e) {
System.err.println("ServerEngine exception:");
}
}
#Override
public String getResource() throws RemoteException {
Object lock = new Object();
if ( ! list.contains(s1)) {
synchronized (lock) {
// wait to ensure concurrency
try {
lock.wait(timer);
} catch (InterruptedException ex) {}
}
list.add(s1);
return s1;
}
if ( ! list.contains(s2)) {
list.add(s2);
return s2;
}
return null;
}
}
The Server interface:
package dummy;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Server extends Remote {
public String getResource(boolean synced) throws RemoteException;
}
and the Client:
package dummy;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Client {
public static void main(String[] args) {
try {
String name = "server";
Registry registry = LocateRegistry.getRegistry();
Server server = (Server) registry.lookup(name);
boolean sync = args.length > 0;
String s = server.getResource(sync);
System.out.println("Resource: " + s);
} catch (Exception e) {
System.err.println("Client exception:");
}
}
}
The ServerEngine is implemented in such a way that it will cause a concurrency issue. If two clients are started from two different VMs within five seconds then they both will get the same String returned.
From what I have researched so far, this is my approach to solve the issue:
package dummy;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.LinkedList;
public class ServerEngine implements Server {
private final String s1 = "Resource Object 1";
private final String s2 = "Resource Object 2";
private final LinkedList<String> list = new LinkedList<>();
private final int timer = 5000;
public static void main(String[] args) {
try {
String name = "server";
ServerEngine engine = new ServerEngine();
Server stub = (Server) UnicastRemoteObject.exportObject(engine, 0);
Registry registry = LocateRegistry.getRegistry();
registry.rebind(name, stub);
System.out.println("ServerEngine bound");
} catch (Exception e) {
System.err.println("ServerEngine exception:");
}
}
private synchronized String localGetResource() {
Object lock = new Object();
if ( ! list.contains(s1)) {
synchronized (lock) {
// wait to ensure concurrency
try {
lock.wait(timer);
} catch (InterruptedException ex) {}
}
list.add(s1);
return s1;
}
if ( ! list.contains(s2)) {
list.add(s2);
return s2;
}
return null;
}
#Override
public String getResource() throws RemoteException {
return localGetResource();
}
}
I would like to know if this is a feasible solution. Are there any caveats? Do I actually need a second function or could I synchronize getResource() directly?
Your synchronization is broken on several levels:
You're not supposed to wait() on something unless you expect some other thread to notify() you.
You're implementing only half of double-checked locking, which translates to "no locking", as the same value may end up in the list several times.
You should have a look at proper thread-safe collection implementations under java.util.concurrent, rather than doing this by hand.
Your locally create lock object is useless, as tsolakp noted, every method call creates its own instance.
Create the object as a field in order to use it's monitor for sychronization.
If you declare a method as synchronized you've use implicitly the monitor of the instance the method is invoked on. It makes no sense to mix these two approaches.
If you want to synchronize the access to your list use the according object's monitor for synchronization.
I am wondering if the following example is properly synchronized.
It isn't synchronized at all. It uses a lock, but not correctly, so it isn't sequentialized either.
public String getResource() throws RemoteException {
Object lock = new Object();
if ( ! list.contains(s1)) {
synchronized (lock) {
// wait to ensure concurrency
try {
lock.wait(timer);
} catch (InterruptedException ex) {}
}
list.add(s1);
return s1;
}
if ( ! list.contains(s2)) {
list.add(s2);
return s2;
}
return null;
}
You don't need all this, and you certainly don't need the wait(). This code will never actually lock the list effectively, because every invocation gets its own lock object.
Throw it all away and just synchronize the method:
public synchronized String getResource() throws RemoteException {
if ( ! list.contains(s1)) {
list.add(s1);
return s1;
}
if ( ! list.contains(s2)) {
list.add(s2);
return s2;
}
return null;
}

Hyperlinklistener will not connect [duplicate]

I'm encountering a weird issue in Java at the moment that I've never seen before.
The error is "No enclosing instance of type Server is accessible. Must qualify the allocation with an enclosing instance of type Server (e.g. x.new A() where x is an instance of Server)."
The line I've commented on is where the error occurs.
package game;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
public class Server {
private static List<ThreadModtagClient> clients;
class ReceiveDataListener implements SocketListener {
#Override
public void dataReceived(ThreadModtagClient client, String data) {
}
}
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
clients = new ArrayList<ThreadModtagClient>();
ServerSocket welcomeSocket = new ServerSocket(16567);
while (true) {
Socket connectionSocket = welcomeSocket.accept();
ThreadModtagClient client = new ThreadModtagClient(connectionSocket);
ReceiveDataListener listener = new ReceiveDataListener(); // <--- this is where the error occurs
client.addSocketListener(listener);
clients.add(client);
}
}
}
class ThreadModtagClient extends Thread implements SocketThread {
private BufferedReader inFromClient;
private DataOutputStream outToClient;
private Player player;
private List<SocketListener> listeners;
public ThreadModtagClient(Socket connection) throws IOException {
inFromClient = new BufferedReader(new InputStreamReader(connection.getInputStream()));
outToClient = new DataOutputStream(connection.getOutputStream());
listeners = new ArrayList<SocketListener>();
}
public void addSocketListener(SocketListener listener) {
listeners.add(listener);
}
public void removeSocketListener(SocketListener listener) {
listeners.remove(listener);
}
public Player getPlayer() {
return player;
}
public void setPlayer(Player player) {
this.player = player;
}
public void sendData(String data) throws IOException {
outToClient.writeChars(data);
}
public void run() {
while (true) {
try {
String data = inFromClient.readLine();
for(SocketListener listener : listeners) {
listener.dataReceived(this, data);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch(NoSuchElementException e1) {
e1.printStackTrace();
}
}
}
}
Server.ReceiveDataListener is a (non-static) inner class. You are creating it from a static context. You need to supply an instance of Server to be the outer instance. However, almost certainly you want ReceiveDataListener to be a static nested class, or probably an outer class.
well the error tells you exactly what needs to be done. ReceiveDataListener is a non-static inner class and must be accessed via an object of the outer class (Server). You have three options:
1. take the compiler's advice (access via an object of Server)
2. make ReceiveDataListener static
3. pull ReceiveDataListener out to a separate .java and use it.
HTH
You cannot instantiate a non-static inner class from a static context like main.
This is because you're trying to create a ReceiveDataListener from a static method, and since ReceiveDataListener is not a static class, it needs to be attached to an instance of Server.

Problems initiating class that will be updated by multiple threads

Hi i'm trying to create a sever/client program that takes up to 5 clients inputting a string each via multiple server side threads, these strings are to be added to team class ie the Same team, then when the team is full, clients disconnect and the server awaits names for the next Team.
My problem lies in creating an instance of the class Team that each thread updates to..
im not sure where to declare the instance of the class?(it contains a string array[5])
my classes on serverside are currently "TeamServer", "TeamServerThread" "team" "streamSocket"
Below is my "TeamServerThread" currently taking the user string and just adding it to another string.
import java.io.*;
class TeamServerThread implements Runnable {
static String names ="";
MyStreamSocket myDataSocket;
TeamServerThread(MyStreamSocket myDataSocket) {
this.myDataSocket = myDataSocket;
}
public void run( ) {
String newName;
try {
newName = myDataSocket.receiveMessage();
/**/ System.out.println("Name Recieved = "+newName);
updateNames(newName);
// now send the names to the requestor
// wait
myDataSocket.sendMessage(names);
myDataSocket.close();
}// end try
catch (Exception ex) {
System.out.println("Exception caught in thread: " + ex);
} // end catch
} //end run
private synchronized void updateNames (String newName) {
names +=newName + "\n";
// this.team.add(newName);
} // end updateNames
} // end Team
Here is my "Team" class
public class Team
{
public final int TEAM_SIZE = 5;
public String names[] = new String[TEAM_SIZE];
public int num_members = 0;
// waits until five names have arrived
// needs to be synchronized because it can be accessed
// by a number of concurrent threads
synchronized void add(String name)
{
names[num_members] = name;
num_members++;
if (num_members < TEAM_SIZE)
try
{
wait();
}
catch(Exception e) {}
else
try
{
notifyAll();
}
catch(Exception e){}
} // end add
public int Getnum_members()
{
return num_members;
}
} // end Team
All class loading is single threaded and you cannot laod/update a class with multiple threads. However I assume this is not what you mean.
You need to have the Team where every socket can see it. The problem you have is that you haven't synchronized access or replacement of the Team so you could ahve a race condition where too many client try to add themselves to the same team.
I suggest you have some type of TeamCoordinator which is passed to each socket connection which can determine when Team a client should be added to.

Categories