1.服务器端对一个客户端的校验
程序说明:
-
客户端登录,需要输入对应的用户名,密码,输入不成功,继续输入
一个服务端对应一个客户端,单一,输入正确,结束两个程序 -
ge对用户名,与密码是用数据流进行写出,读入,这样就不会造成读入混乱
-
例如:zhang123,你不知道从哪里分割开来,无法判断哪部分是用户名
zh,ang123 ; 还是zhan,g123等等
服务器端
public class Server {
private static String username = "zhang";
private static String password = "123";
public static void main(String[] args) {
try(ServerSocket serverSocket = new ServerSocket(8888);){
//阻塞
Socket socket = serverSocket.accept();
while(true) {
//获取输入流 输出流
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
String name = dis.readUTF();
String pass = dis.readUTF();
System.out.println(name+"====="+pass);
//做出响应
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
if(username.equals(name) && password.equals(pass)) {
dos.writeBoolean(true);
break;
}else {
dos.writeBoolean(false);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端
public class Client {
public static void main(String[] args) {
try (Socket socket = new Socket("127.0.0.1", 8888);
Scanner sc = new Scanner(System.in)) {
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
while (true) {
System.out.println("请输入用户名:");
String name = sc.next();
System.out.println("请输入用户名:");
String pass = sc.next();
//写出 发送到服务器端
dos.writeUTF(name);
dos.writeUTF(pass);
DataInputStream dis = new DataInputStream(socket.getInputStream());
boolean is = dis.readBoolean();
if (is) {
System.out.println("登录成功!");
break;
} else {
System.out.println("用户名或密码有误!");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2.服务器不停止,可以接收多个有序客户端
只要将服务器端的 try语句里的语句放在while死循环里即可
客户端不用改变
public class Server {
private static String username = "zhang";
private static String password = "123";
public static void main(String[] args) {
try(ServerSocket serverSocket = new ServerSocket(8888);){
while (true) {
//阻塞
Socket socket = serverSocket.accept();
while(true) {
//获取输入流 输出流
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
String name = dis.readUTF();
String pass = dis.readUTF();
System.out.println(name+"====="+pass);
//做出响应
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
if(username.equals(name) && password.equals(pass)) {
dos.writeBoolean(true);
break;
}else {
dos.writeBoolean(false);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
但是明白,只有一个客户端结束后,才可以连接下一个客户端,要想同时连接多个客户端,必须用多线程
3.多线程服务器,客户端并发访问
多线程服务器的重点是:什么时候开启线程
应该在连接后,再开启线程,如果在连接前开启,会造成没有停止,线程一直增加,服务器崩溃
在等待连接外,加上死循环,这样可以在开启一个线程后,会继续有一个等待连接
代码里,用了新类,来写线程里运行的代码
代码里的注释
public class Server {
private static String username = "zhang";
private static String password = "123";
public static void main(String[] args) throws IOException {
try(ServerSocket serverSocket = new ServerSocket(8888);){
// 制造死循环,可以一直有等待客户端连接,死循环在这里也是为了 制造多线程
while (true) {
// 阻塞
Socket socket = serverSocket.accept();
// 当没有阻塞,即有连接时,启动一个对应的 线程;
// 不能讲阻塞 放在线程里, 这样会直接启动多个线程
S s = new S(socket, username, password);
s.start();
// 启动线程后,循环回去,有一个新的等待,服务器不会停止
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class S extends Thread{
private Socket socket;
private String username ;
private String password ;
public S(Socket socket,String username,String password ){
this.socket = socket;
this.username = username;
this.password = password;
}
@Override
public void run() {
try {
// 死循环是为了在密码,用户名出错的情况下,可以接收多次消息
while(true) {
//获取输入流 输出流
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
String name = dis.readUTF();
String pass = dis.readUTF();
System.out.println(name+"====="+pass);
//做出响应
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
// 根据密码,用户名的对错,返回对错
if(username.equals(name) && password.equals(pass)) {
dos.writeBoolean(true);
// 当正确时,跳出循环,结束线程
break;
}else {
dos.writeBoolean(false);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.用多线程开启客户端访问(慎用)
造成客户端同时开启超多线程,崩溃
public class Client1 {
public static void main(String[] args) {
// 直接启动无限多客户端,让多线程服务器端也 开启很多多线程,
// 服务器崩溃,
while (true) {
new Thread(() -> {
try (Socket socket = new Socket("192.168.1.6", 8888);
Scanner sc = new Scanner(System.in)) {
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
while (true) {
System.out.println("请输入用户名:");
String name = sc.next();
System.out.println("请输入用户名:");
String pass = sc.next();
//写出 发送到服务器端
dos.writeUTF(name);
dos.writeUTF(pass);
DataInputStream dis = new DataInputStream(socket.getInputStream());
boolean is = dis.readBoolean();
if (is) {
System.out.println("登录成功!");
break;
} else {
System.out.println("用户名或密码有误!");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}).start();
}
}
}