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 模拟多用户登录的更多相关文章

  1. Java 网络编程 -- 基于TCP实现文件上传

    Java TCP 操作基本流程 一.创建服务器 1.指定端口, 使用serverSocket创建服务器 2.阻塞式连接 accept 3.操作:输入流 输出流 4.释放资源 二.创建客户端 1.使用S ...

  2. Java 网络编程 -- 基于TCP 实现聊天室 群聊 私聊

    分析: 聊天室需要多个客户端和一个服务端. 服务端负责转发消息. 客户端可以发送消息.接收消息. 消息分类: 群聊消息:发送除自己外所有人 私聊消息:只发送@的人 系统消息:根据情况分只发送个人和其他 ...

  3. JAVA基础知识之网络编程——-基于TCP通信的简单聊天室

    下面将基于TCP协议用JAVA写一个非常简单的聊天室程序, 聊天室具有以下功能, 在服务器端,可以接受客户端注册(用户名),可以显示注册成功的账户 在客户端,可以注册一个账号,并用这个账号发送信息 发 ...

  4. java网络编程基础——TCP网络编程一

    基于TCP协议的网络编程 TCP/IP协议是一种可靠的网络协议,它的通信的两端各自建立一个Socket,从而在通信的两端之间形成网络虚拟链路. Java使用Socket对象来代表两端的通信端口,并通过 ...

  5. 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

    Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...

  6. java 网络编程 UDP TCP

    网络编程 网络编程主要用于解决计算机与计算机(手机.平板..)之间的数据传输问题. 网络编程: 不需要基于html页面就可以达到数据之间的传输. 比如: feiQ , QQ , 微信....网页编程: ...

  7. (网络编程)基于tcp(粘包问题) udp协议的套接字通信

    import   socket 1.通信套接字(1人1句)服务端和1个客户端 2.通信循环(1人多句)服务端和1个客户端 3.通信循环(多人(串行)多句)多个客户端(服务端服务死:1个客户端---&g ...

  8. java网络编程基础——TCP网络编程三

    AIO实现非阻塞通信 java7 NIO2 提供了异步Channel支持,这种异步Channel可以提供更高效的IO,这种基于异步Channel的IO被称为异步IO(Asynchronous IO) ...

  9. java 网络编程基础 TCP/IP协议:服务端ServerSocket;客户端Socket; 采用多线程方式处理网络请求

    1.Java中客户端和服务器端通信的简单实例 Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一 ...

随机推荐

  1. Selenium系列(十五) - Web UI 自动化基础实战(2)

    如果你还想从头学起Selenium,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1680176.html 其次,如果你不懂前端基础知识, ...

  2. Prism 源码解读6-事件聚合

    0 介绍 事件提供的是1对多的绑定,通过委托链实现对订阅者的调用,事件必须要通过发布者调用.同时事件订阅是强引用,事件订阅者的生命周期总是大于等于事件发布者.如果代码中事件很多就会充斥着各种事件的订阅 ...

  3. C#使用反射设置属性值

    最近在Refix一个支持Excel文件导入导出功能时,发现有用到反射的相关技能.故而在网上查了些资料,通过代码调试加深下理解. class Program { static void Main(str ...

  4. 模块 time datetime 时间获取和处理

    模块_time 和时间有关系的我们就要用到时间模块.在使用模块之前,应该首先导入这个模块. 1 延时 time.sleep(secs) (线程)推迟指定的时间运行.单位为秒. 2 获取当前时间戳tim ...

  5. [HDU]1166敌兵布阵<静态线段树>

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 题目大意:给出n个点,每个点有一个值,现在有三种操作, 1.在i点加上j 2.在i点减去j 3. ...

  6. OpenWrite技术自媒体界的JVM一次编辑、随处发布

    原文 :https://mp.weixin.qq.com/s/KUtJ2dwhBRuJ2G_-PkQFEA 最懂你的科技自媒体管理平台 [实用小工具推荐]给科技或技术同学们推荐一款比较好用的工具,可以 ...

  7. 前端经典面试题解密:JS的new关键字都干了什么?

    前言 new关键字在实例化获取对象时都做了什么?是一道经常出现在前端面试时的问题.如果只是简单的了解new关键字是实例化构造函数获取对象,是万万不能够的.更深入的层级发生了什么呢?同时面试官想从这道题 ...

  8. 《Java基础复习》-控制执行流程

    最近任务太多了,肝哭我了,boom 参考书目:Thinking in Java <Java基础复习>-控制执行流程 Java使用了C的所有流程控制语句 涉及关键字:if-else.whil ...

  9. C语言 生日快乐

    #include <stdio.h> #include <math.h> #include <stdlib.h> #define I 20 #define R 34 ...

  10. "二号标题"组件:<h2> —— 快应用组件库H-UI

     <import name="h2" src="../Common/ui/h-ui/text/c_h2"></import> < ...