반응형
SMALL


지난번 포스팅에서 간단한 서버를 구현해보았다. 하지만 서버라는것은 저렇게 하나만 간단히 돌아가는 것이 아니다. 항상 많은 서버들이 맞물려서 돌아가게 되기 마련이다. 그러기때문에 지난번에 했던 서버 내용을 기본으로 이번에는 Dispatcher에 여러 protocol을 넣어서 서버를 구현해보았다. 이번에 만들고자 하는 서버의 구성은 다음과 같다.



1.  Server1이라는 프로젝트를 만들고 그 안에 Serverinitializer class를 만들고 다음과 같이 코      딩해준다.


import java.io.IOException;

import java.net.ServerSocket;



public class Serverinitializer 

{


public static void main(String[] args

{

int port = 5000;

System.out.println("Server ON :" + port);

try

{


ServerSocket serverSocket = new ServerSocket(port);


Dispatcher dispatcher = new Dispatcher();


while (true)

{

      dispatcher.dispatch(serverSocket);

}

}

catch (IOException e)

{

    e.printStackTrace();

}

}


}


2.  Dispatcher이라는 class를 만들고 다음과 같이 코딩한다.

import java.io.IOException;

import java.io.InputStream;

import java.net.ServerSocket;

import java.net.Socket;


public class Dispatcher 

{

   private final int HEADER_SIZE = 6; -> "0X5001"은 헤더 6글자를 의미(헤더설정)

   public void dispatch(ServerSocket serverSocket)

{

  try

  {

  Socket socket = serverSocket.accept();

  demultiplex(socket);

  }

  catch (IOException e)

  {

     e.printStackTrace();

  }

 }


   public void demultiplex(Socket socket) ->Dispatcher에서 받아들인 데이터를 분배해주는 것이 demultiplex다.

   {

   try

   {

      InputStream inputStream = socket.getInputStream();


      byte[] buffer = new byte[HEADER_SIZE];

      inputStream.read(buffer);

      String header = new String(buffer); -> 헤더사이즈만큼 받아온다.



     switch (header) -> 전체적으로 헤더를 2개로 나누어서 표현한것이다.(이것이 프로토콜)

     {

     case "0X5001":

          StreamSayHelloProtocol sayHelloProtocol = new StreamSayHelloProtocol();

          sayHelloProtocol.handleEvent(inputStream); -> "0x5001이면 sayHelloProtocol 실행

          break;

     case "0X6001":

          StreamUpdateProfileProtocol updateProtocol = new StreamUpdateProfileProtocol();

          updateProtocol.handleEvent(inputStream); -> 0x6001이면 updateProtocol  실행

          break;

    }

}

    catch (IOException e)

   {

       e.printStackTrace();

   }

  }

}


2. StreamSayHelloProtocol 이름으로 class를 생성하고 다음과 같이 코딩한다.

import java.io.IOException;

import java.io.InputStream;

import java.util.StringTokenizer;


public class StreamSayHelloProtocol 

{

    private static final int DATA_SIZE = 512; -> ex) 홍길동|26 여기서 최대로 쓸수 있는 사이즈는 512

    private static final int TOKEN_NUM = 2;-> 위 예에서 데이터 종류는 2개

    public void handleEvent(InputStream inputStream)

{

  try 

  {

      byte[] buffer = new byte[DATA_SIZE];

      inputStream.read(buffer);

      String data = new String(buffer);


      String[] params = new String[TOKEN_NUM];

      StringTokenizer token = new StringTokenizer(data, "ㅣ"); ->데이터 512를 받아온다음 StringTokenizer를 이용                                                                                                     해서 파이프(|)를 파싱함

      int i = 0;

      while (token.hasMoreTokens())

      {

         params[i] = token.nextToken();

         ++i;

      }

 }

   catch (IOException e)

  {

      e.printStackTrace();

  }

 }

   private void sayHello(String[] params) 

   {

       System.out.println("SayHello -> name : " +params[0] + "age : "+params[1]);

   }

 } 

3. 이번엔 또다른 하나의 프로토콜인 StreamUpdateProfileProtocol이름으로 class를 생성하고 다음과 같이 코딩한다.


import java.io.IOException;

import java.io.InputStream;

import java.util.StringTokenizer;


public class StreamUpdateProfileProtocol 

{

   private static final int DATA_SIZE = 1024;

   private static final int TOKEN_NUM = 5;

   public void handleEvent(InputStream inputStream)

   {

   try 

   {

      byte[] buffer = new byte[DATA_SIZE];

      inputStream.read(buffer);

      String data = new String(buffer);

      String[] params = new String[TOKEN_NUM];

      StringTokenizer token = new StringTokenizer(data, "ㅣ");

      

      int i = 0;

      while (token.hasMoreTokens())

      {

          params[i] = token.nextToken();

          ++i;

      }

           updateProfile(params);

      }

      catch (IOException e)

      {

          e.printStackTrace();

      }

  }


private void updateProfile(String[] params

{

      System.out.println("UpdateProfile ->" +

            " id :" + params[0] +

            " password : " +params[1] +

            " name :" + params[2] +

            " age :" + params[3] +

            " gender: " + params[4]);

  }

}


전체적인 구조는 앞서 코딩한 2번과 유사하다. 단지 차이점이라고 하면 데이터사이즈와 데이터 최대종류가 달라졌다는 것이고, param구조를 이용해 출력내용을 조금 더 추가했다는 점이다.


4. 마지막으로 TestClient class를 생성하고 다음과 같이 코딩한다.


import java.io.IOException;

import java.io.OutputStream;

import java.net.Socket;

import java.net.UnknownHostException;


public class TestClient {


public static void main(String[] args

{

   System.out.println("Client ON");

   try

   {

      String message;

      Socket socket = new Socket("127.0.0.1", 5000);

      OutputStream out = socket.getOutputStream();

      message = "0x5001|이건주|26";

      out.write(message.getBytes());

      socket.close();


      Socket socket2 = new Socket("127.0.0.1", 5000);

      OutputStream out2 = socket2.getOutputStream();

      message = "0x6001|Lee|1234|이건주|26|남성";

      out2.write(message.getBytes());

      socket2.close();

    } 

    catch (UnknownHostException e)

    {

        e.printStackTrace();

    } 

    catch (IOException e)

   {

       e.printStackTrace();

   }

  }

}


5. 최종적으로 클라이언트를 만든것이다. 이제 이 상태에서 RUNAS를 해주면 다음과 같이 화면에 출력된다.



앞서 포스팅에도 이야기 했듯 사용중인 서버목록을 확인한 후 서버를 닫아주고 나서 실행해야 올려놓은 화면과 같이 출력이 되게된다.


반응형
LIST

'Server > Server의 기초' 카테고리의 다른 글

nio java를 이용한 에코서버 만들기  (0) 2016.08.12
서버의 전체적인 그림  (0) 2016.08.10
Dispatcher  (0) 2016.08.07
블로그 이미지

만년필석사

,