ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 클라이언트 서버 채팅
    공부 2022. 7. 29. 17:47
    728x90

    다양한 사용자들이 채팅을 할 수 있도록 쓰레드를 사용하여 구현

    사용자가 들어오면 닉네임 생성

    '[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 block
                e.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 block
                        e.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 block
                e.printStackTrace();
            }
           
           
        }
    }

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    728x90
    반응형

    '공부' 카테고리의 다른 글

    데이터베이스  (0) 2022.08.10
    네이버 항공권 크롤링 - 파이썬  (0) 2022.08.09
    DB  (0) 2022.07.28
    kafka  (0) 2022.07.28
    HashMap  (0) 2022.07.28

    댓글

Designed by Tistory.