客户端:

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方法阻塞问题的更多相关文章

  1. Java socket中关闭IO流后,发生什么事?(以关闭输出流为例)

    声明:该博文以socket中,关闭输出流为例进行说明. 为了方便讲解,我们把DataOutputstream dout = new DataOutputStream(new BufferedOutpu ...

  2. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

  3. Java多线程中的join()方法

    一.join()方法介绍 join() 定义在Thread.java中.join()方法把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的join( ...

  4. 模拟做饭系统(java+线程中的join方法)

    (一)项目框架分析 妈妈要去做饭,发现没有酱油,让儿子去买酱油,然后回来做饭. 根据面向对象的思想,有两个对象,妈妈和儿子 主要有两个方法: (一)没有线程控制(即儿子没有买酱油回来妈妈就做好饭了)+ ...

  5. 关于Java JDK中 URLDecoder.decode 方法

    java.net.URLDecoder.decode 在项目中碰到了个比较奇怪的问题,就是我在本地使用java.net.URLDecoder.decode(ruleName)方法解码,没有问题,本地的 ...

  6. java 多线程中的wait方法的详解

    java多线程中的实现方式存在两种: 方式一:使用继承方式 例如: PersonTest extends Thread{ String name; public PersonTest(String n ...

  7. java——包装类中的equals方法

    基本数据类型包装类中的equals方法用于比对相同包装类中的值是否相等,如果两者比较的包装类类型不同则返回false: Byte public boolean equals(Object obj) { ...

  8. Java 输出流中的flush方法

    转自:http://blog.csdn.net/jiyangsb/article/details/50984440 java中的IO流中的输出流一般都有flush这个操作,这个操作的作用是强制将缓存中 ...

  9. 编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议16~20)

    建议16:易变业务使用脚本语言编写 Java世界一直在遭受着异种语言的入侵,比如PHP,Ruby,Groovy.Javascript等,这些入侵者都有一个共同特征:全是同一类语言-----脚本语言,它 ...

随机推荐

  1. spring boot 系列之八:SpringBoot处理定时任务

    项目经常会用到定时任务,springboot自然是可以通过整合相关组件来实现的. 目前常用的定时任务的实现有两种: 通过spring 自带的定时器任务@Schedule来实现 通过Quartz来实现 ...

  2. noip模拟48

    A. Lighthouse 很明显的容斥题,组合式与上上场 \(t2\) 一模一样 注意判环时长度为 \(n\) 的环是合法的 B. Miner 题意实际上是要求偶拉路 对于一个有多个奇数点的联通块, ...

  3. C#开源类库SimpleTCP

    目录 简介 使用方法 实现客户端 实现服务端 总结 简介 工作中经常遇到需要实现TCP客户端或服务端的时候,如果每次都自己写会很麻烦且无聊,使用SuperSocket库又太大了.这时候就可以使用Sim ...

  4. shell脚本测试变量是否为空,测试文件是否存在,sed修改配置文件参数,分支语句

    Shell脚本 1. 基本的几个变量 使用$?获取最近一次的执行结果: 使用$#获取传递的参数个数,类似C语言中的int argc; 使用$@获取所有的传参,类似C语言的char **argv 2. ...

  5. 第05课:GDB 常用命令详解(上)

    本课的核心内容如下: run 命令 continue 命令 break 命令 backtrace 与 frame 命令 info break.enable.disable 和 delete 命令 li ...

  6. 口护万亿市场杀出的实力派 Oclean欧可林

    撰文 |懂懂 编辑 | 秦言 来源:懂懂笔记 在"青年必去的电影节"上,发现了一个跟他们打成一片的智能护齿"新星". 25日,备受关注的第15届FIRST青年电 ...

  7. Docker系列(21)- DockerFile介绍

    DockerFile介绍 dockerfile是用来构建docker镜像的文件!命令参数脚本! 构建步骤 编写一个dockerfile文件 docker build构建成为一个镜像 docker ru ...

  8. Charles的breakpoint功能

    修改请求报文 比如,前端已经控制了输入内容,而我们需要验证接口是否做了校验,这时候怎么测试? 可以通过charles抓包,修改请求报文,修改为在页面上无法输入的内容,发出去然后看后台怎么处理. 修改返 ...

  9. python风格对象

    对象表示形式 python提供了两种获取对象字符串表示形式的标准方式 repr()         //便于开发者理解的方式返回对象的字符串表示形式(一般来说满足obj==eval(repr(obj) ...

  10. spy++查找窗口句柄

    spy++可以用来查找桌面程序(c/s)的窗口句柄,实现自动化测试. def find_idxSubHandle(pHandle, winClass, index=0): ""&q ...