In both client and server classes, I have an exact same inner class called Data. This Data object is being sent from the server using:
ObjectOutputStream output= new ObjectOutputStream(socket.getOutputStream());
output.writeObject(d);
(where d is a Data object)
This object is received on the client side and cast to a Data object:
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
Object receiveObject = input.readObject();
if (receiveObject instanceof Data){
Data receiveData = (Data) receiveObject;
// some code here...
}
I'm getting a java.lang.ClassNotFoundException: TCPServer$Data on this line Object receiveObject = input.readObject();
My guess is that it's trying to to look for the Data class in the Server side and can't find it, but I'm not sure... How do I fix this?
What you were trying to do is something along the lines of the following:
class TCPServer {
/* some code */
class Data {
}
}
class TCPClient {
/* some code */
class Data {
}
}
Then you are serializing a TCPServer$Data and trying to unserialize it as a TCPClient$Data. Instead you are going to want to be doing this:
class TCPServer {
/* some code */
}
class TCPClient {
/* some code */
}
class Data {
/* some code */
}
Then make sure the Data class is available to both the client and the server programs.
When you use some class in two different JVMs, and you are marshalling/unmarshalling the class then the class should be exported to a common library and shared between both server and client. Having different class wont work any time.
What you are trying to do is marshall TCPServer$Data and unmarshall as TCPClient$Data. That is incompatible.
Related
I've come across an issue when sending an object over a local connection. The object will send the first time as expected. However variables of the object are constantly being changed therefore need to be updated when sending to the other connection. This is done through sending messages prompting the other client to listen and wait for the object being sent.
I'm aware that the java.io.ObjectOutputStream.reset() method exists but keep getting the following error:
error: cannot find symbol
output.reset();
Here's how the code is currently structured (Minus lots of non relevant code):
import java.net.*;
import java.util.*
import java.io.*;
public class Client
{
private static Socket cSocket = null;
private static ObjectOutput output = null;
private static Person myPerson = null;
private static String serverHost = "localhost";
public void Run()
{
// Declaring the output
output = new ObjectOutputStream(
cSocket.getOutputStream()
);
}
private static void sendPerson()
{
try
{
output.writeObject( myPerson );
output.reset();
} catch (Exception e)
{
}
}
}
TLDR: Each time sendPerson() is called the other client receives the first object sent to the other client rather than the updated variables. Tried using reset(); but error is thrown.
Would just like the objects updated variables to be sent rather than the initial object always being sent.
To use ObjectOutputStream#reset you have to define your field with such type.
Not ObjectOutput, but ObjectOutputStream.
Like this:
private static ObjectOutputStream output = null;
This question already has an answer here:
StreamCorruptedException: invalid type code: AC
(1 answer)
Closed 7 years ago.
I'am writing a simple copy of 'Space Invaders'. I want to add network feature, and atm I have problem with Writing/Reading data.
So I have a LinkedList of (objects)Aliens and I want to send this to Client, to update thier positions.
The problem starts there:
On Server side I got exception:
'java.io.NotSerializableException: sun.awt.image.ToolkitImage'
(Class Alien implements Serializable)
On Client Side:
'StreamCorruptedException: invalid type code: AC'
Code where sending data to client:
else if(Server)
{
while(true)
{
ServerSocket server = new ServerSocket(1500);
serverSocket = server.accept();
new NetworkThreadHelp(serverSocket, board.GetAlienList()).start();
}
}
Code of NetworkThreadHelp:
public class NetworkThreadHelp extends Thread
{
private Socket socket = null;
private LinkedList<Alien> Aliens = new LinkedList<Alien>();
public NetworkThreadHelp(Socket socket, LinkedList<Alien> A)
{
super("NetworkThreadHelp");
this.socket = socket;
this.Aliens = A;
}
public void run()
{
try
{
ObjectOutputStream objectOutput = new ObjectOutputStream(socket.getOutputStream());
objectOutput.writeObject(Aliens);
objectOutput.flush();
objectOutput.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
Code where data is read:
else if(Client)
{
Socket socket = new Socket("127.0.0.1",1500);
ObjectInputStream objectInput;
while (true)
{
objectInput= new ObjectInputStream(socket.getInputStream());
Object object = objectInput.readObject();//Here code doesn't initialize, everything below this won't execute
LinkedList<Alien> Aliens = (LinkedList<Alien>) object;
board.UpdateAliens(Aliens);
}
}
My question is: how to make this work, write and read properly?
Most likely your Alien class contains an instance reference to an instance of the nonserializable ToolkitImage class. You may need to refactor your code so the Alien class doesn't contain such an instance reference, for exaample by making that reference a static constant. Alternatively, you can write custom writeObject(), readObject(), and readObjectNoData() methods for the Alien class as specified in the Javadoc for Serializable.
Your client side problem may or may not be a different problem, but I'd suggest fixing the server side problem first. If you still have a client side problem, you can always post another question.
Suppose we have the following classes:
class Packet implements Serializable { ... };
class OpenConnectionPacket extends Packet { ... };
class DataPacket extends Packet { ... };
class CloseConnectionPacket extends Packet { ... };
Now, I want to be able to send an arbitrary packet like this:
Socket s = ...;
ObjectOutputStream toServer = new ObjectOutputStream(s.getOutputStream());
Packet p = ...;
toServer.writeObject(p);
and recieve it from the other end:
Socket s = ...;
ObjectInputStream fromClient = new ObjectInputStream(s.getInputStream());
Packet p = (Packet) fromClient.readObject();
Is this possible? How? (If it is, I guess is should override the writeObject() and readObject() methods, and maybe have something like a int type; or some enum in the parent class Packet in order to identify each child?)
You don't need to override writeObject() and readObject().
It works by its default implementation until and unless you write your custom logic while serialization if needed.
For more info have a look at below links
ObjectOutputStream
Serialization - readObject writeObject overides
I'd like to do something similar to the example posted in restlet's site (first applicaiton) - with one difference:
I want to stream data - not use primitive types - using an interface.
I want to define some kind of an interface between the client and the server, stream data between them and let restlet handle transmit the data seamlessly.
Example of what I have in mind:
interface Streaming {
InputStream startStream(String streamId);
}
When the client invokes a call, it starts reading from the inputstream. The server receives the call and starts providing the stream by creating an inputstream (for example, a video file, or just some raw data). Restlet should be reading from the inputstream on the server side and provide the data as an inputstream on the client side.
Any idea how can I achieve this? A code sample or link to one would be great. Thanks.
Below's an example code of what I learned so far - an interface with streaming capavilities and a client-server streaming example.
I haven't yet added parameters to the interface and it's only download - no upload yet.
Interface:
public interface DownloadResource {
public ReadableRepresentation download();
}
Interface with protocol: (separation between logic and technology):
public interface DownloadResourceProtocol extends DownloadResource {
#Get
#Override
public ReadableRepresentation download();
}
Client:
ClientResource cr = new ClientResource("http://10.0.2.2:8888/download/");
cr.setRequestEntityBuffering(true);
DownloadResource downloadResource = cr.wrap(DownloadResourceProtocol.class);
// Remote invocation - seamless:
Representation representation = downloadResource.download();
// Using data:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
IOUtils.copy(representation.getStream(), byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
Log.i("Byte array: " + Arrays.toString(byteArray));
Server:
public class DownloadResourceImpl extends ServerResource implements DownloadResourceProtocol {
#Override
public ReadableRepresentation download() {
InputStreamChannel inputStreamChannel;
try {
inputStreamChannel = new InputStreamChannel(new ByteArrayInputStream(new byte[]{1,2,3,4,5,6,7,8,9,10}));
return new ReadableRepresentation(inputStreamChannel, MediaType.ALL);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
Configuration:
public class SampleApplication extends Application {
#Override
public Restlet createInboundRoot() {
Router router = new Router(getContext());
router.attach("/download/", DownloadResourceImpl.class);
return router;
}
}
Not sure this addresses your problem completely, but one approach is to create a thread that streams data back to the client using ReadableRepresentation and a Pipe.
Create a pipe:
Pipe pipe = Pipe.open();
Create a representation like this:
ReadableRepresentation r = new ReadableRepresentation(pipe.source(), mediatype);
Start a separate thread that writes batches of bytes to the pipe like this:
pipe.sink().write(ByteBuffer.wrap(someBytes));
return the representation to the client.
I have to serialize an object and send it from a httpserver
i already know how to send a string from the server to the client,but i don't know how to send a object
So i have this code :
public class Test {
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/test", new MyHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
static class MyHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
String response = "This is the response";
//this part here shows how to send a string
//but i need to send an object here
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
so i tried to search google but no results,and i tried to change the code (mechanically without knowing well what im doing as im not used to HttpServer's in java)
this way :
SendResponse obj = new SendResponse();
ObjectOutputStream objOut = new ObjectOutputStream();
t.sendResponseHeaders(200, objOut);
objOut.writeObject(obj);
objOut.close();
but eclipse shows me an error which tells me that the ObjectOutputStream() constructor is not visible and that httpExchange is not applicable for the arguments (int,ObjectInputStream)
Do you have any idea how i can fix this ?
Thank you in advance for your help !
You have accesible the constructor with one OutputStream as parameter
ObjectOutputStream objOut = new ObjectOutputStream( the http or any other output stream here );
The constructor of ObjectOutputStream sends some header bytes and the constructor of ObjectInputStream expects these header bytes. You should either create a new ObjectOutputStream and a new ObjectInputStream for every object, or create only one ObjectOutputStream and ObjectInputStream for all the objects.
A more simple alternative could be google gson It´s easy to use and it converts a java class to json string and the inverse way too.
After some hours of trying different things
you have just to replace the
t.sendResponseHeaders(200, objOut);
with
t.sendResponseHeaders(200,0);
as mentioned by user cyon on this question