반응형
1. 서버 ( ChatServer.java )
더보기
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class ChatServer {
private ServerSocket svSocket;
private List<ChatHandler> clist;
public ChatServer() {
try {
svSocket = new ServerSocket(9500); // 포트
System.out.println("# 서버 준비 완료");
clist = new ArrayList<ChatHandler>();
while (true) {
System.out.println("소켓 생성");
Socket socket = svSocket.accept();
ChatHandler handler = new ChatHandler(socket, clist);
handler.start();
clist.add(handler);
System.out.println("생성된 리스트 개수 : " + clist.size());
// handler 객체 안에서 스레드를 돌린다.
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new ChatServer();
}
}
생성자 Chatserver - 9500포트로 서버를 열고 들어오는 접속을 받아 각각 핸들러 객체 할당.
main - 서버 실행
2. 핸들러 ( ChatHandler.java )
더보기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.List;
public class ChatHandler extends Thread {
private Socket socket;
private List<ChatHandler> list;
private BufferedReader br;
private PrintWriter pw;
public ChatHandler(Socket socket, List<ChatHandler> list) {
this.socket = socket;
this.list = list;
try {
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String line;
// 닉네임 받는 쪽
try {
String nickName = br.readLine();
// 모든 클라이언트에게 보내기
broadCast(nickName + "님이 입장했습니다.");
while(true) {
line = br.readLine();
// 종료
if(line == null || line.toLowerCase().equals("quit")) {
break;
}
// 별찍기
if(line.toLowerCase().equals("star")) {
for (int i = 1; i <= 5; i++) {
String star = new String();
//공백을 담당하는 j for 문
for (int j = 5; j > i; j--) {
star += " ";
}
//별을 담당하는 k for 문
//5번의 별의 갯수는 2 * i - 1개 만큼의 별이 각 줄에 들어가게 된다.
for (int k = 0; k < i * 2 - 1; k++) {
star += "*";
}
broadCast(star);
}
}
//메세지를 모든 클라이언트에게 보내기
broadCast("[" + nickName + "]" + line);
}//while
// quit을 보낸 클라이언트에게 quit을 보내기
pw.println("quit");
pw.flush();
// 남을 클라이언트에게 퇴장메세지 보내기
list.remove(this); // 현재 handler를 list에서 지움
broadCast(nickName + "님이 퇴장하였습니다.");
br.close();
pw.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}// run()
public void broadCast(String msg) {
for (ChatHandler handler : list) {
handler.pw.println(msg);
handler.pw.flush();
}
}
}
생성자 ChatHandler - 소켓 객체와 전체 핸들러 리스트(모든 접속자 정보), 입출력 객체 생성
run - 접속 직후 닉네임을 입력받음. 메세지 또는 "quit", "star" 등으로 상호작용.
broadcast(String msg) - 모든 핸들러(접속자)에게 메세지를 전송 후 스트림 비움.
3. 클라이언트 ( ChatClient.java )
더보기
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
public class ChatClient extends JFrame implements Runnable, ActionListener {
private JTextField input;
private JButton send;
private JTextArea output;
private Socket socket;
private BufferedReader br;
private PrintWriter pw;
public ChatClient() {
output = new JTextArea();
JScrollPane scroll = new JScrollPane(output);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
output.setEditable(false);
input = new JTextField();
send = new JButton("보내기");
JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.add("Center", input);
p.add("East", send);
Container con = this.getContentPane();
con.add("Center", scroll);
con.add("South", p);
setBounds(700, 200, 300, 300);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
pw.println("quit");
pw.flush();
}
});
}// ChatClient()
public void service() throws IOException {
// 서버IP
// String serverIP = JOptionPane.showInputDialog(this,
// "서버IP를 입력하세요",
// "서버IP",
// JOptionPane.INFORMATION_MESSAGE);
String serverIP = JOptionPane.showInputDialog(this, "서버IP를 입력하세요", "192.168.43.193");
if (serverIP == null || serverIP.length() == 0) {
System.out.println("서버 IP가 입력되지 않았습니다.");
System.exit(0);
}
// 닉네임
String nickName = JOptionPane.showInputDialog(this, "닉네임을 입력하세요", "닉네임", JOptionPane.INFORMATION_MESSAGE);
if (nickName == null || nickName.length() == 0) {
nickName = "guest";
}
try {
socket = new Socket(serverIP, 9500);
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (UnknownHostException e) {
e.printStackTrace();
System.out.println("서버를 찾을 수 없습니다.");
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
System.out.println("서버와 연결이 되지 않았습니다.");
System.exit(0);
}
// 서버로 닉네임 보내기
pw.println(nickName);
pw.flush();
// 스레드 생성
Thread t = new Thread(ChatClient.this); // 실행하려는 클래스 주소 입력
t.start();
// 이벤트
send.addActionListener(this);
input.addActionListener(this); // JTextField에서 엔터 단축키
}// Service()
public static void main(String[] args) throws IOException {
new ChatClient().service();
}
@Override
public void run() {
// 서버로부터 받는 쪽
String line;
while (true) { // 내가 빠져나가지 않는 한, 데이터를 계속 받는다.
try {
line = br.readLine();
if (line == null || line.toLowerCase().equals("quit")) {
br.close();
pw.close();
socket.close();
System.exit(0);
}
output.append(line + "\n");
// int pos = output.getText().length();
output.setCaretPosition(output.getText().length());
} catch (IOException e) {
e.getStackTrace();
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
// 서버로 보내는 쪽
String msg = input.getText();
// PrintWriter 클래스는 Println으로 입력
pw.println(msg);
pw.flush();
input.setText(""); // 텍스트필드 초기화
}
}
생성자 ChatClient - JFrame 윈도우 생성 및 열기.
service - IP 및 닉네임 입력, 서버 접속, 스레드 생성, 버튼 이벤트 생성.
main - 채팅 프로그램 실행. ( ChatClient 객체 생성 및 service() 호출. )
run(스레드) - 스레드가 계속 동작하며 서버로부터 메세지 수신.
actionPerformed - 내가 보낸 메세지 내 채팅창에 띄우고 입력공간 비우기
반응형
'Dev > Java' 카테고리의 다른 글
JDK 1.8 설치중 AdoptOpenJDK (OpenJ9) vs (Hotspot) (0) | 2021.02.18 |
---|---|
Java - NotePad (Swing) (0) | 2020.10.22 |
Java 예제 - 로또 번호 만들기 ( random, array, nested For loop) (0) | 2020.09.10 |
Java - 숫자맞추기 게임 (Math.random(), .equals(), BufferedReader) (0) | 2020.09.09 |
Java 가위바위보 게임 ( Math.random(), System.in.read() ) (0) | 2020.09.08 |