본문 바로가기
프로그래밍/자바

자바 소켓 프로그래밍 - 동시 채팅프로그램 예제

by 밍구몬 2019. 3. 22.

소켓이란?

 

이용하여 두 프로그램이 네트워크를 통해 서로 통신을 수행할 수 있도록 양쪽에 생성되는 단자이다.(TCP) 

 

소켓 통신 과정

 

 

 

 

예제소스 설명

 

이 예제에서는 데이터를 한번씩이 아닌 여러번씩 주고 받기 위하여 쓰레드를 사용하였다.

서버의 경우에는 소켓으로부터 연결요청을 들어오면 데이터를 받아오는 Input쓰레드와 데이터를 보내는 Ouput쓰레드를 사용하였고,

클라이언트는 데이터를 보내는 Output쓰레드를 사용하였다.

 

서버가 클라이언트에게 exit를 보내게 되면, 클라이언트는 Output쓰레드를 정지시키고 소켓을 닫는다.

반대로, 클라이언트가 서버에게 exit를 보내게 되면, 서버는 Output쓰레드와 Input쓰레드를 정지시키고 소켓을 닫는다.

 

 

서버 소스

 

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
102
103
import java.lang.Thread;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
 
public class Server {
 
    public static void main(String[] args){
        try {
            ServerSocket server = new ServerSocket(5959);    //서버의 소켓을 5959번 포트로 생성
            
            while(true) {
                Socket socket = server.accept();    //클라이언트 연결 대기
                System.out.println("클라이언트가 접속하였습니다.");
                Input input = new Input(socket);    //Input 쓰레드 생성
                input.start();
                Output output = new Output(socket);            //Output 쓰레드 생성
                output.start();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
class Input extends Thread {
    BufferedReader in;
    Socket socket;
    String data=null;
    Input(Socket socket){
        this.socket=socket;
    }
    public void run() {
        while(true) {
            try {
                //소켓으로 데이터 받아오기
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                data = in.readLine();
                if(data == null || data.equals("exit")) {
                    break;
                }else {
                    System.out.println("Client : "+data);    //받아온 데이터 출력
                }
            } catch (IOException e) {
                break;
            }
        }
        System.out.println("클라이언트와 연결 종료 Input 쓰레드 종료");
        try {
            in.close();
            socket.close();
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 
class Output extends Thread{
    BufferedReader in;
    PrintWriter out;
    Socket socket;
    Output(Socket socket){
        this.socket=socket;
        try {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
        } catch (IOException e) {
            System.out.println("aa");
            Output.interrupted();
        }
    }
    public void run() {
        String data;
        while(true) {
            try {
                //키보드로부터 입력
                data = in.readLine();
                out.println(data);                        //서버로 데이터 전송
                out.flush();
                if(data.equals("exit"|| socket.isClosed()){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("클라이언트와 연결 종료 Output 쓰레드 종료");
        try {
            in.close();
            out.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
 
cs

 

클라이언트 소스

 

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
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
 
public class Client1 {
    public static void main(String[] args) {
        Socket socket = null;
        BufferedReader in;
        PrintWriter out;
        String data=null;
        
        try {
            socket = new Socket("127.0.0.1"5959);//아아디,포트
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
            
            //실시간으로 데이터를 주고 받기 위하여 쓰레드 사용
            Output output = new Output(socket);
            output.start();
            
            while(true) {
                try { 
                    //소켓으로부터 데이터 받아오기
                    try {
                        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        data = in.readLine();
                    }catch(Exception e) {
                        break;
                    }
                    if(data == null || data.equals("exit")) {
                        socket.close();
                        output.interrupt();        //output쓰레드 종료
                        break;
                    }else if(data!=null) {
                        System.out.println("server : "+data);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            try {
                socket.close();
            }catch (Exception e) {
            }
            System.out.println("서버와 연결 종료");
           
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
 
 
class Output extends Thread{
    BufferedReader in;
    PrintWriter out;
    Socket socket;
    Output(Socket socket){
        this.socket=socket;
        try {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
        } catch (IOException e) {
            System.out.println("aa");
            Output.interrupted();
        }
    }
    public void run() {
        String data;
        while(true) {
            try {
                //키보드로부터 입력
                data = in.readLine();
                out.println(data);                        //서버로 데이터 전송
                out.flush();
                if(data.equals("exit"|| socket.isClosed()){
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("서버와 연결 종료 Output 쓰레드 종료");
        try {
            in.close();
            out.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
cs