记录 serverSocket socket 输入,输出流,关闭顺序,阻塞,PrintWriter的一些问题.
2017-02-28 10:09
447 查看
关于socket.getOutputStream() 的一些问题, OutputStream的flush是一个空方法,所以需要另一个实现了Flush的流来包装一下
这里为什么使用PrintWriter,而不使用BufferedWriter
原因是在接收方使用BufferedReader 的readLine,而BufferedWriter.write并不会自动换行,所以会导致读取阻塞,需要手动换行,代码如下:
以下两个测试类代码,在输出数据的时候,输出空行为结束符,在读取输入流的时候都在循环内判断了readLine长度是否为0(当然规范的做法是约定长度,根据长度判断是否结束),原因如下摘抄☞:点击这里
对于socket,不能认为把某次写入到流中的数据读取完了就算流结尾了,但是socket流还存在,还可以继续往里面写入数据然后再读取。所以用BufferedReader封装socket的输入流,调用BufferedReader的readLine方法是不会返回null的
所以在循环内如果不判断 msg!=null&&msg.length()>0 那么程序将会一直阻塞在这里(程序是因为readLine阻塞,并不是死循环)
关于流的关闭会影响socket的使用,而且对一次连接关闭流以后,没有办法再次打开,哪怕只关闭输入流,也会导致输出流不能使用.反之亦然.
所以如果在一次IO操作以后,还有另一次IO,那么就先不关闭.等全部用完再关闭.
ServerSocket
ClientSocket
这里为什么使用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(); // } } } }
相关文章推荐
- Hbase 开启关闭遇到的一些问题记录 HregionServer 进程关不掉
- 【rubycas-server】遇到的一些问题记录
- linux环境下无阻塞键盘输入以及MAP容器中value为数组的一些问题
- 关于socket与serversocket中的输入输出流
- QTcpSocket使用过程中的一些问题记录
- linux socket编程client关闭时server崩溃问题
- QTcpSocket使用过程中的一些问题记录
- windows 2008 r2 下面搭建 iis+sql server +php5.6 环境遇见的一些问题记录一下
- socket-io-server安装及运行的相关问题记录
- 当客户端socket关闭时,select模型的server端该如何完美的释放掉连接的socket? [问题点数:100分,结帖人guopo]
- QTcpSocket使用过程中的一些问题记录
- JAVA文件读写输入输出流关闭问题、JAVA垃圾回收
- android Sockte、ServerSocket阻塞,不同步问题
- 【java解惑】输入输出流使用后及时关闭问题
- 【java解惑】输入输出流使用后及时关闭问题
- JAVA文件读写输入输出流关闭问题、JAVA垃圾回收
- 我常用的 socket connect 代码,主要是为了记录非阻塞问题
- centos下mysql问题记录--ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/
- 微软工程师对SQL Server中可不可以指定某一些语句不记录到日志问题的回复。
- [转]Win2003 server一些问题和设置参考(附序列号)