Socket

该博客探讨了Java中Socket客户端的read方法存在的阻塞问题,指出其在处理大消息时可能导致效率低下。作者提出通过检查特定字符串(如XML头部或尾部)来优化读取过程,从而减少不必要的等待时间。此外,还讨论了如何处理数据流中的边界情况,以提高读取效率。
摘要由CSDN通过智能技术生成

Socket客户端


``import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.*;
import java.net.Socket;
import java.util.concurrent.TimeoutException;

public class SocketConn {
    private static final String TAG = SocketConn.class.getSimpleName();
    private static final Logger LOG = LogManager.getLogger(SocketConn.class);

    private Socket socket;
    private final DataOutputStream out;
    private final DataInputStream in;
    private final byte[] buffer;

    public SocketConn(Socket socket, int maxMessageLength) throws IOException {
        this.socket = socket;
        this.out = socket == null ? null : new DataOutputStream(new BufferedOutputStream(socket.getOutputStream(), maxMessageLength));
        this.in = socket == null ? null : new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        this.buffer = new byte[maxMessageLength];
    }

    public void write(byte[] b) throws Exception {
        if (LOG.isDebugEnabled()) {
            LOG.debug(TAG + ".write(" + new String(b) + ")\n");
        }

        if (this.out != null) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(TAG + ".write() isConnected=" + this.socket.isConnected() + ", isClosed=" + this.socket.isClosed());
            }

            // data
            this.out.write(b);
            this.out.flush();
        }

        if (LOG.isDebugEnabled()) {
            LOG.debug(TAG + ".write() END");
        }

    }


    public String run() {
        while(true) {
            try {
                if (!this.isClosed()) {
                    int timeout = this.socket.getSoTimeout();
                    long time = System.currentTimeMillis() + (long)timeout;
                    LOG.debug(TAG + "进入run方法");
                    int len = this.read();
                    LOG.debug("返回的长度信息:"+len);
                    if (len > 0) {
                        byte[] data = new byte[len];
                        System.arraycopy(this.buffer, 0, data, 0, len);

                        // 将text数据进行封装
                        String text = new String(data);

                        return "<receive>" + text + "</receive>";

                    }

                    if (timeout > 0 && System.currentTimeMillis() > time) {
                        throw new TimeoutException(this + " timed out after " + timeout + "ms!");
                    }

                    Thread.sleep(50L);
                    continue;
                }
                break;

            } catch (Exception var9) {
                LOG.error(TAG + ".run()", var9);
            } finally {
                this.close();
            }


        }
        return null;
    }


    public int read() throws Exception {
        if (this.isClosed()) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(TAG + ".read(closed)");
            }

            return 0;
        } else {
            int len = 0;
            byte b1;
            byte[] b;
            int off ;
            off = 0 ;
            byte[] end = null;
//            StringBuilder sb = new StringBuilder();
//            System.out.println("read开始读取时间:"+new Date());
//            while (-1 != (len = in.read(buffer))) {
//                System.out.println(len);
//                // 1. 源数组
//                // 2. 源数组要复制的起始位置
//                // 3. 目的数组
//                // 4. 目的数组放置的起始位置
//                // 5. 复制的长度
                System.arraycopy(buffer, 0, receiveBytes, len, recvMsgSize);
                work += recvMsgSize;
//                sb.append(new String(buffer, 0, len));
//                //单次交互结束标识,跳出监听
//                if(new String(buffer, 0, len).contains("</accept>")){
//                    break;
//                }
//            }
//            System.out.println("read结束读取时间:"+new Date());
//            return len;
            for(int headerOffset = 0; this.in.read(this.buffer, off, 1) >= 1; ++off) {
                b1 = this.buffer[off];
                if (b1 == 62) {
                    int startIndex;
                    int n;
                    if (end == null) {
                        if (this.buffer[off - 1] == 63) {
                            headerOffset = off + 1;
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("XML-Header: " + new String(this.buffer, 0, headerOffset));
                            }
                        } else {
                            if (this.buffer[off - 1] == 47) {
                                return off + 1;
                            }

                            for(startIndex = headerOffset; startIndex < off && this.buffer[startIndex] != 60; ++startIndex) {
                            }

                            int endIndex;
                            for(endIndex = startIndex + 1; endIndex < off && this.buffer[endIndex] != 32; ++endIndex) {
                            }

                            n = endIndex - startIndex;
                            end = new byte[n + 1];
                            end[0] = 60;
                            end[1] = 47;
                            System.arraycopy(this.buffer, startIndex + 1, end, 2, n - 1);
                        }
                    } else {
                        startIndex = end.length;
                        boolean ready = true;

                        for(n = 0; n < startIndex; ++n) {
                            if (this.buffer[off - startIndex + n] != end[n]) {
                                ready = false;
                                break;
                            }
                        }

                        if (ready) {
                            ++off;
                            n = this.in.read(this.buffer, off, this.in.available());

                            for(int i = 0; i < n; ++i) {
                                LOG.info(this + " ignored=" + this.buffer[off + i]);
                            }

                            return off;
                        }
                    }
                }
            }

            return 0;
        }
    }

    public boolean isClosed() {
        return this.socket == null || this.socket.isClosed();
    }

    public void close() {
        if (LOG.isDebugEnabled()) {
            LOG.debug(this + ".close() start");
        }

        if (this.socket != null) {
            try {
                if (LOG.isDebugEnabled()) {
                    LOG.debug(this + ".close() " + this.socket);
                }

                this.socket.close();
            } catch (Exception var4) {
            }
        }

        if (this.out != null) {
            try {
                this.out.close();
            } catch (Exception var3) {
            }
        }

        if (this.in != null) {
            try {
                this.in.close();
            } catch (Exception var2) {
            }
        }

        this.socket = null;
        if (LOG.isDebugEnabled()) {
            LOG.debug(this + ".close() end");
        }

    }

    public OutputStream getOutputStream() throws IOException {
        return this.out;
    }
}

socket的read()方法是一个阻塞方法,非常耗时,如何解决呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值