ObjectOutputStream中和java.io.StreamCorruptedException [英] ObjectOutputStream and java.io.StreamCorruptedException

查看:228
本文介绍了ObjectOutputStream中和java.io.StreamCorruptedException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我试图从我的客户端发送一个customobject(见Content.java)与ObjectOutputStream的服务器,我得到StreamCorruptedException的第一个对象发送后。所以,如果我尝试发送另一个对象我得到的异常,(它的作品第一次)。我用Google搜索和阅读的东西很多,现在我打算放弃,于是我找你帮忙。

Client.java

 公共类客户端延伸主题{
私人最终静态字符串TAG =客户;
私人最终静态字符串IP =10.0.2.2;
私人最终静态INT PORT = 12345;
私人插座S;
私有静态的ObjectOutputStream出来;
私有静态的ObjectInputStream的;
//私人的PrintWriter出来;
//私人的BufferedReader的;
私人TextView的电视;
私人内容C =新的内容();公共客户端(TextView的电视){
    this.tv =电视;}公共无效的run(){
    S = NULL;
    出= NULL;
    在= NULL;
    字符串资源;    尝试{
        S =新的Socket(IP,端口);
        Log.v(TAG,C:连接到服务器+ s.toString());        OUT =新的ObjectOutputStream(s.getOutputStream());
        在=新的ObjectInputStream(s.getInputStream());        // OUT =的新PrintWriter(s.getOutputStream(),TRUE);
        //在=新的BufferedReader(新的InputStreamReader(s.getInputStream()));
        //c.setText(\"PING从客户端)的服务器;
        //out.writeObject(c);
        而((C =(内容)in.readObject())!= NULL){
            尝试{
                    RES = c.getText();
                    Log.i(TAG,RES);
            }赶上(例外五){
                Log.e(调用readObject,e.toString());
            }
        }    }赶上(例外五){
        Log.e(运行@客户,e.toString());
    } {最后
        尝试{
            out.close();
            附寄();
            S.CLOSE();
        }赶上(IOException异常五){
            Log.e(TAG,e.toString());
        }
    }
}公共字符串的setText()抛出异常{
    返回in.toString();}公共无效sendText(字符串文本){
    内容CONT =新的内容(文本);
    尝试{
        out.writeObject(续)
    }赶上(例外五){
        e.printStackTrace();
        Log.e(的writeObject,e.toString());
    } {最后
        尝试{
            了out.flush();
            out.close();
            S.CLOSE();
            Log.i(TAG,对象发送);
        }赶上(例外五){}
    }
}
}

Content.java

 公共类内容实现Serializable {
私人字符串文本;公开内容(字符串文本){
    this.text =文本;
}公共字符串的getText(){
    返回文本;
}公共无效的setText(字符串文本){
    this.text =文本;
}
}

堆栈:

  04-24 17:09:12.345:WARN / System.err的(520):java.io.StreamCorruptedException
04-24 17:09:12.355:WARN / System.err的(520):在java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1707)
04-24 17:09:12.355:WARN / System.err的(520):在java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1660)
04-24 17:09:12.365:WARN / System.err的(520):在client.android.Client.sendText(Client.java:83)
04-24 17:09:12.365:WARN / System.err的(520):在client.android.ClientActivity.sendToServer(ClientActivity.java:38)
04-24 17:09:12.365:WARN / System.err的(520):在java.lang.reflect.Method.invokeNative(本机方法)
04-24 17:09:12.365:WARN / System.err的(520):在java.lang.reflect.Method.invoke(Method.java:521)
04-24 17:09:12.365:WARN / System.err的(520):在android.view.View $ 1.onClick(View.java:2026)
04-24 17:09:12.365:WARN / System.err的(520):在android.view.View.performClick(View.java:2364)
04-24 17:09:12.365:WARN / System.err的(520):在android.view.View.onTouchEvent(View.java:4179)
04-24 17:09:12.365:WARN / System.err的(520):在android.widget.TextView.onTouchEvent(TextView.java:6541)
04-24 17:09:12.375:WARN / System.err的(520):在android.view.View.dispatchTouchEvent(View.java:3709)
04-24 17:09:12.375:WARN / System.err的(520):在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
0 4-24 17:09:12.385:WARN / System.err的(520):在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
04-24 17:09:12.385:WARN / System.err的(520):在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
04-24 17:09:12.385:WARN / System.err的(520):在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
04-24 17:09:12.385:WARN / System.err的(520):在com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1659)
04-24 17:09:12.385:WARN / System.err的(520):在com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
04-24 17:09:12.385:WARN / System.err的(520):在android.app.Activity.dispatchTouchEvent(Activity.java:2061)
04-24 17:09:12.395:WARN / System.err的(520):在com.android.internal.policy.impl.PhoneWindow $ DecorView.dispatchTouchEvent(PhoneWindow.java:1643)
04-24 17:09:12.395:WARN / System.err的(520):在android.view.ViewRoot.handleMessage(ViewRoot.java:1691)
04-24 17:09:12.395:WARN / System.err的(520):在android.os.Handler.dispatchMessage(Handler.java:99)
04-24 17:09:12.395:WARN / System.err的(520):在android.os.Looper.loop(Looper.java:123)
04-24 17:09:12.395:WARN / System.err的(520):在android.app.ActivityThread.main(ActivityThread.java:4363)
04-24 17:09:12.395:WARN / System.err的(520):在java.lang.reflect.Method.invokeNative(本机方法)
04-24 17:09:12.395:WARN / System.err的(520):在java.lang.reflect.Method.invoke(Method.java:521)
04-24 17:09:12.395:WARN / System.err的(520):在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:860)
04-24 17:09:12.395:WARN / System.err的(520):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
04-24 17:09:12.395:WARN / System.err的(520):在dalvik.system.NativeStart.main(本机方法)

编辑:添加ClientActivity.java
ClientActivity.java

 公共类ClientActivity延伸活动{
私人的EditText等;
私人客户机C;
私人TextView的电视;
/ **当第一次创建活动调用。 * /
@覆盖
公共无效的onCreate(捆绑savedInstanceState)
{
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.main);
    等=(EditText上)findViewById(R.id.clientTxt);
    电视=(的TextView)findViewById(R.id.recievedTxt);    C =新客户(TV);
    c.start();    尝试{
        tv.setText(c.setText());
    }赶上(例外五){}
}公共无效sendToServer(视图V)抛出异常{
    字符串文本= et.getText()的toString()。
    Log.i(EdittextVALUE,文本);
    c.sendText(文本);}

}

Server.java

 公共类服务器继承Thread {
私有静态最后弦乐TAG =ServerThread;
私有静态最终诠释端口= 12345;公共无效的run(){
    ServerSocket的SS = NULL;
    插座S = NULL;
    字符串资源=;    尝试{
        Log.i(TAG,启动服务器);
        SS =新的ServerSocket(PORT);
        Log.i(TAG的ServerSocket创建等待客户..);
        而(真){
            S = ss.accept();
            Log.v(TAG,客户端连接);
            连接C =新的连接(S);
        }
    }赶上(IOException异常五){
        e.printStackTrace();
    } {最后
        尝试{
            //out.close();
            //附寄();
            S.CLOSE();
            ss.close();
        }赶上(IOException异常五){}
    }
}

Connection.java

 公共类连接扩展Thread {
私人Socket套接字;
私有静态的ObjectOutputStream出来;
私有静态的ObjectInputStream的;
私人最终字符串标记=ConnectionClass;公共连接(Socket套接字){
    尝试{
        this.socket =插座;
        OUT =新的ObjectOutputStream(socket.getOutputStream());
        在=新的ObjectInputStream(socket.getInputStream());        this.start();    }赶上(IOException异常前){
        ex.printStackTrace();
        Log.e(TAG,ex.toString());
    }}公共无效的run(){
    字符串资源=;
    内容C = NULL;
    尝试{
        而(真){
        而((C =(内容)in.readObject())!= NULL){
            尝试{                    RES = c.getText();
                    Log.i(TAG,RES);            }赶上(例外五){
                Log.e(lololololo,e.toString());
            }
        }
        }
    }赶上(例外前){
        Log.e(TAG,ex.toString());
    } {最后
        尝试{
            socket.close();
            附寄();
            out.close();
        }赶上(例外五){}
    }}

ServerActivity.java

 公共类ServerActivity延伸活动{
公众Server服务器;
/ **当第一次创建活动调用。 * /
@覆盖
公共无效的onCreate(捆绑savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.main);
    服务器=新服务器();
    server.start();
}
}


解决方案

编辑:我添加了一个数组中的接收器,关闭所有的流时,接收机停止

您应该重新设计你的协议层。在这两种设备,你必须创建一个的ServerSocket 侦听新插座秒。显然,如果你调用任何阅读()方法,当前线程将处于阻塞状态进入,所以你需要使用一个辅助线程。您需要启动()和stop()接收器,并使用监听器通知插座创作。一个可能的实现(也可以提高了很多,但核心是这样):

Receiver.java

 公共类接收器{
私人的ArrayList< SocketStream> socketStreams;
    私人OnNewSocketListener侦听器;
    私人ServerSocket的服务器;
    私人螺纹螺纹;
    私人诠释口;    公共静态界面OnNewSocketListener {
        无效onNewSocket(流流);
    }    公共接收机(INT端口,OnNewSocketListener听众){
        this.listener =侦听器;
            this.port =口;
    }    公共同步启动(){
        如果(线程!= NULL)回报;        服务器=新ServerSocket的(端口);
        线程=新主题(新的Runnable(){
                @覆盖
                公共无效的run(){
                    尝试{
                        运行= TRUE;
                        而(运行){
                        socketStreams.add(流);
                                                    下面//见Stream.java
                            listener.onNewSocket(新流(server.accept()));
                        }
                    }赶上(SocketException E){
                        //停止()被调用
                    }赶上(IOException异常五){
                        //错误处理
                    }
                }
            })开始();
        }
    }    公共同步无效停止(){
        如果(线程== NULL)回报;        运行= FALSE;
        尝试{
            如果(服务器!= NULL){
                server.close();
            }
        }赶上(IOException异常五){}    对于(SocketStream流:socketStreams){
        stream.close();
    }
    socketStreams.clear();        螺纹=无效;
    }
}

然后,你需要的时候你要读写这个套接字来启动一个线程的类。要了解你需要另一个线程。您还需要其它监听通知读取对象并在其他设备关闭流通知。你需要一个startReading()和close()方法(如果你停止读取插槽将关闭):

Stream.java

 公共类流{
    私人Socket套接字;
    私人OnCloseStreamListener closeListener;
    私人OnReadObjectListener readListener;
    在私人ObjectInputStream的;
    私人的ObjectOutputStream出来;
    私人螺纹螺纹;    公共静态界面OnReadObjectListener {
        无效onReadObject(obj对象);
    }    公共静态界面OnCloseStreamListener {
        无效onCloseStream();
    }    //由接收机用于创建一个输入插座
    公共流(Socket套接字){
        this.socket =插座;
        OUT =新的ObjectOutputStream(socket.getOutputStream());
    }    //用户用来创建一个输出插座,当客户想创建一个套接字与服务器
    公共流(字符串的地址,端口INT){
        插座=新的Socket(地址,端口);
        OUT =新的ObjectOutputStream(socket.getOutputStream());
    }    公共无效setOnCloseStreamListener(OnCloseStreamListener监听){
        closeListener =侦听器;
    }    公共无效setOnReadObjectListener(OnReadObjectListener监听){
        readListener =侦听器;
    }    公共同步无效startReading(){
        如果(线程!= NULL)回报;        线程=新主题(新的Runnable(){
            @覆盖
            公共无效的run(){
                尝试{
                    在=新的ObjectInputStream(socket.getInputStream());
                    读= TRUE;
                    而(阅读){
                        obj对象= in.readObject();
                        如果(OBJ == NULL){
                            //另一台设备已关闭其流套接字
                            读= FALSE;
                            closeListener.onCloseSocketStream();
                        }其他{
                            readListener.onReadObject(OBJ);
                        }
                    }
                }赶上(SocketException E){
                    // STO preading()被调用
                }赶上(IOException异常五){
                    //错误处理
                }
            }
        })开始();
    }    公共同步无效的writeObject(obj对象){
        out.writeObject(OBJ);
        了out.flush;
    }    公共同步无效的close(){
        如果(线程!= NULL){
            读= FALSE;
            socket.close();
            in.close();
            out.close();
            螺纹=无效;
        }其他{
            socket.close();
            in.close();
        }
    }
}

用法:

服务器

 接收器接收器=新的接收器(5000,新Receiver.OnNewSocketListener(){
    @覆盖
    无效onNewSocket(流流){
        stream.setOnCloseStreamListener(新Stream.OnCloseStreamListener(){
            @覆盖
            无效onCloseStream(){
                //流会自动关闭,无需调用close()
                //做一点事
            }
        });
        stream.setOnReadObjectListener(新Stream.OnReadObjectListener(){
            @覆盖
            无效onReadObject(obj对象){
                //使用OBJ东西
                如果(obj.isDoingSomeMaliciousActivities()){
                    stream.close();
                }否则如果(obj.isDoingGoodStuff){
                                    stream.writeObject(新GoodStuff());
                            }
            }
        });
        stream.startReading();
    }
});
receiver.start();
视频下载(10000);
receiver.stop();

客户端

 流流=新流(本地主机,5000);
stream.setOnCloseStreamListener(新Stream.OnCloseStreamListener(){
    @覆盖
    无效onCloseStream(){
        //流会自动关闭,无需调用close()
        //做一点事
    }
});
stream.setOnReadObjectListener(新Stream.OnReadObjectListener(){
    @覆盖
    无效onReadObject(obj对象){
        //使用OBJ东西
        如果(obj.isDoingSomeMaliciousActivities()){
            stream.close();
        }否则如果(obj.isDoingGoodStuff){
            stream.writeObject(新GoodStuff());
        }
    }
});
stream.startReading();
如果(iHaveAGoodDay){
    stream.writeObject(新Iam​​Happy());
}其他{
    stream.writeObject(新IwillHackYou());
}
视频下载(10000);
stream.close();

这code是套接字层的核心。它不会工作,因为我没有测试它。你首先需要了解code继续进行协议。

注意:不要怕使用你认为你需要,因为你正在构建的通知事件层的听众。这就像用户互动时presses一个按钮,但与插座。

When I try to send a customobject (See Content.java) from my client to the server with ObjectOutputStream, I get StreamCorruptedException after the first object is sent. So if I try to send another object I get the exception, (it works the first time). I have googled and read a LOT of stuff, and now I'm about to give up, so I ask for your help.

Client.java

public class Client extends Thread {
private final static String TAG ="Client";
private final static String IP = "10.0.2.2";
private final static int PORT = 12345;
private Socket s;
private static ObjectOutputStream out;
private static ObjectInputStream in;
//private PrintWriter out;
//private BufferedReader in;
private TextView tv;
private Content c = new Content("");

public Client(TextView tv) {
    this.tv = tv;

}

public void run() {
    s = null;
    out = null;
    in = null;
    String res;

    try {
        s = new Socket(IP, PORT);
        Log.v(TAG, "C: Connected to server" + s.toString());

        out = new ObjectOutputStream(s.getOutputStream());
        in = new ObjectInputStream(s.getInputStream());

        //out = new PrintWriter(s.getOutputStream(), true);
        //in = new BufferedReader(new InputStreamReader(s.getInputStream()));
        //c.setText("PING to server from client");
        //out.writeObject(c);


        while((c = (Content)in.readObject()) != null) {
            try {
                    res = c.getText();
                    Log.i(TAG, res);
            } catch (Exception e) {
                Log.e("readobject", e.toString());
            }
        }

    } catch(Exception e) {
        Log.e("run @ client", e.toString());
    } finally {
        try {
            out.close();
            in.close();
            s.close();
        } catch(IOException e) {
            Log.e(TAG, e.toString());
        }
    }
}

public String setText() throws Exception{
    return in.toString();

}

public void sendText(String text) {
    Content cont = new Content(text);
    try {
        out.writeObject(cont);
    } catch(Exception e) {
        e.printStackTrace();
        Log.e("writeObject", e.toString());
    } finally {
        try {
            out.flush();
            out.close();
            s.close();
            Log.i(TAG, "Object sent");
        } catch (Exception e){}
    }


}
}

Content.java

public class Content implements Serializable{
private String text;

public Content(String text) {
    this.text = text;
}

public String getText() {
    return text;
}

public void setText(String text) {
    this.text = text;
}
}

Stack:

04-24 17:09:12.345: WARN/System.err(520): java.io.StreamCorruptedException
04-24 17:09:12.355: WARN/System.err(520): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1707)
04-24 17:09:12.355: WARN/System.err(520): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1660)
04-24 17:09:12.365: WARN/System.err(520): at client.android.Client.sendText(Client.java:83)
04-24 17:09:12.365: WARN/System.err(520): at client.android.ClientActivity.sendToServer(ClientActivity.java:38)
04-24 17:09:12.365: WARN/System.err(520): at java.lang.reflect.Method.invokeNative(Native Method)
04-24 17:09:12.365: WARN/System.err(520): at java.lang.reflect.Method.invoke(Method.java:521)
04-24 17:09:12.365: WARN/System.err(520): at android.view.View$1.onClick(View.java:2026)
04-24 17:09:12.365: WARN/System.err(520): at android.view.View.performClick(View.java:2364)
04-24 17:09:12.365: WARN/System.err(520): at android.view.View.onTouchEvent(View.java:4179)
04-24 17:09:12.365: WARN/System.err(520): at android.widget.TextView.onTouchEvent(TextView.java:6541)
04-24 17:09:12.375: WARN/System.err(520): at android.view.View.dispatchTouchEvent(View.java:3709)
04-24 17:09:12.375: WARN/System.err(520): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
0    4-24 17:09:12.385: WARN/System.err(520): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
04-24 17:09:12.385: WARN/System.err(520): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
04-24 17:09:12.385: WARN/System.err(520): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884)
04-24 17:09:12.385: WARN/System.err(520): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1659)
04-24 17:09:12.385: WARN/System.err(520): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107)
04-24 17:09:12.385: WARN/System.err(520): at android.app.Activity.dispatchTouchEvent(Activity.java:2061)
04-24 17:09:12.395: WARN/System.err(520): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1643)
04-24 17:09:12.395: WARN/System.err(520): at android.view.ViewRoot.handleMessage(ViewRoot.java:1691)
04-24 17:09:12.395: WARN/System.err(520): at android.os.Handler.dispatchMessage(Handler.java:99)
04-24 17:09:12.395: WARN/System.err(520): at android.os.Looper.loop(Looper.java:123)
04-24 17:09:12.395: WARN/System.err(520): at android.app.ActivityThread.main(ActivityThread.java:4363)
04-24 17:09:12.395: WARN/System.err(520): at java.lang.reflect.Method.invokeNative(Native Method)
04-24 17:09:12.395: WARN/System.err(520): at java.lang.reflect.Method.invoke(Method.java:521)
04-24 17:09:12.395: WARN/System.err(520): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
04-24 17:09:12.395: WARN/System.err(520): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
04-24 17:09:12.395: WARN/System.err(520): at dalvik.system.NativeStart.main(Native Method)

EDIT: added ClientActivity.java ClientActivity.java

public class ClientActivity extends Activity {
private EditText et;
private Client c;
private TextView tv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    et =(EditText)findViewById(R.id.clientTxt);
    tv = (TextView)findViewById(R.id.recievedTxt);

    c = new Client(tv);
    c.start();

    try {
        tv.setText(c.setText());
    } catch (Exception e) {}


}

public void sendToServer(View v) throws Exception{
    String text = et.getText().toString();
    Log.i("EdittextVALUE", text);
    c.sendText(text);

}

}

Server.java

public class Server extends Thread {
private static final String TAG = "ServerThread";
private static final int PORT = 12345;

public void run() {
    ServerSocket ss = null;
    Socket s = null;
    String res = "";

    try {
        Log.i(TAG, "Start server");
        ss = new ServerSocket(PORT);
        Log.i(TAG, "ServerSocket created waiting for Client..");
        while(true) {
            s = ss.accept();
            Log.v(TAG, "Client connected");
            Connection c = new Connection(s);
        }
    }catch(IOException e) {
        e.printStackTrace();
    } finally {
        try {
            //out.close();
            //in.close();
            s.close();
            ss.close();
        } catch (IOException e) {}
    }
}

Connection.java

public class Connection extends Thread {
private Socket socket;
private static ObjectOutputStream out;
private static ObjectInputStream in;
private final String TAG = "ConnectionClass";

public Connection(Socket socket) {
    try {
        this.socket = socket;
        out = new ObjectOutputStream(socket.getOutputStream());
        in = new ObjectInputStream(socket.getInputStream());

        this.start();

    } catch (IOException ex) {
        ex.printStackTrace();
        Log.e(TAG, ex.toString());
    }

}

public void run() {
    String res = "";
    Content c = null;
    try {
        while(true) {
        while((c = (Content)in.readObject()) != null) {
            try {

                    res = c.getText();
                    Log.i(TAG, res);

            } catch (Exception e) {
                Log.e("lololololo", e.toString());
            }
        }
        }
    } catch (Exception ex) {
        Log.e(TAG, ex.toString());
    } finally {
        try {
            socket.close();
            in.close();
            out.close();
        } catch (Exception e) {}
    }

}

ServerActivity.java

public class ServerActivity extends Activity {
public Server server;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    server = new Server();
    server.start();
}
}

解决方案

EDIT: I've added an array in the receiver to close all streams when the receiver stops.

You should redesign your protocol layer. In both devices you have to create a ServerSocket to listen for new Sockets. Obviously, if you call any read() method the current thread will enter in a blocked state, so you need to use a secondary thread. You need to start() and stop() the receiver and use a listener to notify the socket creations. A possible implementation (it can be improved a lot, but the core is this):

Receiver.java

public class Receiver{
private ArrayList<SocketStream> socketStreams;
    private OnNewSocketListener listener;
    private ServerSocket server;
    private Thread thread;
    private int port;

    public static interface OnNewSocketListener{
        void onNewSocket (Stream stream);
    }

    public Receiver (int port, OnNewSocketListener listener){
        this.listener = listener;
            this.port = port;
    }

    public synchronized start (){
        if (thread != null) return;

        server = new ServerSocket (port);
        thread = new Thread (new Runnable (){
                @Override
                public void run (){
                    try{
                        running = true;
                        while (running){
                        socketStreams.add (stream);
                                                    //See Stream.java below
                            listener.onNewSocket (new Stream (server.accept ()));
                        }
                    }catch (SocketException e){
                        //stop() has been called
                    }catch (IOException e){
                        //Error handling
                    }
                }
            }).start ();
        }
    }

    public synchronized void stop (){
        if (thread == null) return;

        running = false;
        try{
            if (server != null){
                server.close ();
            }
        }catch (IOException e){}

    for (SocketStream stream: socketStreams){
        stream.close ();
    }
    socketStreams.clear ();

        thread = null;
    }
}

Then you need another class that starts a thread when you want to read and write to this socket. To read you need another thread. You also need another listener to notify the object read and to notify when the other device closes the stream. You need a startReading() and close() methods (if you stop reading the socket it will close):

Stream.java

public class Stream{
    private Socket socket;
    private OnCloseStreamListener closeListener;
    private OnReadObjectListener readListener;
    private ObjectInputStream in;
    private ObjectOutputStream out;
    private Thread thread;

    public static interface OnReadObjectListener{
        void onReadObject (Object obj);
    }

    public static interface OnCloseStreamListener{
        void onCloseStream ();
    }

    //Used by the receiver to create an input socket
    public Stream (Socket socket){
        this.socket = socket;
        out = new ObjectOutputStream (socket.getOutputStream ());
    }

    //Used by the user to create an output socket, when the client wants to create a socket with the server
    public Stream (String address, int port){
        socket = new Socket (address, port);
        out = new ObjectOutputStream (socket.getOutputStream ());
    }

    public void setOnCloseStreamListener (OnCloseStreamListener listener){
        closeListener = listener;
    }

    public void setOnReadObjectListener (OnReadObjectListener listener){
        readListener = listener;
    }

    public synchronized void startReading (){
        if (thread != null) return;

        thread = new Thread (new Runnable (){
            @Override
            public void run (){
                try{
                    in = new ObjectInputStream (socket.getInputStream ());
                    reading = true;
                    while (reading){
                        Object obj = in.readObject ();
                        if (obj == null){
                            //The other device has closed its socket stream
                            reading = false;
                            closeListener.onCloseSocketStream ();
                        }else{
                            readListener.onReadObject (obj);
                        }
                    }
                }catch (SocketException e){
                    //stopReading() has been called
                }catch (IOException e){
                    //Error handling
                }
            }
        }).start ();
    }

    public synchronized void writeObject (Object obj){
        out.writeObject (obj);
        out.flush;
    }

    public synchronized void close (){
        if (thread != null){
            reading = false;
            socket.close ();
            in.close ();
            out.close ();
            thread = null;
        }else{
            socket.close ();
            in.close ();
        }
    }
}

Usage:
Server

Receiver receiver = new Receiver (5000, new Receiver.OnNewSocketListener (){
    @Override
    void onNewSocket (Stream stream){
        stream.setOnCloseStreamListener (new Stream.OnCloseStreamListener (){
            @Override
            void onCloseStream (){
                //Stream is closed automatically, don't need to call close()
                //Do something
            }
        });
        stream.setOnReadObjectListener (new Stream.OnReadObjectListener (){
            @Override
            void onReadObject (Object obj){
                //Do something with obj
                if (obj.isDoingSomeMaliciousActivities ()){
                    stream.close ();
                }else if (obj.isDoingGoodStuff){
                                    stream.writeObject (new GoodStuff ());
                            }
            }
        });
        stream.startReading ();
    }
});
receiver.start ();
Thread.sleep (10000);
receiver.stop ();

Client

Stream stream = new Stream ("localhost", 5000);
stream.setOnCloseStreamListener (new Stream.OnCloseStreamListener (){
    @Override
    void onCloseStream (){
        //Stream is closed automatically, don't need to call close()
        //Do something
    }
});
stream.setOnReadObjectListener (new Stream.OnReadObjectListener (){
    @Override
    void onReadObject (Object obj){
        //Do something with obj
        if (obj.isDoingSomeMaliciousActivities ()){
            stream.close ();
        }else if (obj.isDoingGoodStuff){
            stream.writeObject (new GoodStuff ());
        }
    }
});
stream.startReading ();
if (iHaveAGoodDay){
    stream.writeObject (new IamHappy ());
}else{
    stream.writeObject (new IwillHackYou ());
}
Thread.sleep (10000);
stream.close ();

This code is the core of the socket layer. It won't work because I don't tested it. You first need to understand the code to proceed with the protocol.
Note: Don't be afraid to use all the listeners you think you need because you are constructing a layer that notifies events. It's like the user interaction when presses a button but with sockets.

这篇关于ObjectOutputStream中和java.io.StreamCorruptedException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆