总是在我的套接字客户端中使用断开的管道使用sendUrgentData

时间:2015-03-26 04:57:45

标签: java sockets

我写了一个SocketClient来连接套接字,并在其中添加一些回调。

public class SocketClientV2 {

    public static void main(String[] args) {

        SocketClientV2.Listener listener = new SocketClientV2.Listener() {

            @Override
            public void recv(byte[] result) {
                // TODO Auto-generated method stub
                System.out.println("====recv something");
            }

            @Override
            public void connected() {
                // TODO Auto-generated method stub
                System.out.println("=====connected!");
            }

            @Override
            public void disconnect() {
                // TODO Auto-generated method stub
                System.out.println("=====disconnect!");
            }
        };

        SocketClientV2 client = new SocketClientV2("172.16.16.102", 4444,
                10000, listener);
        byte[] test = new byte[10];
        test[0] = (byte) 0x1c;
        test[1] = (byte) 0xff;
        test[2] = (byte) 0x08;
        client.send(test);

    }

    public interface Listener {
        public void recv(byte[] result);
        public void connected();
        public void disconnect();
    }

    Socket client = null;
    boolean isConnect = false;
    OutputStream outputStream = null;
    InputStream inputStream = null;
    public SocketClientV2() {
    }
    Listener cb = null;
    public SocketClientV2(String site, int port, int timeout, Listener cb) {
        this.cb = cb;
        try {
            client = new Socket(site, port);
            client.setSoTimeout(timeout);
            System.out.println("Client is created! site:" + site + " port:"
                    + port);

            if (isConnected()) {
                isConnect = true;
                if (cb != null) {
                    cb.connected();
                }

                checkConnect();
                listenRecv();
            }

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Socket getClient() {
        return this.client;
    }
    public void closeSocket() {
        try {
            isConnect = false;
            inputStream.close();
            outputStream.close();
            client.close();
            client = null;

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private boolean isConnected() {
        try {
            client.sendUrgentData(0xff);
            isConnect = true;
        } catch (Exception e) {
            System.out.println("return false....2");
            isConnect = false;
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private void checkConnect() {
        new Thread() {

            @Override
            public void run() {
                // TODO Auto-generated method stub

                System.out.println("check connect....1");
                try {

                    while (isConnected()) {

                        Thread.sleep(500);
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {

                    System.out.println("finally....3");
                    if (cb != null) {
                        cb.disconnect();
                    }
                    closeSocket();
                }
            }
        }.start();

    }

    private void listenRecv() {
        new Thread() {

            @Override
            public void run() {
                // TODO Auto-generated method stub

                System.out.println("listening Recv....");

                try {

                    inputStream = client.getInputStream();
                    while (isConnect) {
                        byte[] result = readStream(inputStream);
                        if (cb != null) {
                            cb.recv(result);
                        }
                        Thread.sleep(500);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }.start();

    }
    public void send(final byte[] byteSend) {
        new Thread() {

            @Override
            public void run() {
                // TODO Auto-generated method stub

                // System.out.println("sendMsg  coming....");

                if (isConnect) {

                    try {

                        outputStream = client.getOutputStream();
                        outputStream.write(byteSend);
                        outputStream.flush();

                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

            }

        }.start();

    }

    public byte[] readStream(InputStream inStream) throws Exception {
        int count = 0;
        while (count == 0) {
            // System.out.println(0);
            count = inStream.available();
            // if(count!=0)
            // System.out.println(count);
        }
        byte[] b = new byte[count];
        inStream.read(b);
        return b;
    }
}

有一个线程checkConnect来检查套接字的连接状态..

但运行几分钟后会断开连接,

Client is created! site:172.16.16.102 port:4444
=====connected!
check connect....1
listening Recv....
====recv something
====recv something
====recv something
====recv something
====recv something
====recv something
====recv something
return false....2
java.io.IOException: Broken pipe
    at java.net.PlainSocketImpl.socketSendUrgentData(Native Method)
    at java.net.PlainSocketImpl.sendUrgentData(PlainSocketImpl.java:622)
    at java.net.Socket.sendUrgentData(Socket.java:954)
    at com.udpdemo.multicast.SocketClientV2.isConnected(SocketClientV2.java:100)
    at com.udpdemo.multicast.SocketClientV2.access$0(SocketClientV2.java:98)
finally....3
=====disconnect!
    at com.udpdemo.multicast.SocketClientV2$2.run(SocketClientV2.java:121)
java.io.IOException: Stream closed.
    at java.net.PlainSocketImpl.available(PlainSocketImpl.java:483)
    at java.net.SocketInputStream.available(SocketInputStream.java:217)
    at com.udpdemo.multicast.SocketClientV2.readStream(SocketClientV2.java:205)
    at com.udpdemo.multicast.SocketClientV2$3.run(SocketClientV2.java:154)

以及sendUrgentData ???

的问题

1 个答案:

答案 0 :(得分:1)

'断管'始终意味着您写入了已被对等方关闭的连接。这是一个应用程序协议错误。

但是除非这个客户端的对等方没有用Java编写,否则首先使用紧急数据是没有意义的。 Java只能在线接收紧急数据,即在已经发送的所有其他待处理数据之后。只有当对等方呼叫setOOBLine(true)时才会发生这种情况,否则就会发生

  

默认情况下,此选项被禁用,并且套接字上收到的TCP紧急数据将被静默丢弃。

您可以通过检测断开连接来执行此操作。在这种情况下,你的梦想成真,它的工作,你所要做的就是相应地调整你的捕获和你的代码。但这通常不是一种可靠的技术。

其他说明:

  1. isConnected()在创建Socket,之后测试它时永远不会是假的,之后它永远不会变得虚假。您需要重新访问所有调用此方法的代码。其中大部分都没有意义,或者依赖于错误的假设。
  2. readStream()返回零时,您的available()方法旋转循环。这绝对没有意义。你只是在吸CPU。它也与您尝试使用读取超时完全不一致,当这个循环存在时,它根本无法工作。以下read()调用将阻塞,直到至少一个字节的数据到达,或者流结束或发生异常。您现在的代码永远不会检测到流的结尾。您还需要完全重新设计这部分代码。例如,返回字节数组的做法很糟糕。
  3. 同一段代码完全忽略read().返回的计数。永远不要这样做。