간단한 채팅 프로그램 만들기
- 다대다 클라이언트 간의 채팅
- 서버는 클라이언트에게 메시지를 뿌려주는 역할
[Server]
package tcp4;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Server {
ServerSocket serSock;
List<Socket> sockList;
public Server() throws IOException {
serSock = new ServerSocket(10081);
sockList = new ArrayList<>();
}
public void all_client_write(Socket sock, String msg) {
BufferedOutputStream bos = null;
try {
String info = "[" + sock.getRemoteSocketAddress() + "] : ";
for (int i = 0; i < sockList.size(); i++) {
bos = new BufferedOutputStream(sockList.get(i).getOutputStream());
System.out.println("send to " + sockList.get(i).toString() + ":" + msg);
String inFoMsg = info + msg;
bos.write(inFoMsg.getBytes("UTF-8"));
bos.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
bos.close();
sock.close();
removeSock(sock);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("server write exception!");
e.printStackTrace();
}
}
public void stop(Thread thread) {
thread.interrupt();
}
public void removeSock(Socket sock) {
System.out.println("socket is close");
System.out.println("====================================");
System.out.println("현재 접속: " + sockList.size());
for (int i = 0; i < sockList.size(); i++) {
if (sockList.get(i) == sock) {
try {
sockList.get(i).close();
sockList.remove(i);
break;
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
for (int i = 0; i < sockList.size(); i++) {
System.out.println(sockList.get(i).toString());
}
System.out.println("====================================\n\n");
}
public void read(Socket sock) {
Thread thread = null;
thread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
BufferedInputStream bis = null;
boolean flag = true;
try {
while (flag) {
bis = new BufferedInputStream(sock.getInputStream());
byte b[] = new byte[256];
int data = bis.read(b);
if (data != 0) {
String msg = new String(b);
System.out.println("[" + sock.getLocalAddress() + "] : " + msg);
all_client_write(sock, msg);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
sock.close();
removeSock(sock);
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
}
}
});
thread.start();
}
public void startServer() {
System.out.println("start Server!");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
while (true) {
Socket sock = null;
sock = serSock.accept();
sockList.add(sock);
System.out.println("====================================");
System.out.println("현재 접속: " + sockList.size());
for (int i = 0; i < sockList.size(); i++) {
System.out.println(sockList.get(i).toString());
}
System.out.println("====================================\n\n");
read(sock);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("socket accept excpetion");
return;
}
}
});
thread.start();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
new Server().startServer();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("server start exception");
}
}
}
[Client]
package tcp4;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
Socket sock;
String host;
int port;
public void connect() throws UnknownHostException, IOException {
host = "localhost";
port = 10081;
sock = new Socket();
sock.connect(new InetSocketAddress(host, port));
}
public void read() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
BufferedInputStream bis = null;
try {
while (true) {
bis = new BufferedInputStream(sock.getInputStream());
byte[] b = new byte[256];
int data = bis.read(b);
if (data != 0) {
System.out.println("\n");
System.out.println(new String(b));
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("client read exception!");
e.printStackTrace();
try {
bis.close();
sock.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
thread.start();
}
public void chatStart() {
Scanner scan = new Scanner(System.in);
BufferedOutputStream bos=null;
while (true) {
System.out.print("입력>>");
String msg = scan.nextLine();
try {
bos = new BufferedOutputStream(sock.getOutputStream());
bos.write(msg.getBytes("UTF-8"));
bos.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("client write exception!");
try {
bos.close();
sock.close();
break;
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Client client = new Client();
try {
client.connect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("connect exception");
}
client.read();
client.chatStart();
}
}
====> 결과
소켓이 close() 됐을 때의 예외처리는 무엇보다 중요하다.
반드시 예외를 잡고 처리해야한다.
시간이 없어서 빈약하게 처리했지만, 로직을 작성하는 것보다 메모리 누수 혹은 정확한 처리가 더 중요한 것 같다.
다음은 selector 와 asyncrhronousServerSocket에 대해 마지막으로 알아보자.
https://docs.oracle.com/javase/7/docs/api/java/nio/channels/AsynchronousServerSocketChannel.html
'programming > Java' 카테고리의 다른 글
# Enum (열거형) (0) | 2018.05.20 |
---|---|
# NIO - Selector (0) | 2018.05.19 |
# network, socket / 네트워크 교육과정 (3일차) (0) | 2018.03.22 |
# IO , Stream / 네트워크 교육과정 (2일차) (0) | 2018.03.19 |
# Thread / 네트워크 교육과정 (1일차) (0) | 2018.03.19 |