客户端:
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,,,,,,有点蒙了
|