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();
}
}
运行测试:

现在实现了一个用户登录操作,接下来模拟多用户登录。
对于服务端来说一个连接就是一个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 模拟多用户登录的更多相关文章
- Java 网络编程 -- 基于TCP实现文件上传
Java TCP 操作基本流程 一.创建服务器 1.指定端口, 使用serverSocket创建服务器 2.阻塞式连接 accept 3.操作:输入流 输出流 4.释放资源 二.创建客户端 1.使用S ...
- Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊
分析: 聊天室需要多个客户端和一个服务端. 服务端负责转发消息. 客户端可以发送消息.接收消息. 消息分类: 群聊消息:发送除自己外所有人 私聊消息:只发送@的人 系统消息:根据情况分只发送个人和其他 ...
- JAVA基础知识之网络编程——-基于TCP通信的简单聊天室
下面将基于TCP协议用JAVA写一个非常简单的聊天室程序, 聊天室具有以下功能, 在服务器端,可以接受客户端注册(用户名),可以显示注册成功的账户 在客户端,可以注册一个账号,并用这个账号发送信息 发 ...
- java网络编程基础——TCP网络编程一
基于TCP协议的网络编程 TCP/IP协议是一种可靠的网络协议,它的通信的两端各自建立一个Socket,从而在通信的两端之间形成网络虚拟链路. Java使用Socket对象来代表两端的通信端口,并通过 ...
- 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程
Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...
- java 网络编程 UDP TCP
网络编程 网络编程主要用于解决计算机与计算机(手机.平板..)之间的数据传输问题. 网络编程: 不需要基于html页面就可以达到数据之间的传输. 比如: feiQ , QQ , 微信....网页编程: ...
- (网络编程)基于tcp(粘包问题) udp协议的套接字通信
import socket 1.通信套接字(1人1句)服务端和1个客户端 2.通信循环(1人多句)服务端和1个客户端 3.通信循环(多人(串行)多句)多个客户端(服务端服务死:1个客户端---&g ...
- java网络编程基础——TCP网络编程三
AIO实现非阻塞通信 java7 NIO2 提供了异步Channel支持,这种异步Channel可以提供更高效的IO,这种基于异步Channel的IO被称为异步IO(Asynchronous IO) ...
- java 网络编程基础 TCP/IP协议:服务端ServerSocket;客户端Socket; 采用多线程方式处理网络请求
1.Java中客户端和服务器端通信的简单实例 Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一 ...
随机推荐
- Unable to locate JAR/zip in file system as specified by the driver definitio
把之前的驱动包删掉,然后把你的驱动包导入就行了 现在OK键就算正常了
- nginx 报 502 bad gateway 分析解决
出现nginx 502 bad gateway 问题,先从nginx端日志入手,分析排查原因. 1.排查问题 首先需要打开nginx错误日志. 编辑nginx.conf,默认路径在/usr/local ...
- 使用docsify 写开源文档
使用docsify 写开源文档 官网:https://docsify.js.org/#/ docsify 是一个动态生成文档网站的工具.不同于 GitBook.Hexo 的地方是它不会生成将 .md ...
- POI2014 FAR-FarmCraft 树形DP+贪心
题目链接 https://www.luogu.org/problem/P3574 题意 翻译其实已经很明确了 分析 这题一眼就是贪心啊,但贪心的方法要思索一下,首先是考虑先走时间多的子树,但不太现实, ...
- ssh-add和ssh-agent
注: 因为在ssh-agent异常关闭或者新开窗口是会导致ssh-add找不到私钥,导致添加的私钥无效,所以下面使用keychain管理 ssh-add 参数 -l 查看代理中的私钥 -L 查看代理中 ...
- Johnson-Trotter(JT)算法求全排列
Johnson-Trotter算法描述 算法 JohnsonTrotter(n) //实现用来生成排序的 Johnson-Trotter 算法 //输入:正整数n(代表序列1,2,···,n) //输 ...
- B 外地比赛
时间限制 : - MS 空间限制 : - KB 评测说明 : 1s,256m 问题描述 何老板带着信竞队的k个同学出去外地打比赛.到达目的地后,何老板就找了一家酒店,准备住下.酒店工作人员告诉何 ...
- 【tensorflow2.0】自动微分机制
神经网络通常依赖反向传播求梯度来更新网络参数,求梯度过程通常是一件非常复杂而容易出错的事情. 而深度学习框架可以帮助我们自动地完成这种求梯度运算. Tensorflow一般使用梯度磁带tf.Gradi ...
- pycharm文件名颜色代表的含义
在使用pycharm过程中,文件名有不一样的颜色. 绿色:已经加入版本控制暂未提交 红色:未加入版本控制 蓝色:加入版本控制,已提交,有改动 白色:加入版本控制,已提交,无改动 灰色:版本控制已忽略文 ...
- Byte字节
字节(Byte )是计算机信息技术用于计量存储容量的一种计量单位,作为一个单位来处理的一个二进制数字串,是构成信息的一个小单位.最常用的字节是八位的字节,即它包含八位的二进制数. 中文名 字节 外文名 ...