心得体会
- 一个有趣的小demo,需要对以前的知识有一个很好的掌握,比如,接口的应用,多线程的掌握,常见子线程的方法。
demo简介
要求
-
1.实现每个客户端一个名称
-
2.实现能向某一客户端发起私聊
-
3.实现群聊
思路分析
-
1.客户端只能向服务器端发送字符或者字符
-
2.服务器端只能得到客户端发过来啊的数据
-
3.客户端与服务器端有一个规范,客户端的需求可以在发送的字符里体现
-
4.因为对聊的过程是双向,同时的,所以我们运用多线程处理相关数据
Socket通信模型
![](https://img.haomeiwen.com/i18962381/e3306a0a876a687d.png)
image.png
demo详细步骤
/**
* 定义一套规范
*/
public interface ChatProtocol {
//登陆
String LOGIN_FLAG="u+";
//私聊
String PRIVATE_FLAG="p+";
//群聊
String PUBLIG_FLAG="a+";
//分隔符
String SPLIT_FLAG="♥";
//成功的状态
String SUCCESS="1";
String FAILURE="-1";
}
/**
* 管理所有登陆的用户Map<String,Socket></String,Socket>
*判断某个用户是否已经登录
*/
public class UserManager {
//保存所有用户信息
private Map<String, Socket> users=new HashMap<>();
/**
* 判断用户是否已经登录
*/
public boolean isLogined(String name){
//遍历数组
for(String key:users.keySet()){
if(key.equals(name)){
return true;
}
}
return false;
}
/**
* 保存当前登录的用户信息
*/
public void save(String name,Socket socket){
users.put(name,socket);
}
/**
* 通过用户名找到对应的socket
*/
public Socket socketByName(String name){
return users.get(name);
}
/**
* 通过socket对象找到对应的名称
*/
public String nameBySocket(Socket socket){
for(String key:users.keySet()){
//取出这个key对应的socket
if(socket==users.get(key)){
return key;
}
}
return null;
}
//获取所有人的socket对象
public synchronized Collection<Socket> allUsers(){//加锁
return users.values();
}
}
public class Server {
// 用于保存每一个用户对应的姓名和Socket
public static UserManager manager = new UserManager();
public static void main(String[] args){
// 创建ServerSocket
try(ServerSocket ss = new ServerSocket(6666)) {
// 监听所有来连接的客户端
while (true){
Socket socket = ss.accept();
// 让子线程处理这个Socket
new ServerThread(socket).start();
}
} catch (IOException e) {
}
}
}
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){ this.socket = socket; }
@Override
public void run() {
BufferedReader br = null;
PrintStream ps = null;
try {
// 得到对应的输入流对象
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 得到对应的输出流
ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = br.readLine()) != null){
// 登录u+ ... u+
if (line.startsWith(ChatProtocol.LOGIN_FLAG) && line.endsWith(ChatProtocol.LOGIN_FLAG)){
//u+jacku+
// 获取名字
String name = line.substring(2,line.length()-2);
System.out.println(name);
// 判断这个用户是否已经登录
if (Server.manager.isLogined(name)){
// 登录过了
// 发送结果给客户端
ps.println(ChatProtocol.FAILURE);
}
else {
// 没有登录
// 保存当前登录的用户信息
Server.manager.save(name,socket);
// 发送结果给客户端
ps.println(ChatProtocol.SUCCESS);
}
}
// 判断是不是私聊
else if (line.startsWith(ChatProtocol.PRIVATE_FLAG) && line.endsWith(ChatProtocol.PRIVATE_FLAG)) {
// p+jackhellop+
// 获取信息
String msg = line.substring(2,line.length()-2);
// 分割 jack hello
String[] items = msg.split(ChatProtocol.SPLIT_FLAG);
// 用户名
String name = items[0];
// 聊天内容
String message = items[1];
// 通过用户名找到对应的socket
Socket desSocket = Server.manager.socketByName(name);
PrintStream desPs = new PrintStream(desSocket.getOutputStream());
// 获取当前用户的名称
String currentName = Server.manager.nameBySocket(socket);
// 发送私聊消息
desPs.println(currentName+"向你发来私聊:"+ message);
}else {
// 群聊
// 处理数据
String msg = line.substring(2,line.length()-2);
// 获取当前用户的名称
String currentName = Server.manager.nameBySocket(socket);
// 遍历所有的用户信息
Collection<Socket> sockets = Server.manager.allUsers();
for(Socket s:sockets){
PrintStream tempps = new PrintStream(s.getOutputStream());
tempps.println(currentName+"发来群聊:"+msg);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Client {
public static void main(String[] args){
BufferedReader br=null;
PrintStream ps=null;
BufferedReader brServer=null;
//连接服务器
try(Socket socket=new Socket("192.168.43.121",6666)){
//登录
//接受终端输入流
br=new BufferedReader(new InputStreamReader(System.in));
//发给服务器端的输出流
ps=new PrintStream(socket.getOutputStream());
//接受服务器端的输入流
brServer=new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true) {
//接受终端输入信息
String line = JOptionPane.showInputDialog("请输入用户名");
// BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
// String line=br.readLine();
//拼接登录格式
String loginStr = ChatProtocol.LOGIN_FLAG + line + ChatProtocol.LOGIN_FLAG;
//发送给服务器端
ps.println(loginStr);
//接收服务器端返回的数据
String result = brServer.readLine();
if (result.equals(ChatProtocol.SUCCESS)) {
System.out.println("登录成功");
break;
} else {
System.out.println("用户名已存在,请重新登录");
}
}
//登录成功
//开启线程处理服务器端的输入
new ClientThread(socket).start();//子线程接受服务器端输入
String line=null;
while((line=br.readLine())!=null){//主线程接收终端输入传到服务器
//发送给服务器
System.out.println(line);
ps.println(line);
}
}catch(IOException e){
}
}
}
class Client2 {
public static void main(String[] args){
BufferedReader br = null;
PrintStream ps = null;
BufferedReader brServer = null;
// 连接服务器
try ( Socket socket = new Socket("192.168.43.121",6666)){
// 登录
// 接收终端输入流
br = new BufferedReader(new InputStreamReader(System.in));
// 发给服务器端的输入流
ps = new PrintStream(socket.getOutputStream());
// 接收服务器端的输入流
brServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true){
// 接收终端输入信息
String line = JOptionPane.showInputDialog("请输入姓名");
// 拼接登录格式
String loginStr = ChatProtocol.LOGIN_FLAG+line+ChatProtocol.LOGIN_FLAG;
// 发送给服务器端
ps.println(loginStr);
// 接收服务器端返回的结果
String result = brServer.readLine();
// 判断登录结果
if (result.equals(ChatProtocol.SUCCESS)){
System.out.println("登录成功");
break;
}else {
System.out.println("用户名已存在 请重新登录");
}
}
// 登陆成功
// 开启线程处理服务器端的输入
new ClientThread(socket).start();
// 接收终端输入 发送给服务器端
String line;
while ((line = br.readLine()) != null){
// 发送给服务器
ps.println(line);
}
} catch (IOException e) {
}
}
}
class Client1{
public static void main(String[] args){
BufferedReader br = null;
PrintStream ps = null;
BufferedReader brServer = null;
// 连接服务器
try ( Socket socket = new Socket("127.0.0.1",6666)){
// 登录
// 接收终端输入流
br = new BufferedReader(new InputStreamReader(System.in));
// 发给服务器端的输入流
ps = new PrintStream(socket.getOutputStream());
// 接收服务器端的输入流
brServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true){
// 接收终端输入信息
String line = JOptionPane.showInputDialog("请输入姓名");
// 拼接登录格式
String loginStr = ChatProtocol.LOGIN_FLAG+line+ChatProtocol.LOGIN_FLAG;
// 发送给服务器端
ps.println(loginStr);
// 接收服务器端返回的结果
String result = brServer.readLine();
// 判断登录结果
if (result.equals(ChatProtocol.SUCCESS)){
System.out.println("登录成功");
break;
}else {
System.out.println("用户名已存在 请重新登录");
}
}
// 登陆成功
// 开启线程处理服务器端的输入
new ClientThread(socket).start();
// 接收终端输入 发送给服务器端
String line;
while ((line = br.readLine()) != null){
// 发送给服务器
ps.println(line);
}
} catch (IOException e) {
}
}
}
class ClientThread extends Thread{
private Socket socket;
public ClientThread(Socket socket){
this.socket=socket ;
}
@Override
public void run() {
BufferedReader br=null;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=null;
while((line=br.readLine())!=null){
System.out.println(line);
}
}catch(IOException e){
System.out.println("网络出错");
}finally{
try {
if(br!=null) {
br.close();
}
if(socket!=null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
网友评论