socket的read和available()方法

read()方法:如果没有可获取的字节,将会阻塞。
源码

   /**
     * Reads the next byte of data from the input stream. The value byte is
     * returned as an <code>int</code> in the range <code>0</code> to
     * <code>255</code>. If no byte is available because the end of the stream
     * has been reached, the value <code>-1</code> is returned. This method
     * blocks until input data is available, the end of the stream is detected,
     * or an exception is thrown.
     *
     * <p> A subclass must provide an implementation of this method.
     *
     * @return     the next byte of data, or <code>-1</code> if the end of the
     *             stream is reached.
     * @exception  IOException  if an I/O error occurs.
     */
    public abstract int read() throws IOException;


available()方法。
/**
     * Returns an estimate of the number of bytes that can be read (or
     * skipped over) from this input stream without blocking by the next
     * invocation of a method for this input stream. The next invocation
     * might be the same thread or another thread.  A single read or skip of this
     * many bytes will not block, but may read or skip fewer bytes.
     *
     * <p> Note that while some implementations of {@code InputStream} will return
     * the total number of bytes in the stream, many will not.  It is
     * never correct to use the return value of this method to allocate
     * a buffer intended to hold all data in this stream.
     *
     * <p> A subclass' implementation of this method may choose to throw an
     * {@link IOException} if this input stream has been closed by
     * invoking the {@link #close()} method.
     *
     * <p> The {@code available} method for class {@code InputStream} always
     * returns {@code 0}.
     *
     * <p> This method should be overridden by subclasses.
     *
     * @return     an estimate of the number of bytes that can be read (or skipped
     *             over) from this input stream without blocking or {@code 0} when
     *             it reaches the end of the input stream.
     * @exception  IOException if an I/O error occurs.
     */
    public int available() throws IOException {
        return 0;
    }

大概意思是:注意,一些实现方法将返回流的全部的字节数,有一些方法则不会,想通过这个方法的返回值来分配缓冲区的长度,来承接流的全部数据,这样是不正确。
尽量不使用available方法,如果使用真的需要使用,在available方法使用之前使用一次read,想下面这样。

//将接收到的数据存到字节数组bytes
    int firstByte = inputStream.read();
    int length = inputStream.available();
    byte[] bytes = new byte[length+1];
    bytes[0] = (byte)firstByte;
    inputStream.read(bytes,1,length);

知乎上有一段是这样的。供参考
read的文档说明大致是:如果因已到达流末尾而没有可用的字节,则返回值 -1。在输入数据可用、检测到流的末尾或者抛出异常前,此方法一直阻塞。 socket和文件不一样,从文件中读,读到末尾就到达流的结尾了,所以会返回-1或null,循环结束,但是socket是连接两个主机的桥梁,一端无法知道另一端到底还有没有数据要传输。 socket如果不关闭的话,read之类的阻塞函数会一直等待它发送数据,就是所谓的阻塞。如果发送的东西非常多必须要用循环读的话,可以有一下解决方案:

①在写方调用socket的shutdownOutput方法关闭输出流,该方法的文档说明为,将此套接字的输出流置于“流的末尾”,这样另一端的输入流上的read操作就会返回-1。但是这样不能实现多次交互。
②约定结束标志,当读到该结束标志时退出不再read。
③设置超时,会在设置的超时时间到达后抛出SocketTimeoutException异常而不再阻塞。
④双方定义好通信协议,在协议头部约定好数据的长度。当读取到的长度等于这个长度时就不再继续调用read方法。

作者:qhyuan
链接:https://www.zhihu.com/question/39851782/answer/86588005
来源:知乎

参考连接

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Socket编程中,read()函数会阻塞进程,直到有数据可读。解决这个问题的方法是使用非阻塞模式,可以通过设置Socket的文件描述符为非阻塞模式来实现。 以下是一个示例代码,演示如何将Socket的文件描述符设置为非阻塞模式: ```c int set_socket_non_blocking(int socket_fd) { int flags = fcntl(socket_fd, F_GETFL, 0); if (flags == -1) { return -1; } flags |= O_NONBLOCK; if (fcntl(socket_fd, F_SETFL, flags) == -1) { return -1; } return 0; } ``` 以上代码使用了fcntl()函数来获取和设置Socket的文件描述符标志。首先,使用F_GETFL操作获取当前文件描述符标志,然后设置O_NONBLOCK标志,最后使用F_SETFL操作设置新的文件描述符标志。 使用以上函数设置Socket文件描述符为非阻塞模式后,read()函数将不再阻塞进程,而是立即返回。如果没有数据可读,则返回-1,并且errno被设置为EAGAIN或EWOULDBLOCK。因此,在进行读取操作时,应该根据返回值和errno来判断是否有数据可读。 以下是一个示例代码,演示如何使用非阻塞模式进行Socket读取: ```c char buffer[1024]; int bytes_read = 0; while (1) { bytes_read = read(socket_fd, buffer, sizeof(buffer)); if (bytes_read == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // no more data available to read break; } else { // error occurred perror("read"); break; } } else if (bytes_read == 0) { // connection closed by remote host break; } else { // process the received data process_data(buffer, bytes_read); } } ``` 以上代码使用while循环不断读取Socket数据,如果read()函数返回-1,则根据errno判断是否有数据可读。如果bytes_read为0,则表示远程主机关闭了连接。如果bytes_read大于0,则接收到了数据,可以对数据进行处理。 注意,使用非阻塞模式进行Socket编程需要注意处理EAGAIN和EWOULDBLOCK错误,以及可能出现的partial read(部分读取)情况。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值