java编写socket使用bufferedReader.readLine()问题研究

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

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

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

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

printWriter.write("news");

//输入换行符并发送到客户端

printWriter.write("\r\n");

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("\r\n");
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在操作字符的时候有很多更直观的接口以供调用,使用过程中需仔细注意

 

posted @ 2013-07-20 14:09  行走_  阅读(6381)  评论(0编辑  收藏  举报