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