1.功能:通过socket实现多个人群聊、私聊的功能;效果如图。
2.java代码
服务器端:
/**
* FileName:ChatServer.java
* @author zhanggw
* @date 2018年1月26日 下午10:04:44
*/
package com.kenick.chat;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* 聊天服务器启动程序
* @author zhanggw
* @date 2018年1月26日 下午10:04:44
*/
public class ChatServer {
// 存储所有服务器和客户端的socket连接
public static Map<String,Socket> clientMap = Collections.synchronizedMap(new HashMap<String, Socket>());
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
// 服务器启动,绑定本地端口5555
serverSocket = new ServerSocket(5555);
System.out.println("启动服务器完成!");
// 开始不断接受客户端socket连接
while(true){
Socket clientSocket = serverSocket.accept();
new Thread(new ChatServerProcessThread(clientSocket)).start();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* FileName:ChatServerProcessThread.java
* @author zhanggw
* @date 2018年1月26日 下午10:05:12
*/
package com.kenick.chat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Iterator;
import java.util.Set;
/**
* 聊天服务器多线程处理类
* @author zhanggw
* @date 2018年1月26日 下午10:05:12
*/
public class ChatServerProcessThread implements Runnable{
private Socket clientSocket; // 与客户端的socket连接
private BufferedReader clientBufferedReader; // 封装clientSocket
public ChatServerProcessThread(Socket clientSocket) throws Exception{
this.clientSocket = clientSocket;
this.clientBufferedReader = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
}
@Override
public void run() {
String content = ""; // 接受的内容
try {
while((content=this.clientBufferedReader.readLine())!=null){
try {
String[] clientArray = content.split(":");
String sendId = clientArray[0]; // 发送人id
String receiveId = clientArray[1]; // 接收人id
String sendMsg = clientArray[2]; // 发送内容
if("register".equals(receiveId)){
// 注册并存储建立的socket连接
ChatServer.clientMap.put(sendId, this.clientSocket);
}else if("all".equals(receiveId)){
// 群聊,发送给所有人
Set<String> keySet = ChatServer.clientMap.keySet();
Iterator<String> keyIterator = keySet.iterator();
while(keyIterator.hasNext()){
String clientId= keyIterator.next();
if(!sendId.equals(clientId)){
Socket clientSocket = ChatServer.clientMap.get(clientId);
PrintStream ps = new PrintStream(clientSocket.getOutputStream());
ps.println(sendId+":"+sendMsg);
ps.flush();
}
}
}else{
// 私聊,发送给指定人
Set<String> keySet = ChatServer.clientMap.keySet();
Iterator<String> keyIterator = keySet.iterator();
while(keyIterator.hasNext()){
String clientId= keyIterator.next();
if(clientId.equals(receiveId)){
Socket clientSocket = ChatServer.clientMap.get(clientId);
PrintStream ps = new PrintStream(clientSocket.getOutputStream());
ps.println(sendId+":"+sendMsg);
ps.flush();
}
}
}
} catch (Exception e) {
// 暂时隐去异常处理
//e.printStackTrace();
}
}
} catch (IOException e) {
// 暂时隐去异常处理
// e.printStackTrace();
}
}
}
客户端:
/**
* FileName:ChatClient.java
* @author zhanggw
* @date 2018年1月26日 下午10:18:53
*/
package com.kenick.chat;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
/**
* 聊天客户端启动程序
* @author zhanggw
* @date 2018年1月26日 下午10:18:53
*/
public class ChatClient {
public static void main(String[] args) {
try {
String content = null; // 接收从命令行输入的信息
String clientId = "anonymous"; // 默认账号
Socket serverSocket = new Socket("127.0.0.1",5555);
new Thread(new ChatClientProcessThread(serverSocket)).start();
PrintStream ps = new PrintStream(serverSocket.getOutputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("注册你的账号:");
if((content = br.readLine())!=null){
if(!"".equals(content)){
clientId = content;
System.out.println("账号注册成功!账号ID:"+clientId);
}else{
clientId = clientId+System.currentTimeMillis();
System.out.println("账号未注册成功,使用匿名账号:"+clientId);
}
ps.println(clientId+":register"+":newAccount");
ps.flush();
}
// 开始循环接收输入信息,并发送给服务器
while((content=br.readLine())!=null){
ps.println(clientId+":"+content);
ps.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* FileName:ChatClientProcessThread.java
* @author zhanggw
* @date 2018年1月26日 下午10:19:36
*/
package com.kenick.chat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* 聊天客户端多线程处理类
* @author zhanggw
* @date 2018年1月26日 下午10:19:36
*/
public class ChatClientProcessThread implements Runnable{
private Socket serverSocket; // 与服务器的socket连接
private BufferedReader serverReader; // 对serverSocket的封装
public ChatClientProcessThread(Socket serverSocket) throws Exception{
this.serverSocket = serverSocket;
this.serverReader = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
}
@Override
public void run() {
String content = null;
try {
while((content=this.serverReader.readLine())!=null){
System.out.println(content);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
this.serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}