java - 总是在我的套接字客户端中使用 sendUrgentData 获取 Broken pipe

标签 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 有什么问题???

最佳答案

'Broken pipe' 总是意味着你写入了一个已经被对等方关闭的连接。这是应用程序协议(protocol)错误。

但是除非这个客户端的对等端不是用 Java 编写的,否则一开始就没有必要使用紧急数据。 Java 只能“在线”接收紧急数据,即在所有其他已发送的待处理数据之后。只有当对等方调用 setOOBLine(true) 时才会发生这种情况, 否则

by default, this option is disabled and TCP urgent data received on a socket is silently discarded.

您这样做可能是为了检测断开的连接。在这种情况下,你的梦想成真了,它成功了,你所要做的就是相应地调整你的捕获量和你的代码。但这通常不是可靠的技术。

其他说明:

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

关于java - 总是在我的套接字客户端中使用 sendUrgentData 获取 Broken pipe,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29271366/

相关文章:

c# - 具有大量客户端的套接字编程中的客户端到客户端通信

c++ - 如何在不同用户下为目标进程复制套接字

Python、请求、线程、python 请求关闭其套接字的速度有多快?

java - 通过网络进行对象反序列化

java - Chrome 移动模拟屏幕截图出现 Ashot 问题

java - 在运行时将动态值传递给 kafka 消费者主题以实现消息驱动的 channel 适配器

Java办公组件

Java 替换全部问题

java - 使用 Java 计算标准差?

c - linux 上的 unix 域套接字?