Java - Socket 클래스,Server,Client

2020. 7. 29. 22:42Java

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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
 
public class Server {
 
    public static void main(String[] args) {
        
        ServerSocket serverSocket=null;
        Socket socket=null;
        
        try {
            //ServerSocket 객체 생성 시, 생성자에 사용할 포트번호 전달
            //-> 해당 포트가 사용중일 경우 IOException 발생할 수있음.
            serverSocket= new ServerSocket(59876);
            System.out.println("서버 소켓 생성 완료");
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        //-------------------------------------------------------------
        
        try {
            while(true) {
                //생성된 ServerSocket 객체의 accept() 메서드를 호출하여
                //클라이언트로부터의 연결 요청을 대기하도록 지정
                //만약, 클라이언트로부터 연결 요청을 받아 수락할 경우 Socket 객체라 리턴됨 
                socket= serverSocket.accept();//연결 실패 시 IOException 발생할 수 있음
                System.out.println("클라이언트와 소켓 연결 완료");
                
                //접속된 클라이언트에게 메세지 전송(=텍스트 출력)
                //데이터 출력을 위한 출력스트림 연결 필요= Socket 객체로부터 리턴받기
//                OutputStream os=socket.getOutputStream();
                //자바의 String 타입 데이터를 바로 출력하기 위해 DataOutputStream 객체 생성
//                DataOutputStream ds=new DataOutputStream(os);
                
                //위의 두 문장을 한 문장으로 결합
                DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
                
                //DataOutputStream 객체의 writeUTF() 메서드를 호출하여 문자열 출력
                dos.writeUTF("환영합니다.");
                
                //DataOutputStream 객체 반환
                dos.close();
                
                
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        
        
    }
 
}
 
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
 
public class Client {
 
    public static void main(String[] args) {
        Socket socket=null;
        try {
            //접속할 서버의 주소와 해당 포트번호를 갖는 Socket 객체 생성
            String host="localhost";//서버의 IP주소 또는 도메인(localhost 지정 시 현재 PC)
            int port=59876;//서버의 포트번호
            
            socket=new Socket(host, port);
            System.out.println("소켓 생성 완료");
            
            //서버로부터 전송되는 텍스트를 입력스트림을 통해 전달받아 출력
            //->DataOutputStream 으로 전송된 데이터는 DataInputStream으로 읽어야하며
            //- writeUTF() 메서드로 출력했기 때문에, readUTF()메서드로 읽어오기
            DataInputStream dis=new DataInputStream(socket.getInputStream());
            
            String str=dis.readUTF();
            System.out.println("서버 : "+str);
            dis.close();
            
        } catch (UnknownHostException e) {
            //호스트명이 잘못됐을 경우 발생할 수있는 예외
            e.printStackTrace();
        } catch (IOException e) {
            //포트번호가 잘못됐을 경우 발생할 수있는 예외
            e.printStackTrace();
        }finally {
            //생성된 소켓은 반환 필수
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
 
    }
 
}
//------------------------------------------------------------------------------------
 
 
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
 
public class Server2 {
 
    public static void main(String[] args) {
        
        ServerSocket serverSocket=null;
        Socket socket=null;
        
        try {
            //ServerSocket 객체 생성 시, 생성자에 사용할 포트번호 전달
            //-> 해당 포트가 사용중일 경우 IOException 발생할 수있음.
            serverSocket= new ServerSocket(59876);
            System.out.println("서버 소켓 생성 완료");
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        //-------------------------------------------------------------
        
        try {
            while(true) {
                //생성된 ServerSocket 객체의 accept() 메서드를 호출하여
                //클라이언트로부터의 연결 요청을 대기하도록 지정
                //만약, 클라이언트로부터 연결 요청을 받아 수락할 경우 Socket 객체라 리턴됨 
                socket= serverSocket.accept();//연결 실패 시 IOException 발생할 수 있음
                System.out.println("클라이언트와 소켓 연결 완료");
                
                //Person 객체를 생성하여 이름,나이,주민번호를 저장한 뒤
                //ObjectOutputStream 객체를 사용하여 Person 객체를 클라이언트에게 전송
                Person p=new Person("김두한""8801010-1111222"21);
                ObjectOutputStream op=new ObjectOutputStream(socket.getOutputStream());
                op.writeObject(p);
                
                
                op.close();
                
                
                socket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        
    }
 
}
//Person 객체를 네트워크로 전송하기 위해 직렬화를 해야하며,
//직렬화를 위해서는 클래스 선언 시 Serializable 인터페이스를 구현해야함(추상메서드는 없음)
class Person implements Serializable{
    String name;
    String jumin;
    int age;
    public Person(String name, String jumin, int age) {
        super();
        this.name = name;
        this.jumin = jumin;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", jumin=" + jumin + ", age=" + age + "]";
    }
    
}
 
import java.io.DataInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.net.UnknownHostException;
 
public class Client2 {
 
    public static void main(String[] args) {
        Socket socket=null;
        try {
            //접속할 서버의 주소와 해당 포트번호를 갖는 Socket 객체 생성
            String host="localhost";//서버의 IP주소 또는 도메인(localhost 지정 시 현재 PC)
            int port=59876;//서버의 포트번호
            
            socket=new Socket(host, port);
            System.out.println("소켓 생성 완료");
            
            ObjectInputStream oi=new ObjectInputStream(socket.getInputStream());
            
            Object o=oi.readObject();
            
            if(o instanceof Person) {
                Person p=(Person)o;
                System.out.println(p);
            }
            oi.close();
        } catch (UnknownHostException e) {
            //호스트명이 잘못됐을 경우 발생할 수있는 예외
            e.printStackTrace();
        } catch (IOException e) {
            //포트번호가 잘못됐을 경우 발생할 수있는 예외
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            //생성된 소켓은 반환 필수
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
 
    }
 
}
 
 
 
 
cs

Server와 Client를 객체로 만들어서 연결되는 과정과 순서를 알아보았다.

서버를 먼저 실행시켜야 하고 신호가 나가는 것이니 OutputStream을 적용시켰고

클라이언트가 받아 들이는 것이니 InputStream을 적용시켜서 출력된 것을 받아들였다.

객체도 넘겨줄수 있었고 개념은 확실히 이해가 되었다. 객체를 넘길 때엔 implements Serializable 마커인터페이스를 적용시켜서 직렬화를 시켜 넘긴다.

예외를 보면 알게되니 곧바로 알 수 있다.