08. TCP 프로그래밍 03. 멀티스레드를 이용한 에코 서버

03. 멀티스레드를 이용한 에코 서버

1. 멀티스레드 에코 서버 프로그래밍

import java.net.*;
import java.io.*;

public class EchoThreadServer {
    public static void main(String[] args){
        try {
            ServerSocket server = new ServerSocket(10001);
            System.out.println("접속을 기다립니다.");
            while(true){
                Socket socket = server.accept();
                EchoThread ethr = new EchoThread(socket);
                ethr.start();
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

class EchoThread extends Thread{
    private Socket sock;
    public EchoThread(Socket socke){
        this.sock = socke;
    }
    public void run(){
        try{
            InetAddress inetAddr = sock.getInetAddress();
            System.out.println(inetAddr.getHostAddress() + "로 부터 접속했습니다.");
            OutputStream out = sock.getOutputStream();
            InputStream in = sock.getInputStream();
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
            String line = null;
            while((line = br.readLine()) != null){
                System.out.println("클라이언트로부터 전송받은 문자열 : "+line);
                pw.println(line);
                pw.flush();
            }
            pw.close();
            br.close();
            sock.close();
        }catch(Exception ex){
            System.out.println(ex);
        }
    }
}

05. ChatServer, Client

import java.net.*;
import java.io.*;
import java.util.*;

public class ChatServer {
    public static void main(String[] args) {
        try {
            ServerSocket server = new ServerSocket(10001);
            System.out.println("접속을 기다립니다.");
            HashMap hm = new HashMap();
            while(true) {
                Socket sock = server.accept();
                ChatThread chatthread = new ChatThread(sock, hm);
                chatthread.start();
            }
        }catch(Exception e) {
            System.out.println(e);
        }
    }
}

class ChatThread extends Thread {
    private Socket sock;
    private String id;
    private BufferedReader br;
    private HashMap hm;
    private boolean initFlag = false;
    public ChatThread(Socket sock, HashMap hm) {
        this.sock = sock;
        this.hm = hm;
        try {
            PrintWriter pw = new PrintWriter (new OutputStreamWriter(sock.getOutputStream()));
            br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            id = br.readLine();
            broadcast(id + "님이 접속했습니다.");
            System.out.println("접속한 사용자의 아이디는 "+id+"입니다.");
            synchronized(hm) {
                hm.put(this.id, pw);
            }
            initFlag = true;
        }catch(Exception ex) {
            System.out.println(ex);
        }
    }

    public void run() {
        try{
            String line = null;
            while((line = br.readLine()) != null) {
                if(line.equals("/quit")) break;
                if(line.indexOf("/to ") == 0){
                    sendmsg(line);
                } else {
                    broadcast(id+" : "+line);
                }
            }
        }catch(Exception ex) {
            System.out.println(ex);
        }finally{
            synchronized(hm){
                hm.remove(id);
            }
            broadcast(id + " 님이 접속 종료했습니다.");
            try{
                if(sock != null) sock.close();
            }catch(Exception ex){}
        }
    }

    public void sendmsg(String msg){
        int start = msg.indexOf(" ") +1;
        int end = msg.indexOf(" ", start);

        if(end != -1) {
            String to = msg.substring(start, end);
            String msg2 = msg.substring(end+1);
            Object obj = hm.get(to);
            if(obj != null){
                PrintWriter pw = (PrintWriter) obj;
                pw.println(id + " 님이 다음의 귓속말을 보내셨습니다 : "+msg2);
                pw.flush();
            }
        }
    }

    public void broadcast(String msg){
        synchronized(hm) {
            Collection collection = hm.values();
            Iterator iter = collection.iterator();
            while(iter.hasNext()){
                PrintWriter pw = (PrintWriter)iter.next();
                pw.println(msg);
                pw.flush();
            }
        }
    }
}
import java.net.*;
import java.io.*;

public class ChatClient {
    public static void main(String[] args){
        if(args.length != 2){
            System.out.println("사용법 : java ChatClient id 접속할 서버 ip");
            System.exit(1);
        }

        Socket sock = null;
        BufferedReader br = null;
        PrintWriter pw = null;
        boolean endflag = false;
        try{
            sock = new Socket(args[1], 10001);
            pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
            br = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));

            pw.println(args[0]);
            pw.flush();

            InputThread it = new InputThread(sock, br);
            it.start();
            String line = null;
            while((line = keyboard.readLine()) != null){
                pw.println(line);
                pw.flush();
                if(line.equals("/quit")){
                    endflag = true;
                    break;
                }
            }
            System.out.println("클라이언트의 접속을 종료합니다.");
        }catch(Exception ex) {
            if(!endflag){
                System.out.println(ex);
            }
        }finally{
            try{
                if(pw != null) pw.close();
            }catch(Exception ex){}
            try{
                if(br != null) br.close();
            }catch(Exception ex){}
            try{
                if(sock != null) sock.close();
            }catch(Exception ex){}
        }
    }
}

class InputThread extends Thread {
    private Socket sock = null;
    private BufferedReader br = null;
    public InputThread(Socket sock, BufferedReader br){
        this.sock = sock;
        this.br = br;
    }

    public void run() {
        try{
            String line = null;
            while((line = br.readLine()) != null) {
                System.out.println(line);
            }
        }catch(Exception ex){
        }finally{
            try{
                if(br != null) br.close();
            }catch(Exception ex) {}
            try{
                if(sock != null) sock.close();
            }catch(Exception ex) {}
        }
    }
}

출처 : 김성박 송지훈 공저, 『 자바 IO & NIO 네트워크 프로그래밍』, 한빛미디어(2004.9.30), 8장 인용.