关于java socket中的read方法阻塞问题
客户端:
public class TCPClient {
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("E:\\Trump.jpg");
Socket socket=new Socket("127.0.0.1",8888);
OutputStream os=socket.getOutputStream();
byte[] bytes=new byte[1024];
int len;
while((len=fis.read(bytes))!=-1){
//将读取到的数据传输到客户端与服务器端之间的IO流
os.write(bytes,0,len);
}
//读服务器回写的数据
InputStream is=socket.getInputStream();
len=is.read(bytes);
System.out.println(new String(bytes,0,len));
socket.close();
fis.close();
}
}
服务器端:
public class TCPServer {
public static void main(String[] args) throws IOException {
ServerSocket server=new ServerSocket(8888);
Socket socket=server.accept();
InputStream is=socket.getInputStream();
FileOutputStream fos=new FileOutputStream("E:\\Test\\Trump.jpg");
int len;
byte[] bytes=new byte[1024];
while ((len=is.read(bytes))!=-1) {
fos.write(bytes,0,len);
}
OutputStream os=socket.getOutputStream();
os.write("文件上传完毕!".getBytes());
fos.close();
socket.close();
}
}
这段代码执行以后会发现server类 read()方法发生了阻塞,经过查找资料发现read()是一个阻塞函数(阻塞函数就是当这个函数不执行完,函数所在线程就一直停止在这里不动。)。
在输入数据可用、检测到流末尾或者抛出异常前,read方法一直阻塞。如果客户端没有声明断开outputStream那么它就会认为客户端仍旧可能发送数据,像read()这种阻塞读取函数还有BufferedReader类种的 readLine()、DataInputStream种的readUTF()等。
解决方案:
Socket任意一端在调用完write()方法时调用shutdownOutput()方法关闭输出流,这样服务器端的inputStream上的read操作就会返回-1, 这里我们要注意下不能调用socket.getInputStream().close()。因为它会导致socket直接被关闭。 当然如果不需要继续在socket上进行读操作,也可以直接关闭socket。但是这个方法不能用于通信双方需要多次交互的情况。
原文:https://www.cnblogs.com/gaoqiri/p/10055610.html
关于java socket中的read方法阻塞问题的更多相关文章
- Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)
声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutpu ...
- 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)
编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...
- Java多线程中的join()方法
一.join()方法介绍 join() 定义在Thread.java中.join()方法把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的join( ...
- 模拟做饭系统(java+线程中的join方法)
(一)项目框架分析 妈妈要去做饭,发现没有酱油,让儿子去买酱油,然后回来做饭. 根据面向对象的思想,有两个对象,妈妈和儿子 主要有两个方法: (一)没有线程控制(即儿子没有买酱油回来妈妈就做好饭了)+ ...
- 关于Java JDK中 URLDecoder.decode 方法
java.net.URLDecoder.decode 在项目中碰到了个比较奇怪的问题,就是我在本地使用java.net.URLDecoder.decode(ruleName)方法解码,没有问题,本地的 ...
- java 多线程中的wait方法的详解
java多线程中的实现方式存在两种: 方式一:使用继承方式 例如: PersonTest extends Thread{ String name; public PersonTest(String n ...
- java——包装类中的equals方法
基本数据类型包装类中的equals方法用于比对相同包装类中的值是否相等,如果两者比较的包装类类型不同则返回false: Byte public boolean equals(Object obj) { ...
- Java 输出流中的flush方法
转自:http://blog.csdn.net/jiyangsb/article/details/50984440 java中的IO流中的输出流一般都有flush这个操作,这个操作的作用是强制将缓存中 ...
- 编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议16~20)
建议16:易变业务使用脚本语言编写 Java世界一直在遭受着异种语言的入侵,比如PHP,Ruby,Groovy.Javascript等,这些入侵者都有一个共同特征:全是同一类语言-----脚本语言,它 ...
随机推荐
- Python - 面向对象编程 - __call__()
__call()__ 的作用 使得类实例对象可以像普通函数那样被调用 实际栗子 from typing import Callable class PoloBlog: def __init__(sel ...
- 1.Java 基础
1. JDK 和 JRE 有什么区别? jdk:开发工具包,jre:java运行环境 jdk包含了jre和java开发环境,如编译java源码的编译器javac,还包含了许多java程序调试和分析的工 ...
- 1.26学习总结——css盒子模型
CSS 盒子模型(Box Model) 所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用. CSS盒模型本质上是一个盒子,封装周围的H ...
- 在PHP中检测一个类是否可以被foreach遍历
在PHP中,我们可以非常简单的判断一个变量是什么类型,也可以非常方便的确定一个数组的长度从而决定这个数组是否可以遍历.那么类呢?我们要如何知道这个类是否可以通过 foreach 来进行遍历呢?其实,P ...
- Linux系列(14) - grep
简述 grep是在文件当中匹配符合条件的字符串,作用是查找文件内容 格式 grep [选项] 字符串 文件名 选项 -i:忽略大小写 -v:排除指定字符串 -n:显示行号 例子 grep " ...
- php socket 发送http请求 GET POST
http://docs.php-http.org/en/latest/httplug/users.html <?php /** * Created by PhpStorm. * User: Mc ...
- Appium Android Toast控件
Android Toast控件是Android系统级别的控件,不是App的控件,getPageSource是⽆法找到的. Toast介绍 1.背景 在安卓设备里面,使用各种手机应用程序的时候,需要先进 ...
- P5012-水の数列【并查集,RMQ】
正题 题目链接:https://www.luogu.com.cn/problem/P5012 题目大意 \(n\)个数字的一个序列,\(T\)次询问给出\([l,r]\)要求 找出一个最大的\(x\) ...
- P5369-[PKUSC2018]最大前缀和【状压dp】
正题 题目链接:https://www.luogu.com.cn/problem/P5369 题目大意 一个数列\(a\)的权值定义为\(max\{\sum_{i=1}^ka_i\}(k\in[1,n ...
- Keras函数——keras.callbacks.ModelCheckpoint()及模型的训练
keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=False, save_ ...