본문

TCP/IP 멀티채팅 프로그램

반응형

# TCP/IP 멀티채팅 프로그램


Source01) TcpIpMultiChattingServer.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
 
public class TcpIpMultiChattingServer {
    final static int SERVER_PORT = 7777;
 
      // 서버에 접속한 클라이언트를 HashMap에 저장하여 관리한다.
    HashMap clients;
 
    public TcpIpMultiChattingServer() {
        clients = new HashMap();
        Collections.synchronizedMap(clients);    // 동기화 처리
    }
 
    public void start() {
        ServerSocket serverSocket = null;
        Socket socket = null;
 
        try {
            serverSocket = new ServerSocket(SERVER_PORT);
            System.out.println("서버가 시작되었습니다.");
 
            while (true) {
                socket = serverSocket.accept();
                System.out.println("[" + socket.getInetAddress() + ":" + socket.getPort() + "]" + "에서 접속하였습니다.");
 
                ServerReceiver thread = new ServerReceiver(socket);
                thread.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    void sendToAll(String msg) {
   // 클라이언트가 멀티채팅서버에 접속하면 HashMap에 저장되고 접속을 해제하면 hashMap에서 제거한다. 
   // 클라이언트가 데이터를 입력하면, 멀티채팅서버는 HashMap에 저장된 모든 클라이언트에게 데이터를 전송한다.
        Iterator it = clients.keySet().iterator();
 
        while (it.hasNext()) {
            try {
                DataOutputStream out = (DataOutputStream) clients.get(it.next());
                out.writeUTF(msg);
            } catch (Exception e) {
            }
        }
    }
 
    public static void main(String[] args) {
        new TcpIpMultiChattingServer().start();
    }
  
  // 멀티채팅서버의 ServerReceiver쓰레드는 클라이언트가 추가될 때마다 생성되며
    // 클라이언트의 입력을 서버에 접속된 모든 클라이언트에게 전송하는 일을 한다.
    class ServerReceiver extends Thread {
        Socket socket;
        DataInputStream in;
        DataOutputStream out;
 
        public ServerReceiver(Socket socket) {
            this.socket = socket;
            try {
                in = new DataInputStream(socket.getInputStream());
                out = new DataOutputStream(socket.getOutputStream());
            } catch (IOException ie) {
            }
        }
 
   // 이 쓰레드의 run()을 보면 클라이언트가 새로 추가되었을 때 클라이언트의 이름을
        // key로 클라이언트의 출력스트림을 HashMap인 clients에 저장해서
        // 다른 클라이언트가 입력한 데이터를 전송하는데 사용하는 것을 알 수 있다.
        // 만일 클라이언트가 종료되어 클라이언트의 입력스트림(in)이 null이 되면 while문을 빠져나가서
        // clients의 목록에서 해당 클라이언트를 제거한다.
        public void run() {
            String name = "";
            try {
                name = in.readUTF();
                sendToAll("#" + name + "님이 입장했습니다.");
 
                clients.put(name, out);
                System.out.println("현재 서버접속자 수는 " + clients.size() + "입니다.");
 
                while (in != null) {
                    sendToAll(in.readUTF());
                }
            } catch (IOException ie) {
            } finally {
                sendToAll("#" + name + "님이 퇴장했습니다.");
                clients.remove(name);
                System.out.println("[" + socket.getInetAddress() + ":" + socket.getPort() + "]" + "에서 접속을 종료하였습니다.");
                System.out.println("현재 서버접속자 수는 " + clients.size() + "입니다.");
            }
        }
    }
}
cs


Source02) TcpIpMultiChattingClient.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;
import java.util.Scanner;
 
public class TcpIpMultiChattingClient {
    final static int SERVER_PORT = 7777;
    final static String SERVER_IP = "127.0.0.1";
 
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("프로그램 실행방법 : java TcpIpMultiChattingClient 사용자명");
            System.exit(0);
        }
 
        try {
            String serverIp = SERVER_IP;
            // 소켓을 생성하여 연결을 요청한다.
            Socket socket = new Socket(serverIp, SERVER_PORT);
            System.out.println("서버에 연결되었습니다.");
 
            Thread sender = new Thread(new ClientSender(socket, args[0]));
            Thread receiver = new Thread(new ClientReceiver(socket));
 
            sender.start();
            receiver.start();
        } catch (ConnectException ce) {
            ce.printStackTrace();
        } catch (Exception e) {
        }
    }
 
    static class ClientSender extends Thread {
        Socket socket;
        DataOutputStream out;
        String name;
 
        public ClientSender(Socket socket, String name) {
            this.socket = socket;
            try {
                out = new DataOutputStream(socket.getOutputStream());
                this.name = name;
            } catch (Exception e) {
            }
        }
 
        public void run() {
            Scanner scanner = new Scanner(System.in);
            try {
                if (out != null) {
                    out.writeUTF(name);
                }
 
                while (out != null) {
                    out.writeUTF("[" + name + "]" + scanner.nextLine());
                }
            } catch (IOException e) {
            }
        }
    }
 
    static class ClientReceiver extends Thread {
        Socket socket;
        DataInputStream in;
 
        public ClientReceiver(Socket socket) {
            this.socket = socket;
            try {
                in = new DataInputStream(socket.getInputStream());
            } catch (IOException io) {
            }
        }
 
        public void run() {
            while (in != null) {
                try {
                    System.out.println(in.readUTF());
                } catch (IOException ie) {
                }
            }
        }
    }
}
cs


Result-server(left), client(right))





출처 및 참고자료 : JAVA의정석(남궁성 저)

반응형

공유

댓글