zoukankan      html  css  js  c++  java
  • java编写socket使用bufferedReader.readLine()问题研究

    不写java代码好久,临时写个socket通讯竟然失败,郁闷之下仔细研究了下。

    客户端使用BufferedReader来读取数据,在while中调用BufferedReader.readLine()函数,结果程序运行起来之后一直死等,就是不输出想要的结果。

    google发现 readLine()方式是读行的,所以只有遇到换行符或者流结束的时候才会得到结果,在window系统下使用" "代替换行符,验证ok。

    即在我们一般的服务端输出信息

    printWriter.write("news");
    
    //输入换行符并发送到客户端
    
    printWriter.write("
    ");
    
    printWriter.flush();

    下面附上几个简单源码:小弟这里是用来解决flex调用socket垮与文件许可的,所以下面内容也是以此为例,服务需支持多次调用,客户端接收到跨域文件后则关闭

    首先是最直接的,不使用BufferedReader(),个人感觉这个更简单清晰些

    服务端,客户端都使用DataInputStream; DataOutputStream();

    服务代码:

    public class Server {
    	public static void main(String args[]){
    		try {
    			DataInputStream din;
    			DataOutputStream dout;
    			
    			ServerSocket server = new ServerSocket(4444);
    			
    			while(true){
    				Socket client = server.accept();
    				din  = new DataInputStream(client.getInputStream());
    				dout = new DataOutputStream(client.getOutputStream());
    				
    				String s;
    				if((s = din.readUTF()) != null){
    					System.out.println(s);
    				}
    				
    				if(s.equals("<policy-file-request/>")){
    					String msg = "<?xml version="1.0"?>" + "<cross-domain-policy>" 
    					+ "<site-control permitted-cross-domain-policies="all"/>"
    					+ "<allow-access-from domain="*" to-ports="*" />"
    					+ "</cross-domain-policy>";
    					dout.writeUTF(msg);
    				}
    				din.close();
    				dout.close();
    				client.close();
    			}
    			
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    }
    

    客户端:

    public class Client {
    
    	public static void main(String args[]){
    		
    		DataInputStream din;
    		DataOutputStream dout;
    		try {
    			Socket client = new Socket("127.0.0.1", 2000);
    			
    			din  = new DataInputStream(client.getInputStream());
    			dout = new DataOutputStream(client.getOutputStream());
    			dout.writeUTF("<policy-file-request/>");
    			
    			String s = null;
    			if((s=din.readUTF()) != null){
    				System.out.println(s);
    			}
    			din.close();
    			dout.close();
    			client.close();
    	            
    		} catch (UnknownHostException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    		
    	}
    }
    

    更换客户端接收为BufferedReader,使用readLine()方法。如果继续使用上面的服务,那么依然是没有错的....因为上面的服务段在信息输出之后理科调用了dout.colse方法。正如我们开始说的,当流结束的时候readLine()方法也能读取到结果。  如果是想实现一个客户端和服务端保持连接一直交互通讯的功能,那么请在上面的信息输入完成后添加如下代码

    dout.writeUTF(msg);//补充
    //因为在客户端使用bufferedReader.readLine()在读取,这里必须输入换行符,
    //并且调用fluesh(),方法。否则客户端将陷入死等状态
    dout.writeUTF("
    ");
    dout.flush();
    

    此时客户端代码如下:

    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    
    public class Client {
    
    	public static void main(String args[]){
    
    		DataOutputStream dout;
    		BufferedReader br;
    		PrintWriter out;
    		try {
    			Socket client = new Socket("127.0.0.1", 4444);
    			
    			br  = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
    			dout = new DataOutputStream(client.getOutputStream());
    			dout.writeUTF("<policy-file-request/>");
    			
    			String s = null;
    			while(true){
    				s = br.readLine();
    				if(s != null){
    					System.out.println(s);
    					break;
    				}
    			}
    			
    			br.close();
    			dout.close();
    			client.close();
    	            
    		} catch (UnknownHostException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    		
    	}
    }

    最后,总结两点:

    一、readLine()方法,需要明确换行符或者结束符,信息需要flush()才能接受到,增加了两端的信息输入(多输入换行符,并且这个符号不同系统是不一样的)

    二,任何流进行写入完成后请调用flush()方法推送下。  以确保正确性

    当然bufferedReader在操作字符的时候有很多更直观的接口以供调用,使用过程中需仔细注意

  • 相关阅读:
    vue箭头函数问题
    JS函数知识点梳理
    因tensorflow版本升级ImportError: No module named 'tensorflow.models.rnn'
    数据库优化,以实际SQL入手,带你一步一步走上SQL优化之路!
    在 IntelliJ IDEA 中这样使用 Git,效率提升2倍以上
    百万级高并发mongodb集群性能数十倍提升优化实践
    阿里巴巴Java开发手册正确学习姿势是怎样的?刷新代码规范认知
    50道Redis面试题史上最全,以后面试再也不怕问Redis了
    没想到Spring Boot居然这么耗内存,有点惊讶
    源码角度分析-newFixedThreadPool线程池导致的内存飙升问题
  • 原文地址:https://www.cnblogs.com/xignzou/p/3202346.html
Copyright © 2011-2022 走看看