服务器端多线程与多并发客户端访问UDP(笔记)

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();
		}
	}
}
发布了22 篇原创文章 · 获赞 2 · 访问量 775

猜你喜欢

转载自blog.csdn.net/qq_43542795/article/details/103448485