-
클라이언트 서버 채팅공부 2022. 7. 29. 17:47728x90
다양한 사용자들이 채팅을 할 수 있도록 쓰레드를 사용하여 구현
사용자가 들어오면 닉네임 생성
'[nickname]닉네임' 으로 닉네임 변경 기능 구현
'[to:nickname]message' 로 귓속말 구현
'[list]' 로 접속한 사용자 목록 구현
HashMap을 사용하여 닉네임이 중복되지 않았는지 확인
해당 닉네임으로 소켓을 확인하여 메시지 보낼 수 있음
서버
import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.net.SocketException;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Random;
public class ChatServer {static List<Socket> socketList;static HashMap<String,Socket> nickSet;public static void main(String[] args) throws IOException {socketList = new ArrayList<>();nickSet=new HashMap<>();ServerSocket ss= new ServerSocket(9999);System.out.println("Server Started");while(true){Socket cs=ss.accept();socketList.add(cs); // 여러 명의 클라이언트가 접속String nick="";while(!nickSet.containsKey(nick)){ //중복되지 않았는지 확인nick=random_nick(); //닉네임 생성if(!nickSet.containsKey(nick)){nickSet.put(nick,cs);}}System.out.println("[" + nick + "]가 입장했습니다."); //서버 입장 전달, 접속해 있는 인원System.out.println("clients: "+socketList.size());ChatReciever receiver=new ChatReciever(cs,nick);receiver.start();
}}static String random_nick(){ //랜덤 닉네임 생성String nick="";int leftLimit = 97; // letter 'a'int rightLimit = 122; // letter 'z'int targetStringLength = 10; // 10글자 제한Random random = new Random();nick = random.ints(leftLimit, rightLimit + 1).limit(targetStringLength).collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString();return nick;}}class ChatReciever extends Thread{Socket cs;String nick;ChatReciever(Socket cs,String nick){this.cs=cs;this.nick=nick;}public void run(){String msg;try{InputStream is =cs.getInputStream(); //상대방으로부터 읽을 수 있는 스트림DataInputStream dis = new DataInputStream(is);while(dis!=null){msg=dis.readUTF();if(msg.equals("[list]")){ // 리스트 출력printList();}else if(msg.length()>10&&msg.substring(0,10).equals("[nickname]")){ // 닉네임 변경String str=msg.substring(10);changeNick(str);}else if(msg.length()>4&&msg.substring(0,4).equals("[to:")){ // 귓속말 구현String str=msg.substring(4);sendToOne(str);}else{ // 전체 메시지 전송String str="["+nick+"] "+msg;sendToAll(str);}}}catch(SocketException e){ // 채팅 종료ChatServer.socketList.remove(cs);ChatServer.nickSet.remove(nick);String str="["+nick+"]가 나갔습니다. ";sendToAll(str);System.out.println(str);System.out.println("clients: "+ChatServer.socketList.size());}catch(IOException e){throw new RuntimeException();}}void sendToAll(String msg){ // 메시지 전체 보내기try{for(Socket send:ChatServer.socketList){if(send==cs) continue; // 본인 제외OutputStream os = send.getOutputStream();DataOutputStream dos=new DataOutputStream(os);dos.writeUTF(msg);}}catch(IOException e){throw new RuntimeException(e);}}void printList(){ //접속해 있는 리스트 출력try {OutputStream os = cs.getOutputStream();DataOutputStream dos=new DataOutputStream(os);for(String str: ChatServer.nickSet.keySet()){dos.writeUTF(str);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}void changeNick(String str){ // 닉네임 변경if(!ChatServer.nickSet.containsKey(str)){ // 닉네임 중복 체크ChatServer.nickSet.put(str,cs);ChatServer.nickSet.remove(nick);this.nick=str;}else{try {OutputStream os = cs.getOutputStream();DataOutputStream dos=new DataOutputStream(os);dos.writeUTF("중복된 닉네임 입니다.");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}void sendToOne(String str){ // 귓속말 구현String []message=str.split("]");try{if(!ChatServer.nickSet.containsKey(message[0])){ //존재하는 닉네임인지 확인OutputStream os = cs.getOutputStream();DataOutputStream dos=new DataOutputStream(os);dos.writeUTF("존재하지 않는 닉네임 입니다.");}else{Socket send=ChatServer.nickSet.get(message[0]);if(send==cs){ // 본인인지 확인OutputStream os = cs.getOutputStream();DataOutputStream dos=new DataOutputStream(os);dos.writeUTF("사용자 본인 입니다.");}else{OutputStream os = send.getOutputStream();DataOutputStream dos=new DataOutputStream(os);dos.writeUTF("["+nick+"]"+message[1]);}}}catch(IOException e){throw new RuntimeException(e);}}}클라이언트
import java.io.IOException;import java.net.Socket;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.util.Scanner;
public class ChatClient {public static void main(String[] args) throws IOException {//연결 부분Socket cs= new Socket("ip주소",9999);ChatSender sender = new ChatSender(cs);sender.start();ChatReceiver receiver=new ChatReceiver(cs);receiver.start();System.out.println("닉네임 변경: [nickname]변경할닉네임");System.out.println("귓속말: [to:상대닉네임]메시지");System.out.println("접속한 사용자: [list]");}}class ChatReceiver extends Thread{Socket cs;ChatReceiver(Socket cs){this.cs=cs;}public void run(){try{InputStream is =cs.getInputStream(); //상대방으로부터 읽을 수 있는 스트림DataInputStream dis = new DataInputStream(is);while(dis!=null){System.out.println(dis.readUTF());}}catch(IOException e){throw new RuntimeException();}}}
class ChatSender extends Thread{Socket cs;ChatSender(Socket cs){this.cs=cs;}public void run(){try {OutputStream os = cs.getOutputStream();DataOutputStream dos=new DataOutputStream(os);Scanner scanner=new Scanner(System.in);while(dos!=null){String msg=scanner.nextLine();if(msg.equals("quit")){return;}dos.writeUTF(msg);}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}728x90반응형