import java.util.Set;
import java.io.PrintWriter;
import java.util.HashMap;
import java.io.*;
import java.net.*;
import java.util.*;
public class Server {
public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(12000);
// 서버 소켓을 만
HashMap<String, PrintWriter> hm = new HashMap<String, PrintWriter>();
// hash맵<아이디, 출력빨대> 로 만듬
HashMap<String, HashMap<String, PrintWriter>> room = new HashMap<String, HashMap<String, PrintWriter>>();
// 방을 맵으로 만듬, 방해쉬맵<방제, 게스트맵>
while (true) {
System.out.println("접속대기!!");
Socket sock = server.accept();
// 소켓을 열고 대기
System.out.println("@이녀석 도킹 완으리요! --> "
+ sock.getInetAddress());
// 접속된 아이피 보여줌
ChatThread ct = new ChatThread(sock, hm, room);
// 쓰레드에 소켓,게스트맵,룸맵을 파라미터로
ct.start();
}// while
} catch (Exception e) {
System.out.println(e);
}
}// main
}
class ChatThread extends Thread {
private Socket sock;
private HashMap<String, PrintWriter> hm;
private HashMap<String, HashMap<String, PrintWriter>> room;
private BufferedReader br;
private String id;
private PrintWriter pw = null;
private String bang = null;
// ///////-------------------------------------------------------------
public ChatThread(Socket sock, HashMap<String, PrintWriter> hm,
HashMap<String, HashMap<String, PrintWriter>> room) {
// 생성자에 sock과 HashMap 2가지(유저,룸)을 가져와서 멤버필드로 넣
this.sock = sock;
this.hm = hm;
this.room = room;
try {
pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
// 서버->클라이언트 출력빨때를 소켓에 꼽음 @@@ pw @@@
br = new BufferedReader(
new InputStreamReader(sock.getInputStream()));
// 클라->서버 를 받아주는 빨대를 소켓에 꼽음 @@@ br @@@
this.id = br.readLine();
// 입력받은 id를 멤버필드에 넣어줌
String add = InetAddress.getLocalHost().getHostAddress();
System.out.println(id + "(" + add + ")" + " 님이 접속하셧습니다.");
broadcast(id + "님이 입장하셨습니다.");
synchronized (hm) {
hm.put(this.id, pw);
// synchronized를 거는 이유 : 수정이잇을시에 동시에 작용하기떄문에 오류가 날수도잇어서
// hm<아이디,서버->클라>
}
} catch (Exception e) {
System.out.println(e);
}
}// -----------------------------------------------생성자
public void run() {
boolean isinroom;
try {
String line = null;
while ((line = br.readLine()) != null) {
// 사용자에게 받은 문자를 모두에게 전달
if (line.equals("/quit")) {
pw.println("종료합니다.");
}// quit
if (line.equals("/make")) {
pw.println("방 제목을 입력하세요.");
pw.flush();
bang = br.readLine();
Set<String> um = room.keySet();
if (um.contains(bang)) {
pw.println("동일한 방제목이 존재합니다. 다시 입력해주세요.");
pw.flush();
} else {
pw.println(bang + "가 생성되었습니당!!!!!!");
pw.flush();
room.put(bang, new HashMap<String, PrintWriter>());
synchronized (hm) {
synchronized (room) {
room.get(bang).put(this.id, hm.get(this.id));
System.out.println("방 생성 이후 room -> "
+ room.size());
// Set<String> idd = room.get(bang).keySet();
broadcast(bang, id + "님께서 " + bang
+ "에 입장하심!!!");
hm.get(this.id).flush();
hm.remove(id);
System.out.println("리무브 이후 hm -> " + hm.size());
}
}
}
} else if (line.equals("/out")) {
hm.put(id, pw);
room.get(room).remove(id);
broadcast(bang, id + "님이 나가셨습니다.");
} else if (line.equals("/join")) {
pw.println("방 제목을 입력하세요");
pw.flush();
bang = br.readLine();
if (room.containsKey(bang)) {
synchronized(room){
room.get(bang).put(id, pw);
// 룸에서 벨류값에 아이디와 빨대를 넣는다
broadcast(bang, id + "님께서 입장하였습니다.");
hm.remove(this.id);
}
} else {
pw.print("해당하는 방이 없엉!!");
}
}// join
else if (line.equals("/show")) {
Set<String> hi = room.keySet();
Iterator<String> it = hi.iterator();
pw.println("현 재 존 재 하 는 방!!!!!!");
pw.flush();
if (room.keySet().size() < 1) {
pw.println("존재하는 방이 없엉!!!!!");
pw.flush();
} else {
pw.println("현재 존재하는 방은"+room.size()+"개 입니다");
while (it.hasNext()) {
pw.println(it);
pw.flush();
}
}
}// if startwith
else {
broadcast(id + " : " + line);
}
}
} catch (Exception e) {
System.out.println(e);
}
}// run
public void broadcast(String bang, String msg) {
if (room.containsKey(bang)) {
HashMap<String, PrintWriter> user = room.get(bang);
synchronized (user) {
Collection<PrintWriter> pws = user.values();
// values => return 밸류들 가져와서 전체 리턴 콜렉션 타
Iterator<PrintWriter> it = pws.iterator();
while (it.hasNext()) {
PrintWriter pwq = it.next();
pwq.println(msg);
pwq.flush();
System.out.println(msg + "\t\t <--- 다보냄");
}
}
}
}
public void broadcast(String msg) {
synchronized (hm) {
Collection<PrintWriter> pws = hm.values();
// values => return 밸류들 가져와서 전체 리턴 콜렉션 타
Iterator<PrintWriter> it = pws.iterator();
while (it.hasNext()) {
PrintWriter pwq = it.next();
pwq.println(msg);
pwq.flush();
}
}
}
}
---------------------------------------------------------------------------------------------------
앰창같은 브로드캐스트에서 특정 방에만 뿌려주는거 어떻게 해야될까..
불린값을 어떻게 주면 될거같은데
그게 감이 아예 안옴;; 하...
님들 길어서 안읽겟죠?
댓글 0