반응형

'전체 글'에 해당되는 글 212건

반응형
반응형

컴퓨터에는 여러가지 지식들이 있다. 사실 컴퓨터라는 세계는 끝이 안보이는 미지의 세계일 수도 있지만 모든걸 다 안다기 보다는 그래도 컴퓨터 전공자들이 개발을 하던지, 보안을하던지 등간에 꼭 알아야할 것들이 몇가지가 있다. 지금 그걸 몇가지 소개해보려고 한다.


1. 하드디스크 = ARM 작동될 때 기계로 하는 방식보다 (전기) 하는 방식이 훨씬 빠르기  때문에 컴퓨터 부팅속도                          도  빨라진다.

 -> 당연히 이렇게 될 수 밖에없다. 이 세상에서 가장 빠른건 빛밖에 없기 때문에  빛의 속도로 하드디스크에 접근을 하다면 어떻게 되겠는가? 예전엔 기술의 발전이 없을 때는 당연히 기계식으로 돌렸고, 빛보다 현저히 느릴 수 밖에 없는 구조였다. 현대에는 빛을 이용한 방식을 많이 사용하기 때문에 당연히 모든 면에서 빨라질 수 밖에 없는 구조이다.


2. 라우터 = 일종의 공유기이다. LAN과 LAN, LAN과 WAN을 서로 연결하기 위한 인터넷 프로토콜이며, 데이터의 전송을 위한 경로지정을 해주는 기능을한다. 또한 가장 중요한 것은 현존하는 네트워크 연결 장비중에 가장 속도가 빠르며 전세계는 이러한 라우터들로 이루어져 통신하고 있다. 가장 최적의 경로를 찾아 가장 빨리 송수신 해주는 장비가 바로 라우터이다. 

 



3. TCP/UDP의 차이점?


TCP(Transmission Control Protocol)

연결형 서비스를 지원하는 전송계층 프로토콜이며,  인터넷 환경에서 기본이 된다. 호스트간       신뢰성 있는 데이터 전달과 흐름제어 및 혼잡제어 등을 제공하는 전송계층이다.


TCP의 특징

- 가상 회선 연결 방식, 연결형 서비스를 제공

- 높은 신뢰성(Sequence Number, Ack Number를 통한 신뢰성 보장)

- 연결의 설정(3-way handshaking)과 해제(4-way handshaking)

-> 여기서 가장 중요한 사실은 높은 신뢰성보장이다.


* UDP(User Datagram Protocol)

비연결형 서비스를 지원하는 전송계층 프로토콜이며 사용자 데이터그램형 프로토콜이다. 인터넷상에서 서로 정보를 주고받을 때 정보를 보낸다는 신호나 받는다는 신호 절차를 거치지 않는 것이 특징이며, 보내는 쪽에서 일방적으로 데이터를 전달하는 통신 프로토콜


UDP의 특징


-  비연결형(port만 확인하여 소켓을 식별하고 송수신)

-  패킷 오버헤드가 적어 네트워크 부하 감소

-  비신뢰성

-  오류검출(헤더에 오류 검출 필드를 포함하여 무결성 검사)

-  TCP의 handshaking 같은 연결 설정이 없다

-> 여기서 가장 중요한건 비신뢰성이며 핸드쉐이킹같은 연결설정이 없다는 것이다.


three way handshaking/four way handshaking = three way handshaking은 서로간의 송수신을 서로 제대 인하면서 진행한다. four way handshaking 송수신을 끊을때 사용한다.

※ 프로세스: 프로그램이 실행되고 있는 것


4.  좋은 코딩을 위한 최적화 이슈


    - int arr[800*480] = [0]; -> 배열까진 좋다. 이정도를 메모리공간에 할당한다는거니까.

    - void draw(int x), int y1, int x2, int y2, int type, int color)-> 근데 파라미터가 너무 많다는       느낌 안받는가? 파라미터가 많을수록 레지스터에 대한 부담은 점점 커진다. 그렇게 되                   면 컴파일도 당연히 느릴수밖에 없고 여러모로 불리한 점이 많아진다. 그래서 좋은 코딩을 하         기 위해선 파라미터를 4개정도까지만 하는 것을 권장하고 있다.

    - for (int i = 0;  i < sizeof(arr), i++) -> sizeof 런타임이 아니다. 몇번 호출되든 상관 없다.





반응형
블로그 이미지

만년필석사

,
반응형


지난번 포스팅에서 간단한 서버를 구현해보았다. 하지만 서버라는것은 저렇게 하나만 간단히 돌아가는 것이 아니다. 항상 많은 서버들이 맞물려서 돌아가게 되기 마련이다. 그러기때문에 지난번에 했던 서버 내용을 기본으로 이번에는 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를 해주면 다음과 같이 화면에 출력된다.



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


반응형

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

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

만년필석사

,
반응형

<서버의 기초>

-Dispatcher의 필요성 -> Dispatcher은 데이터를 읽어들이는 역할을 하기때문에 서버에서 가장 중요하게                                      작용된다.

 서버의 문제점을 찾고 Reactor Pattern의 필요성을 확인할 수 있다.


○ 일단 가장 간단한 서버의 접속 프로그램을 만들어보았다.


1. 첫번째로 Serverinitializer class파일을 만든 후 다음과 같이 코딩한다.


import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.net.ServerSocket;

import java.net.Socket;


public class Serverinitializer 

{

      public static void main(String[] args

{

      int port = 5000; ->포트 설정 번호

      System.out.println("Server ON :" + port); -> 서버 on

  try

  {

      ServerSocket serverSocket = new ServerSocket(port); 

      Socket connection;  -> 서버 설정

     while (true)

     {

     connection = serverSocket.accept(); ->연결받기

     InputStreamReader inputStreamReader = new InputStreamReader(connection.getInputStream());

     BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 

     String line = bufferedReader.readLine(); -> 데이터를 읽는 부분

     System.out.println("READ:" + line); -> 받아들인 데이터를 처리하는 부분

     }

 }

  catch (IOException e)

{

   e.printStackTrace(); -> try문에서 에러 발생시 알려주는 부분

    }

}


2. 두번째로 client class를 만든다. 파일명은 TestClient로 한후 다음과 같이 코딩한다.

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("Clinet ON"); -> 클라이언트 서버 on

  try

  {

     String message;

     Socket socket = new Socket("127.0.0.1", 5000); -> 받아들일 소켓 tcp설정

     OutputStream out = socket.getOutputStream();

     message = "0X5001|이건주|26"; -> 화면에 view할 메시지 입력

     out.write(message.getBytes()); ->메시지를 화면에 보내준다.

     socket.close(); -> 소켓 닫기

   }

   catch (UnknownHostException e)

   {

      e.printStackTrace();

   }

   catch (IOException e)

   {

     e.printStackTrace();

    }

  }

}


3. 이렇게 두가지를 완성해서 RUN AS를 해보면 콘솔창에 다음과 같이 나오게 된다.




이때 주의 사항이 있다. 분명 RUN AS를 해보게 된다면 Address already in use라고 경고표시가 나오면서 여러 사이트 비슷한 에러내용이 뜰 것이다. 그렇게 되면 iturm으로 가서 리눅스 명령어 sudo lsof -i tcp:5000 라고 입력을 하게 되면 현재 실행되고 있는 서버목록이 확인될 것이다. 현재 이렇게 포트 5000에서 이미 서버가 돌아가고 있기때문에 이미 사용중인 에러메시지가 나오는 것이다. 그러기때문에 현재 진행중인 서버를 닫아줘야 한다. 서버를 닫기위한 리눅스 명령어는 sudo kill -9 (PID번호)이다. 이걸 입력해주고 다시 돌아와서 RUN AS를 해주면 화면에 보이는 것과 같이 서버가 잘 돌아감을 볼 수 있다.


반응형
블로그 이미지

만년필석사

,
반응형

일단 가장 기초적이면서도 많이 쓰이는 리눅스 명령어들을 정리해보았다. 사실 어떻게 보면 너무 기초적인 것이라 좀 그렇기도 하지만 리눅스를 시작함에 있어서는 중요하기 때문에 몇개 올려보았다.



1. cd [경로]

해당 경로로 이동한다.

- "." 현재 경로를, ".." 상위 경로를 의미한다.

- 상대경로 혹은 절대경로를 이용해 이동 가능하다.

- ex) cd /          : 루트 경로로 이동.

        cd conf      :  위치의 conf 폴더로 이동

        cd ..          : 상위 경로로 이동.

        cd ../conf  : 상위 경로의 conf 폴더로 이동

        cd /apache/conf : 루트 경로의 apache폴더 내의 conf 폴더로 이동

2. pwd

- 현재 작업중인 폴더의 위치를 확인하는 명령어


3. mkdir [폴더명]

- 경로에 폴더를 생성한다.

- ex) mkdir example : 현재 경로에 example이라는 이름의 폴더를 생성


4. ls

- 현재 경로의 파일 하위폴더 목록을 보여준다.

 


옵션 내용 

 -a  숨김 파일을 포함한 목록을 보여준다.

 -l  리스트 형식으로 권한, 파일명, 수정시간 정보도 함께 보여준다.

 -c  파일 상태 정보가 변경된 순으로 보여준다.

 -t  파일이 변경된 순으로 보여준다..

 -u  최근 사용 파일 순으로 보여준다.


 

- ex) ls        : 그냥 현재 경로의 파일 하위폴더 목록을 보여준다.

        ls -l     : 현재 경로의 파일 하위폴더 목록을 자세히 보여줌

        ls -al   : 현재 경로의 파일 하위폴더 목록(숨김 파일 포함) 자세히 보여줌

        ls -altr : 현재  경로의 파일 하위폴더 목록(숨김 파일 포함) 파일 변경 시간 내림차순으로  보여줌(오래된순)

 

5. reboot

- 재부팅 명령어이다.

- reboot라고 입력하면 재부팅된다.

"shutdown -r now"


6. VI

1.Vi 실행하기

vi <file> : 입력한 file 연다

vi + file : file  커서가 본문의 마지막 행에 위치한다.

2.Vi 입력모드 전환 명령어

H : 화면 위로 이동

M : 화면의 중간으로 이동

L : 화면 아래로 이동

i : 커서 있는데서 입력모드 전환한다.

3. 복사와 붙여넣기

yy : 현재 줄을 버퍼로 복사(Ctrl + c)

p : 버퍼에 있는 내용을 커서 뒤에 삽입

d : 현재 커서가 위치해 있는 단어 복사

4. 문자열 찾기

/name : name 입력한 내용이 있는 문자열 찾기

5. 파일 저장 불러오기

:w : 지정된 파일에 저장

:wq : 지정된 파일에 저장하고 vi 종료

:q! : 저장하지 않고 종료


7. mv

파일 또는 디렉토리의 이름을 바꾸거나 위치를 이동시키는 명령

-  옵션

   -f : 옮겨질 파일이 이미 존재하더라도 묻지 않고 덮어 쓴다. ('f'는  force의 약어)
   -i : 옮겨질 파일이 이미 존재하는 파일이면 덮어 쓸 것인지 물어본다.
   -b : 파일을 지우기 전에 백업본을 만든다.
   -u : 옮겨질 디렉토리에 구버전의 파일이 있는 경우에만 옮긴다.
- 예시
   1) mv readme.txt /home/posein/data => readme.txt라는 파일을 /home/posein/data 디렉토리로 옮기라는 명령이다.
   2) mv aaa.txt bbb.txt => aaa.txt 파일을 bbb.txt파일로 바꾸라는 명령이다.


반응형
블로그 이미지

만년필석사

,