-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChatGUIServer.java
More file actions
212 lines (163 loc) · 7.08 KB
/
Copy pathChatGUIServer.java
File metadata and controls
212 lines (163 loc) · 7.08 KB
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
import java.net.*; // ServerSocket, Socket
import java.io.*; // 입출력
import javax.swing.*;
import java.sql.*;
// 동적 배열, 접속한 클라이언트의 정보를 실시간으로 저장하는 목적(고정 배열X)
import java.util.ArrayList;
import java.util.Vector;
public class ChatGUIServer {
// 클라이언트와 연결할 때만 필요한 ServerSocket 클래스
ServerSocket ss;
// 서버로 접속한 클라이언트 Socket을 저장할 멤버 변수
Socket s;
// 접속 클라이언트 정보 실시간 저장
Vector v;
// ServerThread 자료형 멤버 변수 선언, has-a 관계 설정을 위함
ServerThread st;
// 생성자, 멤버 변수 초기화
public ChatGUIServer() {
// 사용자 정보를 담을 v를 Vector 객체로 초기화
v = new Vector();
// 접속이 될 수도 있고 안 될 수도 있기 때문에 예외 처리
try {
// ServerSocket 객체 생성 → 포트 번호 생성(임의의 번호 부여)
ss = new ServerSocket(5432);
System.out.println("ss>>>" + ss);
System.out.println("채팅 서버 가동중...");
// 서버 가동: 클라이언트가 접속할 때까지 기다리는 것(무한 대기)
while (true) {
// 접속 클라이언트 Socket을 s 변수에 저장
s = ss.accept();
System.out.println("Accepted from" + s);
// 접속 클라이언트와 서버로 st객체 생성
st = new ServerThread(this, s);
// 접속할 때마다 v에 접속 클라이언트 스레드 추가
this.addThread(st);
// Thread 가동 -> run() -> broadCast() -> send() 실시간 메소드 호출
st.start();
}
} catch (Exception e) {
// 접속 실패시 간단한 Error 메세지 출력
System.out.println("서버 접속 실패>>>" + e);
}
}
// 벡터 v에 접속 클라이언트의 스레드 저장
public void addThread(ServerThread st) {
v.add(st);
}
// 퇴장한 클라이언트 스레드 제거
public void removeThread(ServerThread st) {
v.remove(st);
}
// 각 클라이언트에게 메세지를 출력하는 메소드, send() 호출
public void broadCast(String str) {
for (int i = 0; i < v.size(); i++) {
// 각각의 클라이언트를 ServerThread 객체로 형 변환
ServerThread st = (ServerThread) v.elementAt(i);
// 각 스레드 객체에 str 문자열을 전송
st.send(str);
}
}
public static void main(String[] args) {
// 익명 객체 생성
new ChatGUIServer();
}
}
// ServerThread 클래스 생성 → 서버에서 각 클라이언트의 요청을 처리할 스레드
class ServerThread extends Thread {
// 클라이언트 소켓 저장
Socket s;
// ChatGUIServer 클래스의 객체를 멤버 변수로 선언, has-a 관계를 위함
ChatGUIServer cg;
// 입출력
BufferedReader br;
PrintWriter pw;
// 전달할 문자열
String str;
// 대화명(ID)
String name;
//채팅 대상
String toname;
// 생성자
public ServerThread(ChatGUIServer cg, Socket s) {
/* cg = new ChatGUIServer(); → 작성 불가, 서버가 두 번 가동되기 때문에 충돌이 일어남
따라서 매개변수를 이용해서 객체를 얻어온(call by reference) 뒤에 cg와 s값을 초기화해야 함
*/
this.cg = cg;
// 접속한 클라이언트 정보 저장
this.s = s;
// 데이터 전송을 위한 입출력 스트림 생성
try {
// =========== 입력 ===========
// s.getInputStream() => 접속 클라이언트(소켓 객체)의 InputStream을 얻어 옴
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
// =========== 출력 ===========
/*
BufferedWriter의 경우 버퍼링 기능을 가지기 때문에 PrintWriter 스트림 사용
PrintWriter 스트림의 경우 생성자의 두 번째 인자로 autoFlush 기능을 지정할 수 있음
BufferedWriter를 사용하는 경우 flush() 메소드를 사용해야 함
*/
pw = new PrintWriter(s.getOutputStream(), true);
} catch (Exception e) {
System.out.println("에러 발생>>>>>" + e);
}
}
// 메세지(입력 문자열) 출력 메소드
public void send(String str) {
// 문자열 출력
pw.println(str);
// 혹시나 버퍼에 남아있는 것을 비워냄
pw.flush();
}
// run()_ServerThread -> broadCast(str)_ChatGUIServer -> send(str)_ServerThread
public void run() {
try {
//승인 여부
int var = JOptionPane.showConfirmDialog(null, "승인하시겠습니까?", "승인", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE, null);
if(var==1)
{
return;
}
// 대화명 입력 받기
pw.println("대화명을 입력하세요");
String[] ntn = br.readLine().split(",");
name = ntn[0];//자기 이름
toname = ntn[1];//원하는 대상 이름
if(toname==null)
{
new Thread(new ChatGUIClient1(name)).start();
}
/*
try {
String sql_query = String.format("select id from user where id = '%s';",toname);
Connection conn = getConnection();
Statement stmt = conn.createStatement();
ResultSet rset = stmt.executeQuery(sql_query);
rset.next();
} catch (SQLException ex) {
JOptionPane.showMessageDialog(null, "Login Failed", "로그인 실패", 1);
System.out.println("SQLException" + ex);
}
*/
// 서버에서 각 클라이언트에 대화명 출력
cg.broadCast("[" + name + "]" + "님이 입장했습니다.");
// 무한 대기하며 입력한 메세지를 각 클라이언트에 계속 전달
while ((str = br.readLine()) != null) {
cg.broadCast("[" + name + "]: " + str);
}
} catch (Exception e) {
// 접속자 퇴장시 v에서 해당 클라이언트 스레드 제거
cg.removeThread(this); // this: ServerThread 객체, 접속 클라이언트
// 서버에서 각 클라이언트에 출력
cg.broadCast("[" + name + "]" + "님이 퇴장했습니다.");
// 콘솔에 퇴장 클라이언트 IP 주소 출력
System.out.println(s.getInetAddress() + "의 연결이 종료됨!");
}
}
public Connection getConnection() throws SQLException {
Connection conn = null;
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/network", "root",
"Namja241377@");
return conn;
}
}