下面是全部的代码
package com.sram.chat;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class CrazyitMap<K,V> {
Map<K,V> maps = Collections.synchronizedMap(new HashMap<K,V>());
//创建一个删除指定项 如果value值相同就删除
public synchronized void removeByValue(V value){
for(K key:maps.keySet()){
if(maps.get(key)==value){
maps.remove(key);
break;
}
}
}
public synchronized Set<V> valueSet(){
Set<V> result = new HashSet<V>();
for(K key:maps.keySet()){
result.add(maps.get(key));
}
return result;
}
//根据value查找key
public synchronized K getKeyByValue(V value){
for(K key:maps.keySet()){
if(maps.get(key)==value||maps.get(key).equals(value)){
return key;
}
}
return null;
}
//添加vlaue 但是不能重复
public synchronized V put(K key,V value){
for(V val:valueSet()){
if(val.equals(value)&&val.hashCode()==value.hashCode()){
throw new RuntimeException("Map集合中不能重复存储value");
}
}
return maps.put(key, value);
}
}
package com.sram.chat;
public interface Protocol {
//定义协议字符长度
int PROTOCOL_LEN = 2;
//下面是协议字符不同表示
String MEG_ROUND ="∞∞"; //发送群聊聊天信息
String USER_ROUND="ぁぁ"; //用户名
String LOGIN_SUCCESS="1"; //登录成功
String NAME_REP ="-1"; //重复用户名,登录失败
String PRIVATE_ROUND ="◎◎"; //私聊
String SPLIT_SIGN="π";
}
package com.sram.chat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JOptionPane;
public class Client {
private static final int SERVER_PORT = 6868;
private Socket socket;
private PrintStream ps;
private BufferedReader brServer;//
private BufferedReader keyIn;//
public void init(){
try{
socket = new Socket("127.0.0.1",SERVER_PORT);
keyIn = new BufferedReader(new InputStreamReader(System.in));
ps = new PrintStream(socket.getOutputStream());
brServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String tip = "";
while(true){
String userName = JOptionPane.showInputDialog(tip+"输入用户名");
ps.println(Protocol.USER_ROUND+userName+Protocol.USER_ROUND);
String result = brServer.readLine();
if(result.equals(Protocol.NAME_REP)){
tip = "用户名重复,请重新";
continue;
}else if(result.equals(Protocol.LOGIN_SUCCESS)){
break;
}
}
}catch(UnknownHostException e){
System.out.println("链接不到远程服务器,请确定服务器已经启动");
closeAll();
System.exit(1);
}catch(IOException e1){
System.out.println("网络异常!请重新登录");
closeAll();
System.exit(1);
}
new ClientThread(brServer).start();
}
public void readAndSend(){
try {
String line = null;
while((line = keyIn.readLine())!=null){
if(line.indexOf(":")>0&&line.startsWith("@@")){
line = line.substring(2);//
ps.println(Protocol.PRIVATE_ROUND
+line.split(":")[0]
+Protocol.SPLIT_SIGN
+line.split(":")[1]
+Protocol.PRIVATE_ROUND);
}else{
ps.println(Protocol.MEG_ROUND+line+Protocol.MEG_ROUND);
}
}
} catch (IOException e) {e.printStackTrace();}
}
public static void main(String[] args) {
Client client = new Client();
client.init();
client.readAndSend();
}
public void closeAll(){
try{
if(keyIn!=null){ //判断流是否创建
keyIn.close();
}
if(brServer!=null){
brServer.close();
}
if(ps!=null){
ps.close();
}
if(socket!=null){
socket.close();
}
} catch (IOException e){
e.printStackTrace();
}
}
}
package com.sram.chat;
import java.io.BufferedReader;
import java.io.IOException;
public class ClientThread extends Thread{
BufferedReader br = null;//处理
public ClientThread(BufferedReader br){
this.br= br;
}
@Override
public void run() {
String line = null;
try {
while((line = br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {e.printStackTrace();}
finally{
try{
if(br!=null){
br.close();
}
}catch(IOException e){e.printStackTrace();}
}
}
}
package com.sram.chat;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private static final int SERVER_PORT = 6868;
public static CrazyitMap<String,PrintStream> clients = new CrazyitMap<>();
public void init(){
try{
ServerSocket ss = new ServerSocket(SERVER_PORT);
while(true){
Socket s = ss.accept();
//启动子线程,读取
new ServerThread(s).start();;
}
}catch(IOException ex){
System.out.println("服务器启动失败,是否"+SERVER_PORT+"已被占用?");
}
}
public static void main(String args[]){
Server server = new Server();
server.init();
}
}
package com.sram.chat;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
public class ServerThread extends Thread{
private Socket socket;
BufferedReader br = null;
PrintStream ps = null;
ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try{
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
ps = new PrintStream(socket.getOutputStream());
String line = null;
while((line = br.readLine())!=null){
//ぁぁstevejobsぁぁ
//如果读到的line字符是以 Protocol.USER_ROUND开始,并且以Protocol.USER_ROUND结束,则可以确定
//读到的是用户登录的用户名
//System.out.println(line);
//System.out.println(getRealMsg(line));
if(line.startsWith(Protocol.USER_ROUND)&&line.endsWith(Protocol.USER_ROUND)){
String userName = getRealMsg(line);
if(Server.clients.maps.containsKey(userName)){
System.out.println("服务器提示:用户名重复");//服务器端到客户端
ps.println(Protocol.NAME_REP);
}else{
System.out.println("服务器提示:成功");
ps.println(Protocol.LOGIN_SUCCESS);
Server.clients.put(userName,ps);
}
}else if(line.startsWith(Protocol.PRIVATE_ROUND)&&line.endsWith(Protocol.PRIVATE_ROUND)){
String message = getRealMsg(line);
String toUser = message.split(Protocol.SPLIT_SIGN)[0];
String msg = message.split(Protocol.SPLIT_SIGN)[1];
Server.clients.maps.get(toUser).println(Server.clients.getKeyByValue(ps)+"悄悄对你说:"+msg);
}else if(line.startsWith(Protocol.MEG_ROUND)&&line.startsWith(Protocol.MEG_ROUND)){
String message = getRealMsg(line);
for(PrintStream out:Server.clients.valueSet()){
out.println(Server.clients.getKeyByValue(ps)+"说:"+message);
}
}
}
}catch(IOException e){
Server.clients.removeByValue(ps);
System.out.println("集合Map"+Server.clients.maps.size());
try {
if(br!=null){
br.close();
}
if(ps!=null){
ps.close();
}
if(socket!=null){
socket.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
private String getRealMsg(String line){
return line.substring(Protocol.PROTOCOL_LEN,line.length()-Protocol.PROTOCOL_LEN);
}
}