服务器端
MultiThreadServer.java
/**
* 服务器
*/
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MultiThreadServer {
private static Map<String,Socket> clientsMap = new ConcurrentHashMap<String, Socket>();
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(6666);
ExecutorService service = Executors.newFixedThreadPool(20);
for (int i = 0; i < 20; i++){
System.out.println("等待客户端连接");
Socket client = serverSocket.accept();
System.out.println("有新的客户端连接,端口号为:"+client.getPort());
service.submit(new ExecuteClientRequest(client));
}
}
//服务器处理客户端请求的线程
static class ExecuteClientRequest implements Runnable{
private Socket client;
public ExecuteClientRequest(Socket client) {
this.client = client;
}
public void run() {
//获取输入楼,不断的读取用户发来的信息
Scanner readFromClient = null;
try {
readFromClient = new Scanner(client.getInputStream());
readFromClient.useDelimiter("\n");
while (true){
if (readFromClient.hasNextLine()){
String str = readFromClient.nextLine();
//进行\r的过滤,替换成空字符
//Win下的字符过滤
Pattern pattern = Pattern.compile("\r");
Matcher matcher = pattern.matcher(str);
str = matcher.replaceAll("");
if (str.startsWith("userName")){
//用户注册流程
//userName:zhangsan
String userName = str.split(":")[1];
userRegister(userName,client);
continue;
}else if (str.startsWith("G")){
//群聊流程
//G:hello
String msg = str.split(":")[1];
groupChat(msg);
continue;
}else if (str.startsWith("P")){
//私聊流程
//P:zhangsan-hello
String tempMsg = str.split(":")[1];
String userName = tempMsg.split("-")[0];
String privateMsg = tempMsg.split("-")[1];
privateChat(userName,privateMsg);
continue;
}else if (str.contains("byebye")){
//用户退出
//zhangsan:byebye
String userName = str.split(":")[0];
userExist(userName);
continue;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 用户注册方法
* @param userName 用户名
* @param client 对于的Socket
*/
private void userRegister(String userName, Socket client){
//将用户信息保存到服务器当中
clientsMap.put(userName,client);
//取得当前注册到服务器的所有人个数
int size = clientsMap.size();
System.out.println("当前聊天室内共有"+size+"人");
//System.out.println(userName+"上线了");
String userOnline = userName+"上线了";
groupChat(userOnline);
}
/**
* 群聊流程
* @param msg 用于要发送的群聊信息
*/
private void groupChat(String msg){
//取出所有连接的客户端,依次拿到输出流进行遍历输出
Collection<Socket> clients = clientsMap.values();
for (Socket client:clients){
//取出客户端的输出流
try {
PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
out.println("群聊信息为:"+msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 私聊流程
* @param userName 私聊对象
* @param msg 私聊要发送的信息
*/
private void privateChat(String userName, String msg){
Socket client = clientsMap.get(userName);
try {
PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
//out.println(userName+"私聊信息为:"+msg);
out.println("私聊信息:"+msg);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 用户退出
* @param userName 退出的用户名
*/
private void userExist(String userName){
clientsMap.remove(userName);
System.out.println("当前聊天室的人数为:"+clientsMap.size());
String groupChatMsg = userName+"已下线";
groupChat(groupChatMsg);
}
}
}
客户端
MutiThreadClient.java
/**
* 多线程版本客户端,读、写操作分离
*/
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
/**
* 读取服务器发来信息的线程
*/
class ReadFromServer implements Runnable{
private Socket client;
//通过构造方法传入通信的Socket
public ReadFromServer(Socket client) {
this.client = client;
}
public void run() {
//获取输入流,读取服务器发来的信息
Scanner readFromServer = null;
try {
readFromServer = new Scanner(client.getInputStream());
readFromServer.useDelimiter("\n");
//不断读取服务器信息
while (true){
if(readFromServer.hasNextLine()){
String str = readFromServer.nextLine();
System.out.println("服务器发来的消息为:"+str);
}
if (client.isClosed()){
System.out.println("客户端已经关闭");
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
readFromServer.close();
}
}
}
/**
* 写线程——向服务器发送信息线程
*/
class SendMsgToServer implements Runnable{
private Socket client;
public SendMsgToServer(Socket client) {
this.client = client;
}
public void run() {
//获取键盘输入,像服务器发送消息
Scanner in = new Scanner(System.in);
in.useDelimiter("\n");
PrintStream sendMsgToServer = null;
try {
sendMsgToServer = new PrintStream(client.getOutputStream(),true,"UTF-8");
while (true){
System.out.println("请输入要发送的消息...");
if (in.hasNextLine()){
String strToServer = in.nextLine();
sendMsgToServer.println(strToServer);
if (strToServer.contains("byebye")){
System.out.println("关闭客户端");
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
sendMsgToServer.close();
in.close();
}
}
}
public class MutiThreadClient {
public static void main(String[] args) throws IOException {
//建立与服务器的连接
Socket client = new Socket("127.0.0.1",6666);
//创建读写线程与服务器通信
Thread readThread = new Thread(new ReadFromServer(client));
Thread sendThread = new Thread(new SendMsgToServer(client));
readThread.start();
sendThread.start();
}
}