记录 serverSocket socket 输入,输出流,关闭顺序,阻塞,PrintWriter的一些问题.
关于socket.getOutputStream() 的一些问题, OutputStream的flush是一个空方法,所以需要另一个实现了Flush的流来包装一下
这里为什么使用PrintWriter,而不使用BufferedWriter
原因是在接收方使用BufferedReader 的readLine,而BufferedWriter.write并不会自动换行,所以会导致读取阻塞,需要手动换行,代码如下:
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("你好啊");
// 因为在服务端使用的是readLine,所以如果不调用newLine,那么会一直阻塞
bw.newLine();
bw.flush();
以下两个测试类代码,在输出数据的时候,输出空行为结束符,在读取输入流的时候都在循环内判断了readLine长度是否为0(当然规范的做法是约定长度,根据长度判断是否结束),原因如下摘抄☞:点击这里
对于socket,不能认为把某次写入到流中的数据读取完了就算流结尾了,但是socket流还存在,还可以继续往里面写入数据然后再读取。所以用BufferedReader封装socket的输入流,调用BufferedReader的readLine方法是不会返回null的
所以在循环内如果不判断 msg!=null&&msg.length()>0 那么程序将会一直阻塞在这里(程序是因为readLine阻塞,并不是死循环)
关于流的关闭会影响socket的使用,而且对一次连接关闭流以后,没有办法再次打开,哪怕只关闭输入流,也会导致输出流不能使用.反之亦然.
所以如果在一次IO操作以后,还有另一次IO,那么就先不关闭.等全部用完再关闭.
ServerSocket
@RunWith(JUnit4.class)
public class ServerSocketTest {
@Test
public void testServer(){
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket();
// serverSocket.setReuseAddress(true);
// System.out.println(InetAddress.getLocalHost());//获取的本机地址不一定正确
serverSocket.bind(new InetSocketAddress(8000)); while(true){
//一旦连接,返回的socket包含客户端信息的socket
Socket socket = serverSocket.accept();
PrintWriter pw = new PrintWriter(socket.getOutputStream(),true);
pw.println("host:"+socket.getInetAddress()+":"+socket.getPort()+"建立链接");
//这里发送空行作为结束符,当然规范做法是根据长度作为标识
pw.println("");
//因为new PrinWriter的时候指定了autoFlush的参数为true所以不用手动flush
// pw.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
for(String msg = br.readLine();msg!=null&&msg.length()>0;msg = br.readLine()){
System.out.println(msg);
}
pw.close();
br.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
ClientSocket
/**
*
* @author lzw
*
*/
@RunWith(JUnit4.class)
public class SocketClient {
@Test
public void testClient() throws UnknownHostException, IOException{
//表示连接到服务器的 地址以及端口
SocketAddress address = new InetSocketAddress("19.95.103.112",8000);
Socket socket = new Socket();
socket.connect(address,60000);//连接
//读取服务端返回的数据
getMsb(socket);
sendMsg(socket);
socket.close();
} private void sendMsg(Socket socket){
PrintWriter pw = null;
// BufferedWriter bw = null;
try { // bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
// bw.write("你好啊");
//因为在服务端使用的是readLine,所以如果不调用newLine,那么会一直阻塞
// bw.newLine();
// bw.flush();
// OutputStream os = socket.getOutputStream();
// //这个是一个空方法
// os.flush();
pw = new PrintWriter(socket.getOutputStream(),true);
pw.println("你好啊");
//输出空行作为结束标识
pw.println("");
//因为new PrinWriter的时候指定了autoFlush的参数为true所以不用手动flush
// pw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
//因为本次连接,到这个方法以后没有更多交互,所以可以关闭
if(pw!=null){
pw.close();
}
}
} private void getMsb(Socket socket){
InputStream is = null;
BufferedReader br = null;
try {
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
for(String msg = br.readLine();msg!=null&&msg.length()>0;msg = br.readLine()){
System.out.println(msg+"--");
}
} catch (IOException e) {
e.printStackTrace();
}finally{
//这里不能关闭流,否则会把socket也关闭了(因为后面还要发送数据,所以不能关闭流,不管是关闭输入输入其中之一,都会导致输入和输出都不能使用)
// try {
// if(br!=null)
// br.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
}
} }
记录 serverSocket socket 输入,输出流,关闭顺序,阻塞,PrintWriter的一些问题.的更多相关文章
- DatagramSocket(邮递员):对应数据报的Socket概念,不需要创建两个socket,不可使用输入输出流。
UDP编程: DatagramSocket(邮递员):对应数据报的Socket概念,不需要创建两个socket,不可使用输入输出流. DatagramPacket(信件):数据包,是UDP下进行传输数 ...
- Java 输入输出流 转载
转载自:http://blog.csdn.net/hguisu/article/details/7418161 1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所 ...
- java输入输出流总结 转载
一.基本概念 1.1 什么是IO? IO(Input/Output)是计算机输入/输出的接口.Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是 ...
- Java输入输出流(转载)
转自http://blog.csdn.net/hguisu/article/details/7418161 目录(?)[+] 1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作 ...
- java socket 以及 流 关闭的问题
首先我一下几个提出问题:稍后再做出解答. 问题一:A如果仅仅将输入流关闭(inA.close()),对A与B之间的连接是否有影响? A能否再次获得输入流(inA = socketA.getInputS ...
- Java 输入输出流 (七)
1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读 ...
- Java基础学习总结(47)——JAVA输入输出流再回忆
一.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列. Java的I/O流提供了 ...
- Java自学第10期——File类与IO流(输入输出流、处理流、转换流、缓冲流、Properties集合、打印流)
1.IO简介 IO(输入输出)通过java.io包下的类和接口来支持,包下包括输入.输出两种IO流,每种输入输出流又可分为字符流和字节流两大类. 2.File类 File类是io包下与平台无关的文件和 ...
- 关于java socket中的read方法阻塞问题
客户端: public class TCPClient { public static void main(String[] args) throws IOException { FileInputS ...
随机推荐
- Linux Shell 编程语法
原文地址:http://www.cnblogs.com/fhefh/archive/2011/04/13/2014967.html.感谢作者的无私分享 编写代码 在计划好要程序干什么以及如何使用程序的 ...
- 使用autoc js生成文章目录(侧边)导航栏
介绍: autocjs 是一个专门用来生成文章目录(Table of Contents)导航的工具.autocjs 会查找文章指定区域中的所有 h1~h6 的标签,并自动分析文章的层次结构,生成文章的 ...
- 完全卸载SQL Server 2008r2
完全卸载SQL Server 2008r2 "五一"时进行了系统重装,在没有卸载SQL Server 2008情况下尝试安装SQL Server 2008r2 ,安装提示成功但 ...
- JavaBean,List,Map,json格式之间转化方式
public class TestBean { private String id; private String name; private String password; public Stri ...
- 针对Chrome谷歌等浏览器不再支持showModalDialog的解决方案
最近在维护一个老项目,之前都是用IE来调试代码的.今天想着测试一下项目的兼容性,就用了谷歌浏览器,然后就遇到这样一个问题:一段用showModalDialog实现弹出模态框和返回值的js代码,在调试时 ...
- AOP 切面编程------JoinPoint ---- log日志
AOP 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件 ...
- CenOS 上安装 Redis 服务器
1.构建 Redis 因为 Redis 官方没提供 RPM 安装包,所以需要编译源代码,则需要安装 GCC & MAKE. 终端输入: yum install gcc make 从官网下载 t ...
- BZOJ 2957: 楼房重建 [线段树 信息合并]
传送门 题意:转换成斜率然后维护区间的上升序列(从区间第一个数开始的单调上升序列) 区间保存这个区间的最长序列的长度$ls$和最大值$mx$ 如何合并两个区间信息? 左区间一定选择,右区间递归寻找第一 ...
- 2018/2/14 设计模式学习笔记(一) 自己实现ArrayList,LinkedList和Iterator,以及在此过程中对于面向对象,面向接口,还有抽象类的一些思考感悟
因为本人目前为止学习编程不过七个月,所以后面的感悟对于一些大神来说可能嗤之以鼻,但对于一些刚刚入门的萌新来说在理解面向对象的思想上,以及抽象类和接口应该怎么设计等方面应该还是会有所帮助的 首先我们定义 ...
- VC调用Delphi对象接口
说在前头 很久没有碰Delphi的东西了,今天有个朋友让我帮他将一个Delphi中已经实现的功能在VC中进行使用,虽然后来又用VC的方式实现了该功能,但是在实现过程中想到了这样的调用方式,特写下本文以 ...