Using sockets and Object IO streams in Android programming - java

I'm trying to implement multiplayer in a game I've been writing, and I've gotten everything to successfully connect (I think..), but when I'm running it, there's an EOFException thrown by the client, and the object (an ArrayList) isn't successfully received.
Code for the server thread:
class ServerThread implements Runnable
{
ServerSocket server = null;
Socket controlSocket = null;
ObjectOutputStream outStream = null;
ObjectInputStream inStream = null;
#Override
public void run() {
setupConnection();
while(true){
sendObject(out.getStuff());
}
}
void setupConnection(){
Log.e("OUTPUTSHOOTER","init-connect");
try {
server = new ServerSocket(SERVERPORT);
Log.e("OUTPUTSHOOTER","server initiated port: "+SERVERPORT);
controlSocket = server.accept();
Log.e("OUTPUTSHOOTER","connected");
inStream = new ObjectInputStream(controlSocket.getInputStream());
outStream = new ObjectOutputStream(controlSocket.getOutputStream());
} catch (StreamCorruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.e("OUTPUTSHOOTER",server+" "+controlSocket+" "+inStream+" "+outStream);
}
public Object recieveObject(){
Object o = null;
try {
o = inStream.readObject();
} catch (OptionalDataException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return o;
}
public void sendObject(Object o)
{
try {
outStream.writeObject(o);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
And then the code for the client:
class ClientThread implements Runnable
{
Socket controlSocket = null;
ObjectOutputStream outStream = null;
ObjectInputStream inStream = null;
#Override
public void run() {
setupConnection();
while(true){
Log.e("OUTPUTSHOOTER","recieving");
Object in = recieveObject();
if(in!= null && in instanceof ArrayList)
{
Log.e("OUTPUTSHOOTER","loading");
out.load((ArrayList<UniverseObject>)in);
}
}
}
void setupConnection(){
Log.e("OUTPUTSHOOTER","ip: "+SERVERIP);
while(controlSocket == null) {
try {
controlSocket = new Socket(SERVERIP,SERVERPORT);
Log.e("OUTPUTSHOOTER","socket connected");
} catch (IOException e) {
e.printStackTrace();
}
}
try {
Log.e("OUTPUTSHOOTER","attempting streams");
outStream = new ObjectOutputStream(controlSocket.getOutputStream());
Log.e("OUTPUTSHOOTER","output working");
inStream = new ObjectInputStream(controlSocket.getInputStream());
Log.e("OUTPUTSHOOTER","streams connected");
} catch (StreamCorruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Object recieveObject(){
Object o = null;
try {
o = inStream.readObject();
} catch (OptionalDataException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return o;
}
public void sendObject(Object o)
{
try {
outStream.writeObject(o);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
What does this mean? And perhaps more importantly, how can I fix it? Thanks in advance..

I don't see you closing your outputstream.
See this SO topic: Problem serializing and deserializing ArrayList

Turns out the server wasn't properly initiating it's input and output streams, even though its sockets were successful. Dunno why, but it only works if I started with the output stream first, then the input (?). Having some other really strange bugs, but at least the communication seems to work.. I'll look more in to them before posting here about it. Thanks guys!

Related

Get data from getter method instead of passing in a Bundle

I need to pass some Bitmaps from one activity to another, and, since the size limit of the Bundle won't let me pass these images (even using a byte array*), I thought that I could use a getter method between these Activities.
-But, since I'm still not a master in Android (Java), I don't know if that would make any difference, and, if it does, what should I watch out for when using it.
the byte array did reduce the total size(at about 60%), but it still wasn't enough
scaling down is a way out, but just in case any other solution works
save your object in a file
private void saveDataToFile() {
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = getContext().openFileOutput("fileName", Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (NullPointerException e) {
}
ObjectOutputStream objectOutputStream = null;
try {
objectOutputStream = new ObjectOutputStream(fileOutputStream);
} catch (IOException e) {
e.printStackTrace();
} catch (NullPointerException e) {
}
try {
if (objectOutputStream != null) {
objectOutputStream.writeObject(yourObject); //which data u want to save
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (objectOutputStream != null) {
objectOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Retrieve the object from another activity
private void getDataFromFile() {
FileInputStream fileInputStream = null;
try {
fileInputStream = getContext().openFileInput("fileName");
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
}
ObjectInputStream objectInputStream = null;
try {
objectInputStream = new ObjectInputStream(fileInputStream);
} catch (IOException |NullPointerException e) {
e.printStackTrace();
}
try {
yourObject = (ObjectClass) objectInputStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Pass through Uri by writing getter method in POJO class
If you want to use getter setter, just create URI of your bitmap and pass to setter method in POJO class and then retrieve using getter method of POJO class.

Why am I getting InvocationTargetException at ClassLoaders.callStaticFunction Java Eclipse? [duplicate]

I have created a program to convert text to xml by using ReverseXSL API.
This program is to be executed by an application by calling static method (static int transformXSL).
I am able to execute and produce output with running from Eclipse. However, When I ran program (jar) by using application it stuck somewhere and I couldnt find anything.
Then, I debugged by "Debug as...-> Remote Java Application" in Eclipse from Application and found "InvocationTargetException" at ClassLoaders.callStaticFunction.
Below Static method is called by application.
public class MyTest4 {
public MyTest4()
{
}
public static int transformXSL(String defFile, String inputFile, String XSLFile, String OutputFile) {
System.out.println("Dheeraj's method is called");
// start time
FileWriter fw=null;
try {
fw = new FileWriter("D://Countime.txt");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
BufferedWriter output=new BufferedWriter(fw);
DateFormat sd=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date dt= new Date();
System.out.println("Date is calculated");
try {
output.write("Start Time:"+sd.format(dt).toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(sd.format(dt));
FileReader myDEFReader=null, myXSLReader=null;
TransformerFactory tf = TransformerFactory.newInstance();
Transformer t=null;
FileInputStream inStream = null;
ByteArrayOutputStream outStream = null;
// Step 1:
//instantiate a transformer with the specified DEF and XSLT
if (new File(defFile).canRead())
{
try {
myDEFReader = new FileReader(defFile);
System.out.println("Definition file is read");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
else myDEFReader = null;
if (new File(XSLFile).canRead())
try {
myXSLReader = new FileReader(XSLFile);
System.out.println("XSL file is read");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
else myXSLReader = null;
try {
t = tf.newTransformer(myDEFReader, myXSLReader);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Step 1: DEF AND XSLT Transformation completed");
// Step 2:
// Read Input data
try {
inStream = new FileInputStream(inputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
outStream = new ByteArrayOutputStream();
System.out.println("Step 2: Reading Input file: completed");
// Step 3:
// Transform Input
try {
try (BufferedReader br = new BufferedReader(new FileReader("D://2.txt"))) {
String line = null;
while ((line = br.readLine()) != null) {
System.out.println("Content: "+line);
}
}
System.out.println("File: "+inputFile.toString());
System.out.println("\n content: \n"+ inStream.toString());
System.out.println("Calling Transform Function");
t.transform(inStream, outStream);
System.out.println("Transformation is called");
outStream.close();
try(OutputStream outputStream = new FileOutputStream(OutputFile)) {
outStream.writeTo(outputStream);
System.out.println("Outstream is generated; Output file is creating");
}
System.out.println(outStream.toString());
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerFactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (javax.xml.transform.TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("output file is created");
// End time
Date dt2= new Date();
System.out.println(sd.format(dt2));
System.out.println("End time:"+dt2.toString());
try {
output.append("End Time:"+sd.format(dt2).toString());
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}
}

Notify client in client server application

first of all, I'm rather new to socket programming to go easy on me ;).
I have a Java program that uses client-server programming to communicate between 1 or more clients and the server. So the clients can send any number of messages to the server where the messages are dealt with and all is fine so far. Now I want to notify the clients of e.g. database changes on the server side. So for example if one client changes for example table A, the other clients should also be notified about this change.
What I have so far is the following (server):
ExecutorService executor = null;
try (ServerSocket socket = new ServerSocket(port);)
{
executor = Executors.newFixedThreadPool(getThreadCount(5));
while(true)
{
Socket clientSocket = socket.accept();
Runnable worker = new PCRequestMapper(clientSocket);
executor.execute(worker);
}
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
finally
{
if(executor != null)
{
executor.shutdown();
}
}
The request mapper class then looks like this:
public class PCRequestMapper implements Runnable
{
private Socket client = null;
private static Map<Integer, PCRequestData> requestData = null;
public PCRequestMapper(Socket client)
{
this.client = client;
}
#Override
public void run()
{
try (ObjectInputStream in = new ObjectInputStream(
client.getInputStream());
ObjectOutputStream writer = new ObjectOutputStream(
client.getOutputStream());)
{
System.out.println("Thread started in PCRequestHandler with name: "
+ Thread.currentThread().getName());
Object recObj = in.readObject();
// ToDo Do something
PCBaseRequest req = (PCBaseRequest) recObj;
System.out.println("Req type: " + req.getRequestType() + " name: "
+ req.getName());
PCRequestData data = requestData.get(req.getRequestType());
if(data == null)
{
PCException ex = new PCException();
ex.setStackTrace(new Throwable().getStackTrace());
PCBaseReply reply = getErrorReply("No mapped request handler found in services.xml for request: "+req.getRequestType()+" - "+req.getName(),
PCException.NO_MAPPED_HANDLER, ex);
writer.writeObject(reply);
}
else
{
Class<?> c = Class.forName(data.getMappedClass());
Constructor<?> cons = c.getConstructor();
PCIRequestHandler object = (PCIRequestHandler)cons.newInstance();
PCBaseReply reply = object.heyHo(req);
System.out.println("Writing reply: "+reply.getClass());
writer.writeObject(reply);
}
} catch (IOException ioe)
{
ioe.printStackTrace();
} catch (ClassNotFoundException cnfe)
{
cnfe.printStackTrace();
} catch (NoSuchMethodException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
It basically takes a message (request), maps it to a configured class and then that class performs whatever action needed.
On the client side, I have a class called RequestSender, which is used to send arbitrary requests to the server:
public class PCRequestSender
{
private static int getPort(int defaultPort)
{
final String port = PCConfigHandler.getStringProperty("serverPort");
if (null != port)
{
try
{
return Integer.parseInt(port);
} catch (NumberFormatException e)
{
System.out.println("Value of port property"
+ " is not a valid positive integer [" + port + "]."
+ " Reverting to default [" + defaultPort + "].");
}
}
return defaultPort;
}
public static PCBaseReply sendRequest(PCBaseRequest req)
{
PCBaseReply reply = null;
int port = getPort(8081);
String address = PCConfigHandler.getStringProperty("serverAddress");
try (Socket serverSocket = new Socket(address, port);
ObjectOutputStream out = new ObjectOutputStream(
serverSocket.getOutputStream());
ObjectInputStream in = new ObjectInputStream(
serverSocket.getInputStream());)
{
out.writeObject(req);
Object recObj = in.readObject();
reply = (PCBaseReply) recObj;
System.out.println("Reply: "+reply);
} catch (IOException e)
{
e.printStackTrace();
} catch (ClassNotFoundException e)
{
e.printStackTrace();
}
return reply;
}
}
Now I'm a bit at a loss, because I would also like to constantly listen to a server socket to catch notifications. Do I need another socket on the server side? Is my setup not tooooo ideal?
I'm helpful for any hints...thanks!

java.io.EOFException (having problems with closing streams)

Got a simple client/server app only with login/logout implemented. When i press connect it runs perfect, but the problem comes after when trying to disconnect (getting EOFException on client side).
Im almost sure its due to a poor close of the stream. Any hints?
java.io.EOFException
at java.io.DataInputStream.readByte(DataInputStream.java:98)
at java.io.ObjectInputStream.nextTC(ObjectInputStream.java:506)
at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:778)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2006)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1963)
at com.mtm.ClientConnection.disconnect(ClientConnection.java:54)**
Client class:
public class ClientConnection implements Admin{
public ObjectInputStream in;
public static ObjectOutputStream out;
public Socket socket;
public void connect(){
String host = IP;
int port = PORTO;
try {
socket = new Socket (host,port);
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
MSG_Login login = new MSG_Login();
login.setID(DeviceId.getId().toString());
send(login);
Object c1 = in.readObject();
if(c1 instanceof MSG_Login){
Thread thread = new ClientThread(this);
thread.start();
}
}
catch (UnknownHostException e) { e.printStackTrace(); }
catch (SocketException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
catch (ClassNotFoundException e) { e.printStackTrace(); }
}
public void disconnect(){
try {
MSG_Logout logout = new MSG_Logout();
logout.setID(DeviceId.getId().toString());
send(logout);
Object c1 = in.readObject();
if(c1 instanceof MSG_Logout){
in.close();
out.close();
socket.close();
}
}
catch (IOException e) { e.printStackTrace(); }
catch (ClassNotFoundException e) { e.printStackTrace(); }
}
public static void send(Object obj) {
try {
out.writeObject(obj);
out.flush();
out.reset();
}
catch (IOException e) { e.printStackTrace(); }
}
}
Server (thread) class:
public class Servidor_Thread extends Thread{
public Socket canal;
Servidor serv;
ObjectOutputStream oos=null;
ObjectInputStream ois=null;
private boolean logOff;
public Servidor_Thread(Servidor serv) {
this.serv = serv;
canal = serv.socket;
logOff = false;
}
public void run(){
try {
ois=new ObjectInputStream(canal.getInputStream());
oos=new ObjectOutputStream(canal.getOutputStream());
while(logOff==false){
Object obj=ois.readObject();/** Objecto recebido - Reconstrução **/
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
if(obj instanceof MSG_Login){
serv.id_database.add(((MSG_Login) obj).getID());
serv.getLog().appendConsole("["+dateFormat.format(date)+"]..........User "+((MSG_Login) obj).getID()+" connected.");
enviar(obj);
}
if(obj instanceof MSG_Logout){
serv.id_database.remove(((MSG_Logout) obj).getID());
serv.getLog().appendConsole("["+dateFormat.format(date)+"]..........User "+((MSG_Logout) obj).getID()+" disconnected.");
enviar(obj);
stopThread();
}
}
}
catch (IOException e) { stopThread(); }
catch (ClassNotFoundException e) { e.printStackTrace(); }
}
public void stopThread(){
logOff = true;
try {
ois.close();
oos.close();
canal.close();
} catch (IOException e) { e.printStackTrace(); }
}
public void enviar(Object obj) {
try {
oos.writeObject(obj);
oos.flush();
oos.reset();
}
catch (IOException e) { e.printStackTrace(); }
}
}
There is no problem here to answer. The readObject() method throws EOFException at end of stream. This is its normal behaviour. You have to catch it, close the stream you are reading, and exit the reading loop.

Serialization of a class which doesnt implement Serializable

I have 2 classes serial1 and serial 2. serial1 implements Serializable whereas serial2 does not.As per theory i should get an Exception for the following code, but it is working fine. why is it so ?
import java.io.*;
public class SerialTest {
public static void main(String args[]){
FileOutputStream fos=null;
ObjectOutputStream oos =null;
serial1 se = new serial1();
serial1 sd = null;
se.mets();
try {
fos= new FileOutputStream("serialtest");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
oos =new ObjectOutputStream(fos);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
oos.writeObject(se);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileInputStream fis=null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("serialtest");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
ois = new ObjectInputStream(fis);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
sd = (serial1) ois.readObject();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sd.mets();
}
}
import java.io.Serializable;
public class serial1 implements Serializable{
/* public static void main(String []args){
serial1 ss = new serial1();
ss.mets();
}*/
public void mets(){
serial2 s2 = new serial2();
System.out.println( "serial 1 + mets");
s2.met1();
}
}
public class serial2 {
public void met1(){
System.out.println("serial2 + met1");
}
}
---------------------------*
The output is
serial 1 + mets
serial2 + met1
serial 1 + mets
serial2 + met1
You don't actually serialize serial2. Your mets method creates a local variable but as soon as the method returns it goes out of scope and becomes eligible for garbage collection.
If you had an instance variable of type serial2 inside serial1 then you would see an exception when you try to serialize (assuming it's a non-null value), but a local variable will not be a problem.
I don't see you ever serializing serial2

Categories