温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java中如何实现Socket多客户端Client-Server聊天程序

发布时间:2021-05-17 13:38:24 来源:亿速云 阅读:559 作者:小新 栏目:编程语言

这篇文章主要介绍Java中如何实现Socket多客户端Client-Server聊天程序,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

任务要求

编写一个简单的Socket多客户端聊天程序:

  • 客户端程序,从控制台输入字符串,发送到服务器端,并将服务器返回的信息显示出来

  • 服务器端程序,从客户机接收数据并打印,同时将从标准输入获取的信息发送给客户机

  • 满足一个服务器可以服务多个客户

低配版本链接

实现代码

工具类

import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; public class SocketUtils {	public static void writeToSocket(Socket socket, String message) throws IOException {	writeToOutputStream(socket.getOutputStream(), message);	}	public static void writeToDataOutputStream(DataOutputStream dos, String message) throws IOException {	dos.writeUTF(message);	dos.flush();	}	public static void writeToOutputStream(OutputStream os, String message) throws IOException {	writeToDataOutputStream(new DataOutputStream(os), message);	} }

服务器端线程

import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; public class ChatServerRunnable implements Runnable {	private Socket socket;	private DataOutputStream dos;	private DataInputStream dis;	private String currentUserNickName;	public ChatServerRunnable(Socket socket) throws IOException {	this.socket = socket;	this.dos = new DataOutputStream(socket.getOutputStream());	this.dis = new DataInputStream(socket.getInputStream());	}	@Override	public void run() {	try {	write("欢迎来到聊天室!");	login();	System.out.println(currentUserNickName + "用户登录成功");	write(currentUserNickName + ", 您已登录。\n输入【list users】可以查看当前登录用户列表\n输入【to all 消息内容】可以群发消息\n输入【to 某个用户 消息内容】可以给指定用户发送消息\n输入【exit】可以退出聊天");	String input = dis.readUTF();	while (!ChatServer.EXIT.equals(input)) {	System.out.println(currentUserNickName + "输入了" + input);	if (input.startsWith("to ")) {	sendMessage(input);	} else if ("list users".equals(input)) {	showOnlineUsers();	} else {	write("您输入的命令不合法,请重新输入!");	}	input = dis.readUTF();	}	} catch (IOException e) {	e.printStackTrace();	} finally {	ChatServer.nickNameSocketMap.remove(currentUserNickName);	try {	dis.close();	} catch (IOException e) {	e.printStackTrace();	}	try {	dos.close();	} catch (IOException e) {	e.printStackTrace();	}	try {	socket.close();	} catch (IOException e) {	e.printStackTrace();	}	}	}	private void login() throws IOException {	write("请输入你的昵称:");	while (true) {	String nickName = dis.readUTF();	System.out.println("用户输入了昵称:" + nickName);	synchronized (ChatServerRunnable.class) {	if (!ChatServer.nickNameSocketMap.containsKey(nickName)) {	currentUserNickName = nickName;	ChatServer.nickNameSocketMap.put(nickName, socket);	break;	} else {	write("您输入的昵称已存在,请重新输入:");	}	}	}	}	private void sendMessage(String input) throws IOException {	int receiverEndIndex = input.indexOf(" ", 3);	String receiver = input.substring(3, receiverEndIndex);	String message = input.substring(receiverEndIndex + 1);	if ("all".equals(receiver)) {	broadcast(message);	} else {	sendIndividualMessage(receiver, message);	}	}	private void sendIndividualMessage(String receiver, String orignalMessage) throws IOException {	Socket receiverSocket = ChatServer.nickNameSocketMap.get(receiver);	if (receiverSocket != null) {	SocketUtils.writeToSocket(receiverSocket, formatMessage("你", orignalMessage));	} else {	write("您要单独聊天的用户【" + receiver + "】不存在或者已经下线");	}	}	private String formatMessage(String receiver, String originalMessage) {	StringBuilder messageBuilder = new StringBuilder();	messageBuilder.append(currentUserNickName).append(" 对 ").append(receiver).append(" 说:\n")	.append(originalMessage).append("\n发送时间:")	.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));	return messageBuilder.toString();	}	private void broadcast(String orignalMessage) throws IOException {	for (Map.Entry<String, Socket> entry : ChatServer.nickNameSocketMap.entrySet()) {	if (!currentUserNickName.equals(entry.getKey())) {	SocketUtils.writeToSocket(entry.getValue(), formatMessage("所有人", orignalMessage));	}	}	}	private void showOnlineUsers() throws IOException {	StringBuilder users = new StringBuilder();	users.append("当前在线的用户有:\n");	for (String nickName : ChatServer.nickNameSocketMap.keySet()) {	users.append("【").append(nickName).append("】\n");	}	write(users.toString());	}	private void write(String message) throws IOException {	SocketUtils.writeToDataOutputStream(dos, message);	} }

客户端线程

import java.io.DataInputStream; import java.io.IOException; public class ClientMessageReceiver implements Runnable {	private DataInputStream dis;	private boolean timeToStop = false;	public ClientMessageReceiver(DataInputStream dis) {	this.dis = dis;	}	@Override	public void run() {	while (!timeToStop) {	try {	System.out.println(dis.readUTF());	} catch (IOException e) {	if ("Connection reset".equals(e.getMessage())) {	System.out.println("与服务器的连接已中断!");	break;	}	if (!timeToStop) {	e.printStackTrace();	}	}	}	}	public void stop() {	timeToStop = true;	} }

服务器端程序

import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.Map; public class ChatServer {	public static final String EXIT = "exit";	public static final int PORT = 8888;	static Map<String, Socket> nickNameSocketMap = new HashMap<>();	public static void main(String[] args) {	try (ServerSocket ss = new ServerSocket(PORT)) {	System.out.println("聊天室服务器端已启动,正在监听" + PORT + "端口");	while (true) {	try {	Socket socket = ss.accept();	System.out.println("有新用户连接到服务器端,信息为:" + socket);	new Thread(new ChatServerRunnable(socket)).start();	} catch (Exception e) {	e.printStackTrace();	}	}	} catch (IOException e) {	e.printStackTrace();	}	} }

客户端程序

import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.util.Scanner; public class ChatClient {	private static Scanner scanner = new Scanner(System.in);	public static void main(String[] args) {	try (Socket socket = new Socket("127.0.0.1", 8888);	DataInputStream dis = new DataInputStream(socket.getInputStream());	DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {	ClientMessageReceiver messageReceiver = new ClientMessageReceiver(dis);	new Thread(messageReceiver).start();	String input = null;	do {	input = scanner.nextLine();	write(dos, input);	} while (!ChatServer.EXIT.equals(input));	messageReceiver.stop();	} catch (IOException e) {	e.printStackTrace();	}	}	private static void write(DataOutputStream dos, String message) throws IOException {	dos.writeUTF(message);	dos.flush();	} }

运行说明

启动服务器:

Java中如何实现Socket多客户端Client-Server聊天程序

启动第一个客户端,输入客户昵称:

Java中如何实现Socket多客户端Client-Server聊天程序

服务器监听到了这个事件:

Java中如何实现Socket多客户端Client-Server聊天程序

获取所有用户列表,发送给所有用户“hhh”的信息:

Java中如何实现Socket多客户端Client-Server聊天程序

服务器端接收到了这个事件:

Java中如何实现Socket多客户端Client-Server聊天程序

新的客户端登录,注册用户昵称:

Java中如何实现Socket多客户端Client-Server聊天程序

服务器接收到这个事件:

Java中如何实现Socket多客户端Client-Server聊天程序

用户1向用户2发送私聊消息:

Java中如何实现Socket多客户端Client-Server聊天程序

用户2收到用户1的消息:

Java中如何实现Socket多客户端Client-Server聊天程序

客户2向所有用户发送消息:

Java中如何实现Socket多客户端Client-Server聊天程序

客户1收到客户2的群发消息:

Java中如何实现Socket多客户端Client-Server聊天程序

服务器监听到了这些事件:

Java中如何实现Socket多客户端Client-Server聊天程序

客户2退出:

Java中如何实现Socket多客户端Client-Server聊天程序

客户1显示的在线列表只有1人了:

Java中如何实现Socket多客户端Client-Server聊天程序

客户1也退出:

Java中如何实现Socket多客户端Client-Server聊天程序

客户端用户退出的时候,该线程终止。

没客户端用户,服务器也正常跑自己的事。

Java的特点有哪些

Java的特点有哪些 1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。 2.Java具有简单性、面向对象、分布式、安全性、平台独立与可移植性、动态性等特点。 3.使用Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等。

以上是“Java中如何实现Socket多客户端Client-Server聊天程序”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI