1.項目簡介:
基於Socket編程的網絡聊天室
2.功能描述:
可以實施多個用戶的註冊,羣發和私聊:
3.具體實現流程:
客戶端實現流程:
1.客戶端的功能可以進一步細化爲:
對外發送信息:
接受其他客戶端的信息:
由於發送和接受的功能應該是獨立的,所以使用兩個線程來分別實現:
1.發送線程:
內部主要實現原理是通過獲取sokcet輸出流,通過輸出流發送信息
2.如果有Bye字樣則關閉Socket退出聊天
public class Write implements Runnable{
private Socket socket;
public Write(Socket socket) {
this.socket = socket;
}
public void run() {
try {
//獲取輸出流
PrintStream out=new PrintStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in);
String msg=null;
while(true) {
if(scanner.hasNext()) {
msg = scanner.next();
}
out.println(msg);
if(msg.contains("Bye")){
socket.close();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
接受其他客戶端的信息:
流程:
獲取輸入流來讀取從服務器發送的信息:
class Read implements Runnable{
private Socket socket;
public Read(Socket socket) {
this.socket = socket;
}
public void run() {
Scanner scanner= null;
try {
scanner = new Scanner(socket.getInputStream());
while(true){
System.out.println("等待客戶端發來的消息");
String str=null;
if(scanner.hasNext()){
System.out.println(scanner.next());
}
if(socket.isClosed()){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
服務器實現流程:
一箇中轉站的功能:將發送來的信息進行分類,來達到註冊、羣發、私聊的功能
public class Services {
private static Map<String,Socket> map=new ConcurrentHashMap<String, Socket>();
static private class RealServices implements Runnable{
private Socket socket;
public RealServices(Socket socket) {
this.socket = socket;
}
public void run() {
try {
Scanner in=new Scanner(socket.getInputStream());
String msg=null;
while(true){
if(in.hasNext()) {
msg = in.next();
}
Pattern pattern = Pattern.compile("\r");
java.util.regex.Matcher matcher = pattern.matcher(msg);
//如果以userName開頭則是註冊,即將所有用戶信息存放在map中
if(msg.startsWith("userName")){
String username=msg.split(":")[1];
register(username);
continue;
}
//G開頭說明是羣聊
if(msg.startsWith("G")){
String send=msg.split(":")[1];
group(send);
}
//收到數據已P開頭說明是私聊
if (msg.startsWith("P")){
String username=msg.split(":")[1].split("\\-")[0];
String send=msg.split("\\-")[1];
privateSend(username,send);
}
if(msg.contains("Bye")){
Set<Map.Entry<String, Socket>> entries = map.entrySet();
Iterator<Map.Entry<String,Socket>> iterator=entries.iterator();
String username=null;
Socket socket=null;
while(iterator.hasNext()){
Map.Entry<String,Socket> i=iterator.next();
username=i.getKey();
socket=i.getValue();
if(socket==this.socket){
iterator.remove();
}
}
group(username+"退出羣聊,當前聊天室還剩"+map.size());
System.out.println(username+"退出羣聊");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void register(String username) throws IOException {
if(map.containsKey(username)){
System.out.println("當前用戶已存在");
}else {
map.put(username,socket);
group("歡迎"+username+"加入聊天室,當前聊天室人數:"+map.size());
System.out.println("歡迎"+username+"加入聊天室,當前聊天室人數:"+map.size());
}
}
//遍歷map集合將每一個數據發送出去
private void group(String send) throws IOException {
Set<Map.Entry<String, Socket>> entries = map.entrySet();
Iterator<Map.Entry<String,Socket>> iterator=entries.iterator();
while (iterator.hasNext()){
Map.Entry<String,Socket> i=iterator.next();
Socket socket=i.getValue();
if(socket==this.socket){
continue;
}
PrintStream printStream=new PrintStream(socket.getOutputStream());
printStream.println(send);
}
}
//私聊獲取指定用戶的Socket,創建連接發送
private void privateSend(String username, String send) throws IOException {
Socket to=map.get(username);
if(to==null){
PrintStream out=new PrintStream(socket.getOutputStream());
out.println("當前用戶不存在");
}else {
PrintStream out=new PrintStream(to.getOutputStream());
out.println("發送信息: "+send);
}
}
}