import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class ChatClient {
public static void main(String[] args) {
try {
String serverIp = "127.0.0.1";
Socket chSocket = new Socket(serverIp, 7777);
Socket fiSocket = new Socket(serverIp, 7778);
System.out.println("서버에 연결되었습니다");
new Thread(new ClientSender(chSocket)).start();
new Thread(new ClientReceiver(chSocket, "receive.txt")).start();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static class ClientSender extends Thread {
Socket socket;
DataOutputStream out;
ClientSender(Socket socket) {
try {
out = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
Scanner sc = new Scanner(System.in);
try {
while (out != null) {
out.writeUTF(sc.nextLine());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static class ClientReceiver extends Thread {
Socket fiSocket;
DataInputStream in;
String file;
ClientReceiver(Socket socket, Socket fiSocket, String file) {
this.fiSocket = fiSocket;
this.file = file;
try {
in = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
while (in != null) {
try {
String readLine = in.readUTF();
System.out.println(in.readUTF());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
static class ClientFileReceiver extends Thread {
DataInputStream in;
FileOutputStream out;
byte[] b = new byte[1024 * 4];
ClientFileReceiver(Socket fileSocket, String file) {
try {
in = new DataInputStream(fileSocket.getInputStream()); // 클라이언트가 보낸 파일을 받는다
out = new FileOutputStream(file); // 그걸 저장
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
try {
int len = 0;
int total = 0;
while ((len = in.read(b, 0, b.length)) != -1) {
out.write(b, 0, len);
total += len;
}
out.close();
System.out.println("receiver : " + total + "bytes received");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} // run
}
/////////////////////////////// 여기까진 클라이언트 클래스
//////////////////////////////// 여기부턴 서버 클래스
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/*
* 2개 이상의 클라이언트에게 채팅 서비스를 제공 // 완료
* 파일 전송 서비스도 제공 // 아직 못함
* 대화방을 제공 // map(대화방)을 map(리스트)에 담는다 // 완료
*
* 클라이언트가 접속하면,
* 현재 대화방 리스트를 보여주고, // 완료
* >클라이언트가 선택한 대화방으로 조인시킨다. // 완료
* >새로운 대화방을 만듦 // 완료
*
* 대화방
* 사용자간의 대화는 모든 참여 사람들에게 전송 // 완료
* 파일 전송도 모든 사람들에게 전송 // 아직 못함
*
* 옵션
* 비밀 대화방 // 완료
* 방장이 자기방만 대화방 폐쇄 // /방폭하기
* 방장이 특정 클라이언트 퇴출 // /강퇴하기
* 방장이 비번 변경 // 비번 변경하기 /강퇴하기
*/
public class ChatServer {
// <방제/ 비번, 대화방>, 사이즈는 대화방 개수
HashMap<ArrayList<String>, HashMap<ArrayList, DataOutputStream>> chatRoom = null;
// 대화방 <이름 / 방장 여부, 클라이언트에게 쏴줄 아웃풋>, 사이즈는 그 대화방에 접속한 사람수
HashMap<ArrayList, DataOutputStream> clients = null;
ChatServer() {
chatRoom = new HashMap<>();
Collections.synchronizedMap(chatRoom);
}
public void start() {
ServerSocket chatSocket = null;
ServerSocket fileSocket = null;
Socket chSocket = null;
Socket fiSocket = null;
try {
chatSocket = new ServerSocket(7777); // 대화 소켓은 7777
fileSocket = new ServerSocket(7778); // 파일 소켓은 7778
System.out.println("서버가 시작되었습니다.");
while (true) {
chSocket = chatSocket.accept(); // 대화 연결 기다림
fiSocket = fileSocket.accept(); // 파일 연결 기다림
System.out.println("[" + chSocket.getInetAddress() + ":" + chSocket.getPort() + "] 에서 접속하였습니다.");
ServerReceiver thread = new ServerReceiver(chSocket, fiSocket);
thread.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void sendFileToAll (ArrayList roomSetting, String file, String name, DataOutputStream out) {
try {
DataInputStream in = new DataInputStream(new FileInputStream(file));
DataOutputStream out2;
byte[] b = new byte[1024 * 4];
Iterator it = chatRoom.get(roomSetting).keySet().iterator();
while (it.hasNext()) {
out2 = (DataOutputStream) chatRoom.get(roomSetting).get(it.next());
int len = 0;
int total = 0;
while ((len = in.read(b, 0, b.length)) != -1) {
out2.write(b, 0, len);
total += len;
}
out2.close();
System.out.println(name +"님이 " + total + "bytes 크기의 파일 " + file +"을 보냈습니다");
}
} catch (FileNotFoundException e1) {
try {
out.writeUTF("해당 파일이 없습니다");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void sendToAll(ArrayList roomSetting, String name, String msg) {
Iterator it = chatRoom.get(roomSetting).keySet().iterator();
while (it.hasNext()) {
try {
DataOutputStream out = (DataOutputStream) chatRoom.get(roomSetting).get(it.next());
out.writeUTF("[" + name + "] : " + msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
void makeRoom(ArrayList roomSetting, ArrayList clientSetting, DataOutputStream out) { // 방제, 클라이언트 이름, 쏴줄 곳
clients = new HashMap<>();
clients.put(clientSetting, out);
chatRoom.put(roomSetting, clients);
}
void showRoomList(DataOutputStream out) {
try {
if (chatRoom.isEmpty())
out.writeUTF("개설된 대화방이 없습니다.");
else {
Iterator it = chatRoom.entrySet().iterator(); // arraylist(방제, 비번), hashmap <리스트, 대화방> 나옴
while (it.hasNext()) {
Map.Entry e = (Map.Entry) it.next();
if (((ArrayList) e.getKey()).size() >= 2) { // 비번 걸린 방
out.writeUTF((String) ((ArrayList) e.getKey()).get(0) + " (비밀방) : "
+ ((HashMap) e.getValue()).size() + "명 접속중");
} else { // 비번 안 걸린 방
out.writeUTF((String) ((ArrayList) e.getKey()).get(0) + " : " + ((HashMap) e.getValue()).size()
+ "명 접속중");
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void showClientList(DataOutputStream out, String roomName) {
Iterator it = chatRoom.keySet().iterator();
ArrayList al = null;
while (it.hasNext()) {
ArrayList al2 = (ArrayList)it.next();
if(al2.get(0).equals(roomName)) {
al = al2;
}
}
it = chatRoom.get(al).keySet().iterator();
while (it.hasNext()) {
try {
out.writeUTF("이름 : " + (String)((ArrayList)it.next()).get(0));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} // 완료
void selectRoom(ArrayList roomSetting, ArrayList clientSetting, DataOutputStream out) { // 방제, 비번, 클라이언트 이름, 방장 여부,
// 쏴줄 곳
chatRoom.get(roomSetting).put(clientSetting, out); // 방제에 해당하는 대화방(hashmap)에 클라이언트 이름,방장여부 / 클라이언트에게 쏴줄 아웃풋 넣음
try {
out.writeUTF("현재 접속자 수는 " + chatRoom.get(roomSetting).size() + "명 입니다");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void roomBoom(String roomName, DataOutputStream out) { // 방 폭파
Iterator it = chatRoom.keySet().iterator();
while(it.hasNext()) {
ArrayList al = (ArrayList)it.next();
if(al.get(0).equals(roomName)) {
try {
out.writeUTF("방이 폭파되었습니다");
chatRoom.remove(al);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} //완료
void kickClient(DataOutputStream out, DataInputStream in, String roomName) { // 특정 클라이언트 퇴출
try {
out.writeUTF("----------------강퇴리스트----------------");
showClientList(out, roomName); // 강퇴 리스트를 보여줌
out.writeUTF("강퇴하고 싶은 사람의 이름을 입력해주세요");
String name = in.readUTF();
Iterator it = clients.keySet().iterator(); // 이름은 clients의 key에 있다
int count = 0;
while(it.hasNext()) {
count++;
ArrayList al = (ArrayList)it.next();
if(al.get(0).equals(name)) { // 이름과 일치하면
clients.remove(al); // 삭제
out.writeUTF(name + "님을 강퇴했습니다");
}
if(!al.get(0).equals(name) && count == clients.size()) {
out.writeUTF("해당 유저가 없습니다");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void changePassword(String roomName, DataOutputStream out, DataInputStream in) { // 비번 변경
Iterator it = chatRoom.keySet().iterator();
while(it.hasNext()) {
ArrayList al = (ArrayList)it.next();
if(al.get(0).equals(roomName)) {
try {
out.writeUTF("새비밀번호를 입력하세요");
al.add(in.readUTF());
out.writeUTF("비밀번호가 변경되었습니다");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} // 이상함
void grantRight(String roomName, DataOutputStream out, DataInputStream in) { // 방장 권한 주기
try {
out.writeUTF("----------------권한 부여 리스트----------------");
showClientList(out, roomName); // 강퇴 리스트를 보여줌
out.writeUTF("방장 권한을 주고 싶은 사람의 이름을 입력해주세요");
String name = in.readUTF();
Iterator it = clients.keySet().iterator(); // 이름은 clients의 key에 있다
int count = 0;
while(it.hasNext()) {
count++;
ArrayList al = (ArrayList)it.next();
if(al.get(0).equals(name)) { // 이름과 일치하면
al.remove(1);
al.add(true);
out.writeUTF(name + "님에게 권한을 부여했습니다");
}
if(!al.get(0).equals(name) && count == clients.size()) {
out.writeUTF("해당 유저가 없습니다");
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} // 이상함
public static void main(String[] args) {
new ChatServer().start();
}
class ServerReceiver extends Thread {
Socket chSocket; // 채팅 소켓
Socket fiSocket; // 파일 소켓
DataInputStream in;
DataOutputStream out;
ServerReceiver(Socket chSocket, Socket fiSocket) {
this.chSocket = chSocket;
this.fiSocket = fiSocket;
try {
in = new DataInputStream(chSocket.getInputStream());
out = new DataOutputStream(chSocket.getOutputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run() {
ArrayList<String> roomSetting = null; // get(0)은 방이름(String), get(1)은 방 비번(String)
ArrayList clientSetting = null; // get(0)은 이름(String), get(1)은 방장 여부(boolean)
String roomName = ""; // chatRoom의 특정key의 get(0) (방 제목)
String password = ""; // chatRoom의 특정key의 get(1) (방 비번)
String name = ""; // chatRoom의 특정 value의 key의 get(0) (클라이언트 이름)
boolean isMaster = false; // chatRoom의 특정 value의 key의 get(1) (클라이언트의 방장 여부)
try {
showRoomList(out);
out.writeUTF("[1] 대화방 들어가기 or [2] 대화방 새로 만들기");
int select = Integer.parseInt(in.readUTF());
if (chatRoom.isEmpty() && select == 1) {
out.writeUTF("개설된 대화방이 없으니 대화방을 새로 만들어주세요");
select = 2;
}
while (select != 1 && select != 2) {
out.writeUTF("잘못 입력하셨습니다");
out.writeUTF("[1] 대화방 들어가기 or [2] 대화방 새로 만들기");
select = Integer.parseInt(in.readUTF());
if (select == 1 && chatRoom.isEmpty()) {
out.writeUTF("개설된 대화방이 없으니 대화방을 새로 만들어주세요");
select = 2;
}
}
if (select == 1) {
out.writeUTF("본인의 이름을 입력해주세요");
name = in.readUTF();
clientSetting = new ArrayList();
clientSetting.add(name);
clientSetting.add(isMaster);
outer: while (true) {
out.writeUTF("대화방을 선택해 주세요");
roomName = in.readUTF();
// roomName과 일치하는 roomName을 가지고 있는 array객체를 찾아야 한다 >> array객체는 chatRoom의 키에 있다.
Iterator it = chatRoom.keySet().iterator();
while (it.hasNext()) {
roomSetting = ((ArrayList) it.next());
if (roomSetting.get(0).equals(roomName)) { // roomName이 chatRoom의 Array객체를 순회하며 일치하는
if (roomSetting.size() >= 2) { // 비밀 번호가 걸려있는 방이면
out.writeUTF("비밀번호를 입력해주세요"); // 비번을 입력받는다
if (roomSetting.get(roomSetting.size()-1).equals(in.readUTF())) { // 비번 일치한다면
selectRoom(roomSetting, clientSetting, out);
sendToAll(roomSetting, name, "님이 들어오셨습니다.");
break outer; // 찾으면 전체 while문 빠져나감
} else { // 비번이 일치하지 않으면
out.writeUTF("비밀번호가 일치하지 않습니다");
it = chatRoom.keySet().iterator();
continue; // 안쪽 while문 돌게해서 다시 입력받게함
}
} else { // 비밀 번호가 안 걸려있으면
selectRoom(roomSetting, clientSetting, out);
sendToAll(roomSetting, name, "님이 들어오셨습니다.");
break outer; // 찾으면 전체 while문 빠져나감
}
}
}
// 해당하는 방제목을 찾지 못함 > 다시 돌려야함.
out.writeUTF("해당하는 방 이름을 찾지 못했습니다, 다시 입력해주세요");
}
} else if (select == 2) {
isMaster = true; // 개설한 사람이 방장
out.writeUTF("방을 개설합니다");
out.writeUTF("본인의 이름을 입력해주세요");
name = in.readUTF();
clientSetting = new ArrayList();
clientSetting.add(name);
clientSetting.add(isMaster);
if (chatRoom.isEmpty()) {
out.writeUTF("방 제목을 정해주세요");
roomName = in.readUTF();
} else {
outer: while (true) {
out.writeUTF("방 제목을 정해주세요");
roomName = in.readUTF();
Iterator it = chatRoom.keySet().iterator();
ArrayList al = null;
int count = 0;
while (it.hasNext()) {
count++;
al = (ArrayList) it.next();
if (al.get(0).equals(roomName)) { // roomName이 chatRoom의 Array객체를 순회하며 일치하는 방제를 찾으면
out.writeUTF("이미 존재하는 방 이름입니다, 방제를 다시 설정해주세요");
showRoomList(out);
break; // 나가서 올바른 방제를 입력할 때까지 돌리게함
} else if (!(al.get(0).equals(roomName)) && count == chatRoom.size()) { //
break outer;
}
}
}
}
out.writeUTF("비밀번호를 설정하시겠습니까? Y/N");
String answer = in.readUTF().toLowerCase();
while (!answer.equals("y") && !answer.equals("n")) {
out.writeUTF("잘못 입력하셨습니다");
out.writeUTF("비밀번호를 설정하시겠습니까? Y/N");
answer = in.readUTF().toLowerCase();
}
if (answer.equals("y")) {
out.writeUTF("비밀번호를 설정해주세요");
password = in.readUTF();
roomSetting = new ArrayList<>();
roomSetting.add(roomName);
roomSetting.add(password);
makeRoom(roomSetting, clientSetting, out);
out.writeUTF("대화방이 개설되었습니다");
} else if (answer.equals("n")) {
roomSetting = new ArrayList<>();
roomSetting.add(roomName);
makeRoom(roomSetting, clientSetting, out);
out.writeUTF("대화방이 개설되었습니다");
}
}
while (in != null) {
String readLine = in.readUTF();
if (readLine.equals("/방폭하기") && (boolean) clientSetting.get(1)) {
roomBoom(roomName, out);
} else if (readLine.equals("/방폭하기") && !(boolean) clientSetting.get(1)) {
out.writeUTF("권한이 없습니다");
} else if (readLine.equals("/강퇴하기") && (boolean) clientSetting.get(1)) {
kickClient(out ,in, roomName);
} else if (readLine.equals("/강퇴하기") && !(boolean) clientSetting.get(1)) {
out.writeUTF("권한이 없습니다");
} else if (readLine.equals("/비번 변경하기") && (boolean) clientSetting.get(1)) {
changePassword(roomName, out, in);
} else if (readLine.equals("/비번 변경하기") && !(boolean) clientSetting.get(1)) {
out.writeUTF("권한이 없습니다");
} else if (readLine.equals("/방장 권한주기") && (boolean) clientSetting.get(1)) {
grantRight(roomName, out, in);
} else if (readLine.equals("/방장 권한주기") && !(boolean) clientSetting.get(1)) {
out.writeUTF("권한이 없습니다");
} else if (readLine.equals("/파일 보내기")) {
out.writeUTF("보낼 파일을 입력하세요");
sendFileToAll(roomSetting, in.readUTF(), name, out);
} else if (readLine.equals("/사람 목록")) {
showClientList(out, roomName);
}
else
sendToAll(roomSetting, name, readLine);
}
} catch (IOException e) {
} finally {
chatRoom.get(roomSetting).remove(clientSetting);
sendToAll(roomSetting, "관리자", "[" + chSocket.getInetAddress() + ":" + chSocket.getPort() + "]" + "["
+ name + "] 님께서 접속을 종료하였습니다.");
sendToAll(roomSetting, "관리자", "현재 접속자 수는 " + chatRoom.get(roomSetting).size() + "명 입니다");
}
}
}
}
대화방 만들고 그 안에서만 채팅 다 되고 방 리스트 보여주고 비밀방 시스템도 되고 방 안에있는 사람 목록 보기도 되는데
방장 권한을
잘 봤습니다
시발 ㅋㅋㅋㅋ
아니 씨바 github에 올려서 링크를 주던지 말던지 해야지
ㅋㅋㅋㅋ