【优化】IO流应用之网络传输

来源:互联网 发布:淘宝卖家怎么申请直播 编辑:程序博客网 时间:2024/06/06 09:13

javase已经看到网络编程了,快结束啦!微笑掌声鼓励下。。。呵呵

经过一个月的自学,基本把java基础语法掌握的差不多了。我发现学的越多,就越喜欢java代码的简洁,清晰,很享受写代码的过程!加油吧,骚年!奋斗接下来就是通过小项目练手了!

废话不多说,下面是昨天写的代码,通过这个例子,我发现优化代码真的很重要!!!!

需求是这样子的,

客户端通过键盘录入用户名
服务端对这个用户名进行校验

如果该用户存在 在服务端显示xxx已登录
并在客户端显示xxx 欢迎光临

如果该用户不存在,在服务端显示xxx,尝试登陆
并在客户端显示xxx,该用户不存在

最多就登陆三次。

环境,控制台。

下面是我的代码。

用户数据存放在data.txt中

 

 

/* *本程序为方便调试,将客户端和服务端放在同一个.java文件中, *另外将ip地址设置为127.0.0.1,仅限本机登陆,如果连有局域网,可以 *进行局域网登陆测试,本人亲测通过。(需先获取对方ip)*/import java.net.*;import java.io.*;import java.util.*;//客户端class Client{//为保持代码简洁,这里抛出IO异常public static void main(String[] args)throws IOException{//建立socket服务Socket s=new Socket(InetAddress.getByName("127.0.0.1"),10006);BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));//键盘录入BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));String line=null;for(int i=0;i<3;i++){line=bufr.readLine();if(line==null)break;//将登录名发给服务端bufw.write(line);bufw.newLine();bufw.flush();//接收服务端反馈String dataRe=bufIn.readLine();System.out.println(dataRe);if(dataRe.contains("欢迎"))break;}s.close();}}//服务端class Server{public static void main(String[] args)throws IOException{//开启ServerSocket服务,监听一个端口ServerSocket ss=new ServerSocket(10006);while(true){Socket s=ss.accept();//多线程处理并发登陆new Thread(new LoginThread(s)).start();}}}class LoginThread implements Runnable{private Socket socket;private ArrayList<String> arr;LoginThread(Socket socket){this.socket=socket;}public void run(){try{System.out.println(socket.getInetAddress().getHostName()+"...connected");File file=new File("data.txt");//动态访问数据库,并遍历用户名,存入集合BufferedReader buda=new BufferedReader(new FileReader(file));String temp=null;arr=new ArrayList<String>();while((temp=buda.readLine())!=null){arr.add(temp);}//通过缓冲类包装getInputStream()和getOutputStream()方法BufferedReader bufr=new BufferedReader(new InputStreamReader(socket.getInputStream()));BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));String line=null;//这里要求循环获取信息并反馈for(int i=0;i<3;i++){line=bufr.readLine();//获取客户端发来的信息if(line==null)break;//遍历集合Iterator<String> it=arr.iterator();int count=0;while(it.hasNext()){//检索到该用户名if(it.next().equals(line)){System.out.println(line+"已登录");//反馈信息bufw.write("尊敬的"+line+",欢迎光临");bufw.newLine();bufw.flush();break;}elsecount++;}if(count==arr.size()){System.out.println(line+"尝试登陆");bufw.write(line+"用户不存在");bufw.newLine();bufw.flush();}}socket.close();//超过三次,自动断开连接}catch(IOException e){throw new RuntimeException();}}}

以上代码通过不够优化,特别是将文件中的数据存到集合中,每开启一个线程都会执行一次,效率很低,而且是通过计数器来判断返回信息的,比较低效。

下面将代码稍微优化一下。

import java.io.*;import java.net.*;//客户端class NClient{public static void main(String[] args)throws IOException{//建立服务Socket s=new Socket(InetAddress.getByName("127.0.0.1"),10006);BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));//键盘录入BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));BufferedReader bufIn=new BufferedReader(new InputStreamReader(s.getInputStream()));String line=null;String temp=null;for(int i=0;i<3;i++){//读取键盘录入,写入流中,注意,因为有缓冲,必须换行并刷新line=bufr.readLine();if(line==null)break;//如果录入为空,则退出循环bufw.write(line);bufw.newLine();bufw.flush();//接收服务端反馈temp=bufIn.readLine();System.out.println(temp);if(temp.contains("欢迎"))//登陆成功就退出循环break;}s.close();}}//服务端class NServer{public static void main(String[] args)throws IOException{ServerSocket ss=new ServerSocket(10006);while(true){Socket s=ss.accept();new Thread(new LoginThread(s)).start();}}}class LoginThread implements Runnable{private Socket s;LoginThread(Socket s){this.s=s;}public void run(){System.out.println(s.getInetAddress().getHostAddress()+"....connected");try{File file=new File("data.txt");BufferedReader bufr=new BufferedReader(new InputStreamReader(s.getInputStream()));BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));boolean flag=false;String line=null;for(int i=0;i<3;i++){line=bufr.readLine(); if(line==null) break;BufferedReader buf=new BufferedReader(new FileReader(file));String temp=null;while((temp=buf.readLine())!=null)if(line.equals(temp)){flag=true;break;}if(flag){System.out.println(line+"已登录");bufw.write("尊敬的"+line+",欢迎光临");bufw.newLine();bufw.flush();}else{System.out.println(line+"尝试登陆");bufw.write(line+",该用户名不存在");bufw.newLine();bufw.flush();}}s.close();}catch(IOException e){//throw new RuntimeException();e.printStackTrace();}}}

优化后的代码通过判断标记flag的boolean值向客户端返回信息,很高效。

运行结果如下(同时打开两个控制台):

 

提示:需要先打开服务端!

这里注意一个细节,客户端和服务端都有这样一行代码:

if(line==null)    break;

这是因为如果客户端第一次登陆已经登陆成功的话,就不必要继续登陆了,这时按ctrl+c退出时,服务端并不结束,且其readLine方法会读到null值,所以

我们在客户端加上这句判断。

思考:优化后的代码其实还可以继续优化,例如我们的BufferedWriter类每次write之后都需要换行并刷新缓冲区,

很麻烦,可以用PrinterWriter类,自动刷新。


 

 

原创粉丝点击