[책펌] Unicast (1:1 소켓 스레드) 프로그램 예제

By | 10월 21, 2008

* 개요

- Unicast 란? : 클라이언트와 서버간에 지속적으로 일대일로 통신하는 개념

* 구성

- UnicastServer.java
- UnicastServerThread.java
- UnicastClient.java

* Unicast 프로그램 예제 흐름

(1) 서버를 실행시키면 TCP서버소켓을 생성하게 된다.
(2) TCP서버소켓으로 accept()를 통해서 클라이언트의 통신을 기다린다.
(3) 클라이언트가 TCP소켓을 생성한다.
(4) 클라이언트의 TCP소켓이 생성되면 TCP서버소켓과 연결을 시도한다.
(5) TCP서버소켓이 클라이언트와 TCP연결이 이루어졌다면 (2)의 accept() 메서드에 의해 클라이언트와 통신할 수 있는 TCP소켓을 생성하게 된다.
(6) TCP소켓을 서버에게 전달한다.
(7) 서버에서는 스레드를 생성하여 TCP소켓을 계속 유지할 수 있도록 한다.
(8) 클라이언트에 있는 TCP소켓과 서버쪽에 있는 TCP소켓은 TCP/IP 계층을 통해서 TCP로 통신할 수 있는 상태가 된다.

UnicastServer.java

package socket.unicast;

import java.net.ServerSocket;
import java.io.IOException;
import java.net.Socket;

public class UnicastServer {

 private ServerSocket serverS;
 
//생성자
 public UnicastServer(int port){
  
  try{
   serverS = new ServerSocket(port);//서버소켓생성
  }catch(IOException ioe){
   ioe.printStackTrace();
   System.exit(0);
  }
 
  UnicastServerThread ust = null;
  
  while(true){
  
   System.out.println("클라이언트 대기중");
   Socket s = null;
   
   try{
    s = serverS.accept();
   }catch(IOException ioe){
    ioe.printStackTrace();
   }
  
   System.out.println("client ip : "+s.getInetAddress().getHostAddress());
   
//Runnable객체 UnicastServerthread에, 클라이언트와 연결된 소켓 s 를 인자로 넘기며 스레드를 시작한다.
    ust = new UnicastServerThread(s);
   Thread t = new Thread(ust);
   t.start();

  
  }
 
 }
 
 public static void main(String[] args){
  new UnicastServer(3000);
 }
 
}

UnicastServerThread.java

package socket.unicast;

import java.net.Socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

//TCP연결이 완료된 소켓객체를 잃어버리지 않기 위해서 소켓에 쓰고 읽는 부분을 스레드 처리하기 위한 클래스
//연결된 소켓객체를 인자로 받아서 스트림의 생성을 하고, run()메서드의 while 루프 안에서 읽고 쓰는 것을 반복한다.
public class UnicastServerThread implements Runnable{

 private Socket socket;
 private BufferedReader bufferR;
 private BufferedWriter bufferW;
 private InputStream is;
 private OutputStream os;
 
//생성자 - 소켓을 인자로 받아 멤버변수로 할당.
 public UnicastServerThread(Socket socket){
  this.socket = socket;
 }
 
 
 public void run(){
  
  boolean isStop = false;   //스레드 루프의 실행 및 중지에 관한 boolean
  
  try{
   is = socket.getInputStream();
   os = socket.getOutputStream();
   bufferR = new BufferedReader(new InputStreamReader(is));
   bufferW = new BufferedWriter(new OutputStreamWriter(os));
   
  }catch(IOException ioe){
   isStop = true;   //스트림 생성에 실패하면 스레드 루프를 중지한다.
  }
 
  try{

   while(! isStop){

    String message = bufferR.readLine();
    if(message.equals("exit")) isStop = true;
    System.out.println("received message : "+message);
    message += System.getProperty("line.separator");
    bufferW.write(message);
    bufferW.flush();
    
   }//end while
   
  }catch(IOException ioe){
   System.out.println("클라이언트가 강제로 종료되었습니다.");
   isStop = true;   //클라이언트가 exit 메세지 없이 임의로 종료해도 스레드가 종료되도록 설정
  }finally{
   try{
    if(bufferR!=null)bufferR.close();
    if(bufferW!=null)bufferW.close();
    if(socket!=null)socket.close();
   }catch(IOException ioe){
    ioe.printStackTrace();
   }
  }//end finally
  
 }//end run()
 
 
}

UnicastClient.java

package socket.unicast;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.io.IOException;

public class UnicastClient {

 private String ip;
 private int port;
 private String message;
 private BufferedReader file = null;
 private BufferedReader bufferR = null;
 private BufferedWriter bufferW = null;
 
 public UnicastClient(String ip, int port)throws IOException{
  
  this.ip = ip;
  this.port = port;
  boolean isStop = false;   //while 루프의 실행 및 중지에 관한 boolean

//소켓을 만들어 리턴하는 사용자 메서드, 호스트(서버)의 정보를 넣은 클라이언트 소켓이 만들어지면 호스트의 accept()메서드가 반응하여 TCP소켓연결이 완성된다.
  Socket tcpsocket = getSocket();   
  OutputStream os = tcpsocket.getOutputStream();
  InputStream is = tcpsocket.getInputStream();
  bufferW = new BufferedWriter(new OutputStreamWriter(os));
  bufferR = new BufferedReader(new InputStreamReader(is));

  while(! isStop){
   
   System.out.print("message : ");
   file = new BufferedReader(new InputStreamReader(System.in));   //사용자 키보드 입력
   message = file.readLine();
   message += System.getProperty("line.separator");
   bufferW.write(message);
   bufferW.flush();   //사용자 메세지 전송

   message = bufferR.readLine();
   if(message.equals("exit")){   //서버에서 넘어온 문자열이 exit 인 것을 감지하면 루프 종료 처리
    isStop = true;
    System.out.println("종료되었습니다.");
   }else{
    System.out.println("Received message : "+message);
   }
   
  }//end while
  
  tcpsocket.close();
  bufferW.close();
  bufferR.close();
  file.close();
  
 }//end 생성자.

 
 public Socket getSocket(){
  
  Socket tcpsocket = null;
  
  try{
   tcpsocket = new Socket(ip, port);
  }catch(IOException ioe){
   ioe.printStackTrace();
   System.exit(0);
  }
  return tcpsocket;
 }
 

 public static void main(String[] args)throws IOException{
  new UnicastClient("localhost", 3000);
 }
 
}

- 출처 : [한빛미디어] 자바 5.0 프로그래밍 -

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments