A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 聂斌 中级黑马   /  2013-3-14 18:16  /  1428 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

客户端:
               

public class LoginClient {
                public static void main(String[] args) throws Exception
                {
                        Socket s = new Socket("192.168.1.254",10008);
                        //读取键盘录入的数据,,这里是定义输入流,,,
                        BufferedReader bufr =
                                new BufferedReader(new InputStreamReader(System.in));
                        //发送数据到服务器,把读取到的键盘数据发到服务器里,,,定义一个输出流
                        PrintWriter out = new PrintWriter(s.getOutputStream(),true);
                        //客户端读取服务器返回来的信息
                        BufferedReader bufIn =
                                new BufferedReader(new InputStreamReader(s.getInputStream()));               
                        for(int x=0; x<3; x++)
                        {
                                //读取键盘录入的数据
                                String line = bufr.readLine();
                       
                                //读取键盘录入时bufr.readLine()有可能返回null,,就是键盘没有输入数据,,比如键盘录入时你按crtl+c时readLine(里面的read方法就返回-1了
                                                //那么readLine()就返回null,,,之后out.println(line)就把null发给服务器了,,那个null发过去没有意义,,
                                //line==null是说你按crtl+c了不想往里面输入了就关闭客户端
                                if(line==null)
                                        break;
                                //把读取到的数据发送到服务器
                                out.println(line);

                                //读取服务器返回来的信息
                                String info = bufIn.readLine();
                                System.out.println("info:"+info);
                                //比如我第一次输入张三后,,发给服务器了,服务器就判断了说张三存在,,就把张三的信息返回给客户端,,bufIn.readLine()返回了张三了就代表张三登陆

成功,,,
                                //第一次输入张三登陆成功后就不需要再次输入用户名了,就退出客户端
                                if(info.contains("欢迎"))
                                        break;

                        }

                        //必须得关资源,,不关的话会占用服务器的资源,,,服务器只给你验证3次,,,
                        bufr.close();
                        s.close();
                }



把客户端封装到线程里

//封装客户端到线程里,,对每个客户端分配一个线程
public class LoginUserThread  implements Runnable{
        private Socket s;
        //不明确客户端,,就传入一个客户端
        LoginUserThread(Socket s)
        {
                this.s = s;
        }
        //方法里面验证客户端输入的用户名
        public void run()
        {
                String ip = s.getInetAddress().getHostAddress();
                System.out.println(ip+"....connected");
                try
                {
                        //服务器只验证3次
                        for(int x=0; x<3; x++)
                        {
                                //先获取到客户端发来的数据,创建一个输入流读取客户端的数据
                                BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
                                //客户端只发一句话,所以不需要循环
                                String name = bufIn.readLine();
                               
                                //用户名信息存到一个文件里了,,所以得读取文件信息,再判断文件信息里是否包含有客户端发来的用户名
                                //这里是读取文件信息
                                BufferedReader bufr = new BufferedReader(new FileReader("c:\\user.txt"));

                                PrintWriter out = new PrintWriter(s.getOutputStream(),true);

                                String line = null;

                                boolean flag = false;
                                //读取一行就验证一次...
                                while((line=bufr.readLine())!=null)//这个readLine()可以读到结尾,,因为流操作的是个文件user.txt,,,源是user.txt文件
                                                                                                        //能不能读到结尾就看流操作的是什么,,这里流操作的是个文件

user.txt
                                {
                                       
                                        if(line.equals(name))
                                        {
                                                //找到用户了就返回true,,,就不需要往下判断( equals(name )了就退出循环,,
                                                flag = true;
                                                break;
                                        }                               
                                }
                                //根据循环后的结果来判断要定义什么信息返回给客户端
                                if(flag)
                                {
                                        System.out.println(name+",已登录");
                                        out.println(name+",欢迎光临");
                                        //找到用户名之后就不需要再循环往下验证了
                                        break;
                                }
                                else
                                {
                                        System.out.println(name+",尝试登录");
                                        out.println(name+",用户名不存在");
                                }


                        }
                        //关闭客户端,,,三次都不满足,或者你输入一次就满足了就不继续验证了,,,都关闭服务器
                        s.close();
                }
                catch (Exception e)
                {
                        throw new RuntimeException(ip+"校验失败");
                }
        }



服务器:


public class LoginServer {
        public static void main(String[] args) throws Exception
        {
                ServerSocket ss = new ServerSocket(10008);

                //循环获取多个客户端,,,
                while(true)
                {
                        Socket s = ss.accept();
                        //为每一个客户端分配一个线程
                        new Thread(new LoginUserThread(s)).start();
                }
        }
}


结果:当你第一次输入hh时不存在,,就继续输入,,我再按crtl+c时,,,服务器返回:
hh
null,尝试登录

null,尝试登录

为什么会返回null呢,,,

我的理解是客户端LoginClient 里的bufr.readLine()方法,,这个readLine()里面有个read方法,,这个read方法是会返回-1的,,执行bufr.readLine()时就返回了null,,,那么之后就执行了s.close();客户端就结束了,,,此时 LoginUserThread类里面bufIn.readLine()就读了就读了一次客户端的信息,第一次读hh,第二次你客户端搞-1了所以
bufIn.readLine()就返回null,之后执行后面的System.out.println(name+",尝试登录"),,打印了第一个null,,,之后又循环了一次,就又读了一次null(执行了bufIn.readLine),,就打印了第二

个null..



我不明白的是,,,按crtl+c时客户端发送的是-1还是null,,,,,,有点蒙了

点评

如果问题未解决,请继续追问回复者,如果问题已经解决,请将分类改为“已解决”,谢谢  发表于 2013-3-16 23:22

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

4 个回复

倒序浏览
你在//客户端只发一句话,所以不需要循环String name = bufIn.readLine();这句话后面加上一个判断
if(name==null)break; ,这里要先判断一下读取到的name是不是null,也就是说,当按下ctrl+c的时候,是不需要再继续的。
回复 使用道具 举报
黄玉昆 发表于 2013-3-16 08:04
你在//客户端只发一句话,所以不需要循环String name = bufIn.readLine();这句话后面加上一个判断
if(name== ...

hh呵呵知道了谢谢哈
回复 使用道具 举报
呵呵但还是有点不明白客户端关闭后是返回-1吧
回复 使用道具 举报
聂斌 发表于 2013-3-17 01:34
呵呵但还是有点不明白客户端关闭后是返回-1吧

ctrl+c是强制关闭虚拟机,荡客户端ctrl+c后 服务端将接受不到数据 也就是说line=bufr.readLine()这句的line将没有数据,也就是line=null;所以while((line=bufr.readLine())!=null){}就不会执行,flag也就为false, 所以执行  else
{
  System.out.println(name+",尝试登录");
  out.println(name+",用户名不存在");
  }

直到循环结束

所以我认为客户端关闭,服务检测到连接断开后,直接将line=bufr.readLine()标记为null   客户端应该是没有发送数据

个人见解  可能不是很正确
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马