Java 网络编程 -- 基于TCP 模拟多用户登录

Java TCP的基本操作参考前一篇:Java 网络编程 – 基于TCP实现文件上传

实现多用户操作之前先实现以下单用户操作,假设目前有一个用户:

账号:zs

密码:123

服务端:

public class LoginServer {
public static void main(String[] args) throws IOException {
System.out.println("=========server========");
// 1、使用serverSocket 创建服务端
ServerSocket server = new ServerSocket(8888);
// 2、阻塞式连接
Socket socket = server .accept();
// 3、操作
DataInputStream dis = new DataInputStream(socket.getInputStream());
String datas = dis.readUTF();
// 解析用户信息
String[] dataArray = datas.split("&");
String uname = null;
String pwd = null;
for (String info : dataArray) {
String[] userInfo = info.split("=");
if("uname".equals(userInfo[0])) {
uname = userInfo[1];
System.out.println("用户名:" + uname);
}else if("pwd".equals(userInfo[0])) {
pwd = userInfo[1];
System.out.println("密码:" + pwd);
}
}
// 输出 模拟和数据库比较信息
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
if(uname.equals("zs") && pwd.equals("123")) {
dos.writeUTF("登录成功,欢迎回来");
}else {
dos.writeUTF("用户名或密码错误");
}
// 4、释放资源
dos.close();
dis.close();
socket.close();
server.close();
}
}

客户端:

public class LoginClient {
public static void main(String[] args) throws IOException, IOException {
System.out.println("=========client========");
// 1、使用Socket 创建客户端
Socket client = new Socket("localhost", 8888);
// 2、操作
// 输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("请输入用户名:");
String uname = br.readLine();
System.out.print("请输入用密码:");
String pwd = br.readLine();
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
dos.writeUTF("uname=" + uname +"&pwd=" + pwd);
dos.flush();
// 接收服务端响应
DataInputStream dis = new DataInputStream(client.getInputStream());
String response = dis.readUTF();
System.out.println(response);
// 3、释放资源
dis.close();
dos.close();
br.close();
client.close();
}
}

运行测试:

Java 网络编程 -- 基于TCP 模拟多用户登录

现在实现了一个用户登录操作,接下来模拟多用户登录。

对于服务端来说一个连接就是一个socket,要满足多用户登录的需求,如果直接在现有代码上加上while循环,需要一个用户操作完,下一个用户接着操作,这样很不合理,明显的我们要加入多线程,并且现在所有代码都写在main 方法里面,不好维护。

如果使用lambda表达式,代码比较多,看起来比较累。

我们还是用静态内部类封装一下每一个类

封装服务端:

public class LoginMultiServer {
public static void main(String[] args) throws IOException {
System.out.println("=========server========");
// 1、使用serverSocket 创建服务端
ServerSocket server = new ServerSocket(8888);
boolean isRuning = true;
while (isRuning) {
// 2、阻塞式连接
Socket socket = server.accept();
System.out.println("一个客户端建立了连接");
// 3、操作
new Thread(new Channel(socket)).start();
}
server.close();
} // 一个Channel 代表一个客户端
static class Channel implements Runnable{
private Socket socket;
private DataInputStream dis;
private DataOutputStream dos; public Channel(Socket socket) {
this.socket = socket;
try {
// 输入
dis = new DataInputStream(socket.getInputStream());
// 输出
dos = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
release(); // 一个出错就不用玩了
} } // 接收数据
public String receive() {
String datas = "";
try {
datas = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
return datas;
} // 发送数据
public void send(String msg) {
try {
dos.writeUTF(msg);
} catch (IOException e) {
e.printStackTrace();
}
} // 释放资源
public void release() {
try {
if(null != dos)
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null != dis)
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null != dos)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() { // 3、操作
String datas = receive();
// 解析用户信息
String[] dataArray = datas.split("&");
String uname = null;
String pwd = null;
for (String info : dataArray) {
String[] userInfo = info.split("=");
if ("uname".equals(userInfo[0])) {
uname = userInfo[1];
System.out.println("用户名:" + uname);
} else if ("pwd".equals(userInfo[0])) {
pwd = userInfo[1];
System.out.println("密码:" + pwd);
}
}
// 输出 模拟和数据库比较信息
if (uname.equals("zs") && pwd.equals("123")) {
send("登录成功,欢迎回来");
} else {
send("用户名或密码错误");
}
// 4、释放资源
release();
} }
}

封装客户端:

public class LoginMultiClient {
public static void main(String[] args) throws IOException, IOException {
System.out.println("=========client========");
// 1、使用Socket 创建客户端
Socket client = new Socket("localhost", 8888);
// 2、操作
// 输入
new Send(client).send();
// 接收服务端响应
new Receive(client).receice();
// 3、释放资源
client.close();
} // 发送
static class Send{
private Socket client;
private BufferedReader br;
private DataOutputStream dos;
private String msg;
public Send(Socket client) {
try {
this.client = client;
br = new BufferedReader(new InputStreamReader(System.in));
this.msg = init();
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
} private String init() {
try {
System.out.print("请输入用户名:");
String uname = br.readLine();
System.out.print("请输入用密码:");
String pwd = br.readLine();
return "uname=" + uname +"&pwd=" + pwd;
} catch (IOException e) {
e.printStackTrace();
}
return "";
} public void send() {
try {
dos.writeUTF(this.msg);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
} // 接收
static class Receive{
private Socket client;
private DataInputStream dis;
public Receive(Socket client) {
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public void receice() {
String response;
try {
response = dis.readUTF();
System.out.println(response);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

封装之后,main 方法里可以比较简洁的书写逻辑代码了。

运行测试:

Java 网络编程 -- 基于TCP 模拟多用户登录

上一篇:Web.py 框架学习笔记 - ctx


下一篇:java网络编程(5)——Tcp