Dev/Java

[java] 채팅프로그램 만들기

창문닦이 2019. 1. 31. 13:46

챗팅 프로그램을 만들기 위해 awt를 사용할 것이다. 먼저 간단한 예제 소스를 통해 구현해보자.

Test1 : 액션 리스너를 구현한 예제 클래스.

package com.day18;

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.TextField;
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.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

public class Test1 extends Frame implements ActionListener{

	private static final long serialVersionUID = 1L;
	private TextField tf;
	private TextArea ta;
	
	/**
	 * 생성자. ActionListener 설정 
	 */
	public Test1(){
		
		ta = new TextArea();
		add(ta);
		
		tf = new TextField();
		tf.addActionListener(this);
		add(tf,BorderLayout.NORTH);
		
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		setTitle("HTML Viewer");
		setSize(400,300);
		setVisible(true);
		
	}
	
	/**
	 * 자바 실행 시 객체 생성 
	 */
	public static void main(String[] args) {
		new Test1();
	}

	/**
	 * 버튼 클릭 시 수행되는 메소드. 입력한 url의 데이터를 읽어와서 출력 
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		//https://www.naver.com : URL 
		//www->호스트, naver.com->도메인
		
		try {
			String str;
			URL url = new URL(tf.getText());//tf에 사용자가 입력한 값을 url로 가져옴
			
			ta.setText("");//기존데이터 초기화
			
			InputStream is = url.openStream();//url로 가서 들어오는 스트림을 inputstream에 다시 담아두겠다.
			BufferedReader br = new BufferedReader(new InputStreamReader(is));//네트워크로 들어오는 데이터를 1byte씩 읽어서 br에 할당
			
			while((str=br.readLine())!=null){
				if(ta.getText().equals(null)){
					ta.setText(str);
				}else{
					ta.setText(ta.getText() + "\r\n" +str);//기존 텍스트를 읽어와서 누적해서 출력해라 append와 동일
				}
			}
			is.close();
		} catch (Exception e2) {
			e2.printStackTrace();
		}
		
	}
}

Test1 클래스를 실행하여 조회되는 뷰어

 


일대일 채팅 프로그램

ClientTest : 채팅 시스템에 접속하는 클라이언트 클래스이다.

ServerTest : 채팅 서버 클래스.

package com.day18;

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.TextField;
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.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientTest extends Frame implements ActionListener, Runnable{//다중 인터페이스 

	private static final long serialVersionUID = 1L;
	private TextArea ta = new TextArea();
	private TextField tf = new TextField();
	
	//클라이언트는 소켓만 필요
	private Socket sc = null;
	private int port = 5555;
	private String host="127.0.0.1";//me, loopback주소, 네트워크에서 자기자신을 의미하는 특별한 주소
	
	/**
	 * 기본 생성자를 통해 ActionListener의 기본값을 설정한다.
	 */
	public ClientTest(){
		
		add(ta,BorderLayout.CENTER);
		add(tf,BorderLayout.SOUTH);
		
		//텍스트입력창에 리스너
		tf.addActionListener(this);
		
		//종료
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		
		setTitle("채팅클라이언트");
		setSize(300,400);
		setVisible(true);
	}
	
	/**
	 * 어플리케이션이 구동되면 main문을 가장 먼저 찾아가게 되고 연결 메소드을 실한다. 
	 */
	public static void main(String[] args) {
		new ClientTest().connect();
	}

	/**
	 * 설정한 포트번호와 아이피 주소로 소켓을 생성한다. 자기자신을 스레드 객체로 생성하여 run을 호출한다.
	 */
	public void connect(){

		try {
			sc = new Socket(host, port);
			Thread th = new Thread(this);//채팅시 시작하라고 스레드 설정
			th.start();
			
		} catch (Exception e) {
			ta.append("서버가 죽어있다!!");
		}
	}
	
	/**
	 * 메세지를 전송한다.
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		
		//채팅창 데이터를 보낼 때 사용
		String str = tf.getText();
		if(str.trim().equals("")){//공백제거 후 문자열 값이 null이면 보내지마라
			return;
		}
		
		if(sc==null){
			return;
		}
		
		try {
			OutputStream os = sc.getOutputStream();
			PrintWriter pw = new PrintWriter(os,true);//여기서 true는 auto flush에 해당
			pw.println("[클라이언트]" + str);
			
			ta.append("\r\n[클라이언트]" + str);
			tf.setText("");
			tf.requestFocus();
			
		} catch (Exception e2) {//데이터를 보내다가 에러 발생시
			ta.append("\r\n 서버와 연결 종료!!");
			sc = null;//클라이언트는 소켓만 사용. 소켓만 초기화
		}
	}
	
	/**
	 * 메세지를 수신한다.
	 */
	@Override
	public void run() {
		
		//스레드는 채팅창 데이터를 받을 때 사용
		String str;
		try {
			
			if(sc==null){//소켓이 null이면 클라이언트가 접속을 안한 상태
				return;
			}
			InputStream is = sc.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			ta.append("\r\n 접속!");//줄바꿈작업+사용자접속알림
			
			while((str=br.readLine())!=null){
				ta.append("\r\n" +str);
			}
		} catch (Exception e) {
			ta.append("\r\n 서버 연결 종료!");			
			//소켓 초기화
			sc = null; 
		}
	}
}
package com.day18;

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.TextField;
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.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerTest extends Frame implements ActionListener, Runnable{//다중인터페이스 
	
	private static final long serialVersionUID = 1L;
	private TextArea ta = new TextArea();
	private TextField tf = new TextField();
	
	//서버는 서버소켓과 소켓 둘다 필요
	private ServerSocket ss = null;
	private Socket sc = null;
	//Socket에 담겨서 전달해야 하는 정보 : 서버ip, 내ip, data, port
	//Port번호 0~65535. 0~2000은 대부분 OS에서 사용
	//TCP-IP는 상대편의 IP를 반드시 받아오게 되어있음
	
	/**
	 * 생성자. ActionListener 설정 
	 */
	public ServerTest(){
		
		add(ta,BorderLayout.CENTER);
		add(tf,BorderLayout.SOUTH);
		
		//텍스트입력창에 리스너
		tf.addActionListener(this);
		
		//종료
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		
		setTitle("채팅서버");
		setSize(300,400);
		setVisible(true);
	}
	
	/**
	 * 어플리케이션이 구동되면 main문을 가장 먼저 찾아가게 되고 serverStart메소드을 실행한다. 
	 */
	public static void main(String[] args) {
		new ServerTest().serverStart();
	}
	
	/**
	 * 소켓 생성 및 클라이언트의 요청을 기다린다. 소켓이 생성되면 Thread에 할당한다.
	 */
	public void serverStart(){
		
		try {
			ss = new ServerSocket(5555); //서버포트번호
			ta.setText("서버시작!!");
			
			//클라이언트가 접속을 해야 움직임. 접속전까지 딜레이 상태
			sc = ss.accept(); //accept(): 서버소켓과 소켓을 연결
			
			Thread th = new Thread(this);//채팅시 시작하라고 스레드 설정
			th.start();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 채팅창 데이터를 전송한다.  
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		String str = tf.getText();
		if(str.trim().equals("")){//공백제거 후 문자열 값이 null이면 보내지마라
			return;
		}
		
		if(sc==null){
			return;
		}
		
		try {
			OutputStream os = sc.getOutputStream();
			PrintWriter pw = new PrintWriter(os,true);//여기서 true는 auto flush에 해당. flush는 enter를 만나야 함 
			pw.println("[서버]" + str);
			
			ta.append("\r\n [서버] " + str);
			tf.setText("");
			tf.requestFocus();
			
		} catch (Exception e2) {//데이터를 보내다가 에러 발생시
			ta.append("\r\n 클라이언트와 연결 종료!!");
			sc = null;//데이터 전송시 소켓만 사용하므로 소켓만 초기화
		}
	}
	
	/**
	 * 채팅창 데이터를 수신한다.	
	 */
	@Override
	public void run() {
		String str;
		String ip;
		
		try {
			if(sc==null){//소켓이 null이면 클라이언트가 접속을 안한 상태
				return;
			}
			
			InputStream is = sc.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			ip = sc.getInetAddress().getHostAddress();//client IP
			
			ta.append("\r\n["+ip+"] 접속!");//줄바꿈작업+사용자접속알림
			
			while((str=br.readLine())!=null){
				ta.append("\r\n" +str);
			}
			
		} catch (Exception e) {
			ta.append("\r\n 클라이언트 연결 종료!");
		
			//네트워크에서 소켓들 초기화 진행 하지않으면 쓰레기값 들어있음.  
			sc = null; 
			ss = null;
		}
	}
}

 


다대다 채팅 프로그램

ChatCS : 같은 가상 아이피와 호스트를 가진 사용자를 모아 다수 채팅을 할 수 있도록 제공하는 클래스이다.

MultiServerTest : 여러명이 메세지를 주고 받을 수 있는 채팅 멀티서버 클래스

package com.day18;

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

//UDP(근거리 통신망에서 사용. 프로토콜)
//인트라넷 IP
//IP:32bit 주소체제
//A,B,C class 
//D class(224.0.0.0 ~ 239.255.255.255): IP 똑같이 세팅해도 충돌안남. 인터넷연결x이기 때문
public class ChatCS extends Frame implements Runnable,ActionListener{

	private static final long serialVersionUID = 1L;
	private MulticastSocket ms = null;
	private InetAddress xGroup = null;
	
	private String host = "230.0.0.1";
	private int port = 7777;
	private String userName = "사용자이름";
	
	private TextArea ta = new TextArea();
	private TextField tf = new TextField();
	
	//DatagramSocket : UDP로 데이터그램 패킷을 전송하거나 수신
	//DatagramPacket : UDP를 이용하여 전송될 수 있는 데이터
	//MulticastSocket : 다수의 클라이언트에 데이터그램 전송	
	//MulticastSocket : 서버에서 파일이나 데이터베이스에서 정보를 특정위치에 내려주면 클라이언트가 그 쪽으로 접속해서 받아감
	
	/**
	 * 기본생성자를 통해 채팅할 때의 틀을 만든다.
	 */
	public ChatCS(){
		
		ta.setEditable(false);//수정 불가능.읽기 가능
		add(ta,BorderLayout.CENTER);
		add(tf,BorderLayout.SOUTH);
		tf.addActionListener(this);
		
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		
		setTitle("그룹채팅");
		setSize(400,400);
		setVisible(true);
		tf.requestFocus();
	}
	
	/**
	 * 동일한 아이피와 포트번호로 접속한 사용자들을 모은다. 
	 */
	public void setup(){
		
		try {
			xGroup = InetAddress.getByName(host);//DNS로 가서 IP주소를 받아 xGroup에 할당 
			ms = new MulticastSocket(port);
			
			//특정 그룹에 포함
			ms.joinGroup(xGroup);//230.0.0.1 ip를 쓰면서 포트번호 7777을 사용한 사람을 모음
			
			Thread th = new Thread(this);
			th.start();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 연결 종료 
	 */
	public void disConnection(){
		
		try {
			ms.leaveGroup(xGroup);//그룹에서 나오게 연결 끊음
			ms.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 어플리케이션이 구동되면 main문을 가장 먼저 찾아가게 되고 챗팅 셋업을 시작한다. 
	 */
	public static void main(String[] args) {
		new ChatCS().setup();
	}

	
	/**
	 * 메세지 전송한다.
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		String str = tf.getText().trim();//읽어오면서 공백제거
		
		if(str.equals("")){
			return; //보낼 메세지가 없으면 중단한다.
		}
		
		byte[] buffer = (userName+"]"+str).getBytes();//문자열이므로 배열 buffer에 넣기위해 형변환
		
		try {
			DatagramPacket dp = new DatagramPacket(buffer, buffer.length, xGroup, port);//버퍼에 있는 내용을 그 길이만큼 xGroup(host), port로 전송
			ms.send(dp);
			tf.requestFocus();
			tf.setText("");
			tf.requestFocus();
			
		} catch (Exception e2) {
			System.out.println(e.toString());
		}
	}

	/**
	 * 메세지를 수신한다.
	 */
	@Override
	public void run() {
		try {
			//사용자의 요청이 있기전까지 채팅이 유지되므로 무한 루프. 
			while(true){
				byte[] buffer = new byte[512];
				DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
				ms.receive(dp);
				String str = new String(dp.getData()).trim();
				ta.append(str + "\r\n");
			}
			
		} catch (Exception e) {
			System.out.println(e.toString());
			disConnection();//수신 중 exception 발생해서 연결 종료
		}
	}
}
package com.day18;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class MultiServerTest {

	// 클라이언트가 접속한 소켓을 담을 저장소
	private List<Socket> client = new ArrayList<Socket>();
	
	/**
	 * 소켓 생성 및 클라이언트의 요청을 기다린다. 소켓이 생성되면 WorkThread에 할당한다.
	 */
	public void serverStart(){		
		try (//포트 설정 및 서버 소켓 객체 생성.
			ServerSocket serverSocket = new ServerSocket(5555);) {		
			System.out.println("서버시작...");
			
			while(true){//몇 명이 접속할지 모르니 무한루프
				Socket socket = serverSocket.accept();//클라이언트가 접속되어있으면 진행, 소켓 생성. 접속을 안하면 딜레이 상태이므로 무한루프.
				WorkThread wt = new WorkThread(socket);//인원수만큼 소켓 생성하듯이, 스레드도 인원수만큼 만들어줌. 사람들이 말할때마다 스레드 번갈아 실행
				wt.start();//스레드 시작
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 메세지 송수신 작업을 수하는 스레드 객체 
	 */
	class WorkThread extends Thread{
		
		private Socket sc;				//소켓 초기화
		public WorkThread(Socket sc){	//오버로딩된 생성자
			this.sc = sc;
		}
		
		@Override
		public void run() {
			String ip = null;
			String msg = null;

			try {

				BufferedReader br = new BufferedReader(new InputStreamReader(sc.getInputStream()));
				ip = sc.getInetAddress().getHostAddress();//ip와 호스트 읽어옴
				client.add(sc);//리스트에 사용자의 소켓을 저장
				
				//입장알림
				msg = ip +"]가 입장 했습니다!";
				for(Socket s: client){//사용자가 입장했다는 메세지를 모든 사용자에게 msg 알려야 함 
					if(s==sc){//꺼낸 소켓이 자신과 동일?
						continue;//이번만 통과
					}
					PrintWriter pw = new PrintWriter(s.getOutputStream(),true);//boolean autoFlush. 동일하지 않으면 출력
					pw.println(msg);
				}
				//서버에도 입장알림
				System.out.println(msg);
				
				//대화 : 스레드가 실행하기 때문에 절대 겹치지 않음
				while((msg=br.readLine())!=null){
					
					for(Socket s: client){//채팅시 자신을 제외한 사람들에게 보여야 함
						if(s==sc){//꺼낸 소켓이 자신과 동일?
							continue;//이번만 통과
						}
						PrintWriter pw = new PrintWriter(s.getOutputStream(),true);//boolean autoFlush
						pw.println(msg);
					}
					System.out.println(msg);//서버에도출력
				}
			
			} catch (Exception e) {
				
				//퇴장(연결끊김)
				msg = ip +"]가 퇴장 했습니다!";
				try {
					for(Socket s: client){
						if(s==sc){
							continue;
						}
						PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
						pw.println(msg);
					}
					System.out.println(msg);//서버에도출력
					sc =null;//퇴장했으니 소켓 초기화. 그래야 다음번에 연결 가능

				} catch (Exception e2) {
					// TODO: handle exception
				}
			}
		}
		
	}

	/**
	 * 어플리케이션이 구동되면 main문을 가장 먼저 찾아가게 되고 serverStart메소드을 실행한다. 
	 */
	public static void main(String[] args) {
		new MultiServerTest().serverStart();
	}

}

파일 전송 프로그램

FileInfo : 파일을 전송할 때, 파일 관련 정보를 담는 객체이다.

FileClientTest : 파일을 전송하고자 하는 클라이언트 객체이다.

FileServerTest : 서버 소켓을 생성하고 요청이 들어올 때 까지 대기한다. 소켓이 전달되면 스트림 데이터 읽은 후 파일 생성을 진행하는 서버 클래스.

package com.day18;

import java.io.Serializable;

// 데이터를 주고 받기 위해서 직렬화 반드시 필요하다.
public class FileInfo implements Serializable{

	private static final long serialVersionUID = -7601500689412887280L;

	/*	
	 * 응답 결과를 주고 받는 code (개발자가 응답상태에 대하여 협의하여 정의한 코드)
	 * 100 : 파일전송 시작(파일명 전송)
	 * 110 : 파일 내용을 전송
	 * 200 : 파일전송 종료(파일명 전송)
	 * size : 한번에 전송하는 크기
	 * data : 내용
	 * */	
	private int code;
	private int size;
	private byte[] data = new byte[1024];//한번에 전송가능한 데이터의 양은 1024byte로 설정
	
	public int getCode() {
		return code;
	}
	public void setCode(int code) {
		this.code = code;
	}
	public int getSize() {
		return size;
	}
	public void setSize(int size) {
		this.size = size;
	}
	public byte[] getData() {
		return data;
	}
	public void setData(byte[] data) {
		this.data = data;
	}	
}

 

package com.day18;

import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;

// 파일을 전송하고자 하는 클라이언트 클래스
// [클라이언트] fis 파일읽기 > oos 직렬화 >>> 전송 >>> [서버] ois 역직렬화 > fos파일생성
public class FileClientTest {

	public static void main(String[] args) {
		
		int port = 5555;
		String host = "127.0.0.1";// 자신 ip를 써줘도 된다.
		
		Socket sc = null;		
		ObjectOutputStream oos = null;
		Scanner scn = new Scanner(System.in);
		String file;
		
		try {
			
			// 1. 전송할 파일경로를 입력 받는다.
			System.out.print("전송할 파일 경로명? :");	// d:\\doc\\test.txt
			file = scn.next();
			File f = new File(file);
			
			// 2. 파일 존재 여부 확인
			if(!f.exists()){
				System.out.println("파일이 없습니다.");
				System.exit(0);
			}
			
			// 3. 전송을 위한 소켓 및 스트림 생성
			sc = new Socket(host, port);
			oos = new ObjectOutputStream(sc.getOutputStream());
			oos.flush();
			
			// 전송하는 파일과 관련된 정보를 담는 클래스 객체 생성
			FileInfo info = new FileInfo();
			info.setCode(100);
			info.setData(f.getName().getBytes());//파일의 이름을 받을 때 byte단위로 받아야 함
			info.setSize((int)f.length());
			oos.writeObject(info);// 명시된 fileinfo 객체를 ObjectOutputStream 으로 작성한다. 네트워크를 통해 파일 저장한 것
			
			System.out.println(f.getName() + "파일 전송 시작!!");
			Thread.sleep(300);//한번에 내보내지 않고 중간에 휴식. 처리되는 과정을 확인하기 위함.
			
			// 4. 파일 내용 전송
			FileInputStream fis = new FileInputStream(f);//클라이언트에서는 읽어서 보내는게 필요
			
			int data = 0 ;
			byte[] buffer = new byte[1024];
			
			while((data=fis.read(buffer,0,1024))!=-1){//1024 -> buffer.length와 같음
				
				info = new FileInfo();
				
				info.setCode(110);
				info.setData(buffer);
				info.setSize(data);
				
				System.out.println(data + "bytes 전송중.....");
				oos.writeObject(info);//파일 object로 내보냄
				
				buffer = new byte[1024];//버퍼에 있는 내용이 사라짐. 사용 후 새로만듦
				Thread.sleep(300);
			}
			// 5. 파일 전송 종료
			fis.close();
			
			// 6. 파일 전송 종료를 알리기 위한 FileInfo 클래스 전송
			info = new FileInfo();//FileInfo 클래스 재할당 
			info.setCode(200);
			info.setData(f.getName().getBytes());
			info.setSize((int)f.length());		
			oos.writeObject(info);
			
			System.out.println(f.getName() + "파일 전송 종료!!");
			Thread.sleep(300);
			
			oos.close();
			scn.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
package com.day18;

import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

//스트림 데이터 읽은 후 파일 생성을 진행하는 서버 클래스 
//직렬화된 데이터를 전송하므로 ObjectOutputStream, ObjectInputStream 필요(Serializable 필수)
//네트워크에서 데이터를 보낼 때는 getInputStream, getOutputStream 메소드 활용
public class FileServerTest {

	/**
	 * 파일을 수신하는 작업을 하는 스레드 객체 
	 */
	class WorkThread extends Thread {// 내부 클래스. 이너 클래스 
	
		// 멤버변수로 소켓을 가진다. 
		private Socket sc = null;

		// 생성자 
		public WorkThread(Socket sc){
			this.sc = sc;
		}
		
		// WorkThread.start() 시 작업을 수행한다.
		@Override
		public void run() {
		
			try {
				
				ObjectInputStream ois = new ObjectInputStream(sc.getInputStream());//소켓의 InputStream을 넣어줌
				System.out.println(sc.getInetAddress().getAddress() + "접속....");
				FileOutputStream fos = null; //서버에서는 파일을 생성하기 위해서 FileOutputStream 필요
				Object ob = null;
				
				while((ob=ois.readObject())!=null){
					
					if(ob instanceof FileInfo){
						FileInfo info = (FileInfo)ob;//downcast

						// 100 : 파일전송 시작(파일명 전송)
						if (info.getCode()==100) {
							String str =new String(info.getData());
							fos = new FileOutputStream(str);//파일명
							
							System.out.println(str + "파일 전송 시작!!");
						
						}
						// 110 : 파일 내용을 전송
						else if (info.getCode()==110) {
							if(fos==null)
								break;//파일없으면 중지
							
							fos.write(info.getData(), 0 ,info.getSize());//파일을 내보냄. 0~사이즈만큼
							
							System.out.println(info.getSize() + "bytes 받는 중...");
						
						}
						// 200 : 파일전송 종료(파일명 전송)
						else if(info.getCode()==200) {
							if(fos==null)
								break;
							String str = new String(info.getData());//data에는 파일명 있음
							fos.close();
							System.out.println(str + "파일 전송 끝");
						}
					}
					
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 소켓 생성 및 클라이언트의 요청을 기다린다. 소켓이 생성되면 WorkThread에 할당한다.
	 */
	public void serverStart(){
	
		try (//포트 설정 및 서버 소켓 객체 생성.
			ServerSocket serverSocket = new ServerSocket(5555); 
			//클라이언트의 요청이 있는지 listen 하는 상태가 된다. 연결이 유지되는 동안 소켓을 생성한다.
			Socket socket = serverSocket.accept();) {
			
			System.out.println(">> 파일 서버 시작");
			WorkThread wt = new WorkThread(socket);
			wt.start();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 어플리케이션이 구동되면 main문을 가장 먼저 찾아가게 되고 serverStart메소드을 실한다. 
	 */
	public static void main(String[] args) {
		new FileServerTest().serverStart();
	}

}