TCP/IP 이해

국제 표준 단체인 ISO가 제정한 OSI 7 layers는 실제로 사용되지
않는 프로토콜이지만, 통신 프로토콜 개발과 이해하는데 이용된다. 




ARPA 네트워크에서 부터 시작된 TCP/IP 프로토콜은 1983년 버클리 
대학교에서 개발된 BSD 유닉스에 포함되면서 부터 점차 많이 사용되게
되었다. BSD 유닉스가 소켓 기능을 제공하면서 부터 네트워크 프로그래밍은
휠씬 간단하게 되었다. 즉, 프로그래머는 OSI 7 layer에서 트랜스포트 계층
이하는 무시하고, 소켓 함수만 이용해서 프로그래밍 할 수 있게 된 것이다.
System V 계열의 유닉스도 소켓의 영향을 받아서 STREAM을 개발해서
TLI 프로그래밍을 지원하고 있다. 




TCP/IP 프로토콜에서 각 계층은 상대방에게 전달할 데이터와 제어 정보를
가지고 있다. 데이터와 제어 정보를 메시지라고 한다. 메시지는 하위 계층으로
전달되면 기존 메시지에 추가적인 제어 정보를 붙이게 되는데 이것을 
캡슐화(encapsulation)라고 한다. 이와 반대되는 과정을 decapsulation이라고
한다.



다음 그림은 인터넷 상에서 메시지가 전송되는 과정을 보여준다. 인터넷상에는
수많은 컴퓨터들이 존재하고, 이 컴퓨터들 중에서 어떤 것들은 메시지를 
받아서 다른 곳으로 전송하는 역할을 하기도 한다. 이러한 역할을 하는 컴퓨터나
장치를 라우터라고 한다. 라우터는 전송받은 내용을 decapsulation해서 
제어 정보를 알아보고 적당한 곳으로 메시지를 전송한다.





URL

protocol://hostname[:port]/path/filename#section 프로토콜에는 다음과 같은 것이 있다. file : 하드 디스크에 있는 파일 ftp : FTP 서버에 연결 http : 웹서버에 연결 gopher : gopher 서버에 연결 news : usenet 뉴스 그룹에 연결 telnet : 텔넷 서비스를 이용 wais : wais 서버에 연결 URL을 이용해서 다른 곳으로 이동하는 애플릿을 작성해보자. URLButton.java 파일
import java.awt.*;
import java.net.*;
import java.applet.Applet;

public class URLButton extends Applet {
	URL     url = null;
	String  title = null;

	public void init() {
		String urlString = null;
		setLayout(new GridLayout(1,1));
		title = getParameter("title");
		if(title == null)
			title = "URLButton";
		urlString = getParameter("url");
		if(urlString == null)
			urlString = "http://";
		try {
			url = new URL(urlString);
		} catch(MalformedURLException e) {
			System.out.println("Invalid URL:"+ urlString);
		}
		Button site = new Button(title);
		add(site);
		resize(100, 60);
	}


	public boolean action(Event e, Object arg) {
		if((e.target instanceof Button)&&(arg.equals(title))) {
			getAppletContext().showDocument(url);
		}
		return false;
	}
}

URLButton.html 파일
<body bgcolor="#ffffff">
<applet code=URLButton width=100 height=50>
<param name=title value="WebZine">
<param name=url   value="http://203.253.23.3/special.html">
</applet>

<applet code=URLButton width=100 height=50>
<param name=title value="BBS">
<param name=url   value="http://203.253.24.55/~bbs/">
</applet>


<applet code=URLButton width=100 height=50>
<param name=title value="WebNews">
<param name=url   value="http://203.253.23.3/">
</applet>

소켓

일반적으로 C 언어를 이용해서 네트워크 프로그램을 작성하는 경우, 프로그램 절차는 다음 그림과 같다. 서버 프로그램은 소켓을 생성하고, bind()를 이용해서 소켓과 어드레스 및 포트를 결합시킨다. listen() 함수를 호출하고, bind()함수를 호출해서 클라이언트로 부터 요청이 올 때까지 블락되어서 기다린다. bind() 함수는클라이언트로부터 요청이 오면 클라이언트와 콩신할 수 있는 소켓을 만들어서 리턴한다. 리턴된 소켓을 통해서 서버와 클라이언트는 read()/write() 함수를 이용해서 통신할 수 있다. 클라이언트에서는 소켓을 생성하고, connnect()함수를 통해서 서버에 연결을 시도한다. connect()를 호출하면 서버에서는 accept()함수 가 실행된다. 서버와 연결되면 소켓을 통해 read/write를 할 수 있다.

서버소켓

자바에서 네트워크 프로그래밍을 하기 위해서는 java.net패키지를 이용한다. 서버프로그램을 만들 때는 소켓을 만들고, bind()하고 listen()하는 일들이 항상 반복된다. 자바에서는 이러한 반복 작업을 제거하기 위해서 서버 소켓(ServerSocket)이라는 클래스를 만들었다. 프로그래머는 서버 소켓을 만들어서 accept()메소드를 호출한다. accept() 메소드는 클라이언트로 부터 컨넥션이 요청될 때까지 블락되있다가, 요청이 들어오면 클라이언트와 통신할 수 있는 소켓을 생성해서 리턴해준다. 서버는 리턴된 소켓을 이용해서 클라이언트와 통신할 수 있다. 클라이언트에서도 마찬가지로 반복되는 작업을 제거하기 위해, connect()라는 함수를 호출할 필요가 없도록 소켓(Socket)이라는 클래스를 만들었다. 따라서, 클라이언트에서는 소켓을 만들고, 소켓을 이용해서 만든 I/O 스트림을 이용해서 서버와 통신할 수 있다.

예: 자바 채팅 프로그램

다음 채팅 프로그램은 "Java Network programming"의 저자인 Hughes가 자바월드에 기고한 프로그램 소스이다. 프로그램을 너무 간단하고도 잘 작성했기 때문에 저자의 허락없이 인용 한다. 프로그램의 저작권은 hughes에 있슴을 밝혀둔다.(국내에서는 출처만 밝히면 인용해도 저작권법에 저촉되지 않는 것으로 알고 있다. -_-;;;) 서버 실행시키기 % java ChatServer 9830 & 애플릿뷰어로 본 채팅 클라이언트 ChatServer.java 파일
  
import java.net.*; 
import java.io.*; 
import java.util.*; 
 
public class ChatServer { 
  public ChatServer (int port) throws IOException { 
    ServerSocket server = new ServerSocket (port); 
    while (true) { 
      Socket client = server.accept (); 
      System.out.println ("Accepted from " + client.getInetAddress ()); 
      ChatHandler c = new ChatHandler (client); 
      c.start (); 
    } 
  } 
 
  public static void main (String args[]) throws IOException { 
    if (args.length != 1) 
      throw new RuntimeException ("Syntax: ChatServer "); 
    new ChatServer (Integer.parseInt (args[0])); 
  } 
} 

ChatHandler.java 파일
  
import java.net.*; 
import java.io.*; 
import java.util.*; 
 
public class ChatHandler extends Thread { 
  protected Socket s; 
  protected DataInputStream i; 
  protected DataOutputStream o; 
 
  public ChatHandler (Socket s) throws IOException { 
    this.s = s; 
    i = new DataInputStream (new BufferedInputStream (s.getInputStream ())); 
    o = new DataOutputStream (new BufferedOutputStream (s.getOutputStream ())); 
  } 
 
  protected static Vector handlers = new Vector (); 
 
  public void run () { 
    String name = s.getInetAddress ().toString (); 
    try { 
      broadcast (name + " has joined."); 
      handlers.addElement (this); 
      while (true) { 
        String msg = i.readUTF (); 
        broadcast (name + " - " + msg); 
      } 
    } catch (IOException ex) { 
      ex.printStackTrace (); 
    } finally { 
      handlers.removeElement (this); 
      broadcast (name + " has left."); 
      try { 
        s.close (); 
      } catch (IOException ex) { 
        ex.printStackTrace(); 
      } 
    } 
  } 
 
  protected static void broadcast (String message) { 
    synchronized (handlers) { 
      Enumeration e = handlers.elements (); 
      while (e.hasMoreElements ()) { 
        ChatHandler c = (ChatHandler) e.nextElement (); 
        try { 
          synchronized (c.o) { 
            c.o.writeUTF (message); 
          } 
          c.o.flush (); 
        } catch (IOException ex) { 
          c.stop (); 
        } 
      } 
    } 
  } 
} 

ChatApplet.java 파일
 
import java.net.*; 
import java.io.*; 
import java.awt.*; 
import java.applet.*; 
 
// Applet parameters: 
//   host = host name 
//   port = host port 
 
public class ChatApplet extends Applet implements Runnable { 
  protected DataInputStream i; 
  protected DataOutputStream o; 
 
  protected TextArea output; 
  protected TextField input; 
 
  protected Thread listener; 
 
  public void init () { 
    setLayout (new BorderLayout ()); 
    add ("Center", output = new TextArea ()); 
    output.setEditable (false); 
    add ("South", input = new TextField ()); 
    input.setEditable (false); 
  } 
 
  public void start () { 
    listener = new Thread (this); 
    listener.start (); 
  } 
 
  public void stop () { 
    if (listener != null) 
      listener.stop (); 
    listener = null; 
  } 
 
  public void run () { 
    try { 
      String host = getParameter ("host"); 
      if (host == null) 
	host = getCodeBase ().getHost (); 
      String port = getParameter ("port"); 
      if (port == null) 
	port = "9830"; 
      output.appendText ("Connecting to " + host + ":" + port + "..."); 
      Socket s = new Socket (host, Integer.parseInt (port)); 
      i = new DataInputStream (new BufferedInputStream (s.getInputStream ())); 
      o = new DataOutputStream (new BufferedOutputStream (s.getOutputStream ())); 
      output.appendText (" connected.\n"); 
      input.setEditable (true); 
      input.requestFocus (); 
      execute (); 
    } catch (IOException ex) { 
      ByteArrayOutputStream out = new ByteArrayOutputStream (); 
      ex.printStackTrace (new PrintStream (out)); 
      output.appendText ("\n" + out); 
    } 
  } 
 
  public void execute () { 
    try { 
      while (true) { 
        String line = i.readUTF (); 
        output.appendText (line + "\n"); 
      } 
    } catch (IOException ex) { 
      ByteArrayOutputStream out = new ByteArrayOutputStream (); 
      ex.printStackTrace (new PrintStream (out)); 
      output.appendText (out.toString ()); 
    } finally { 
      listener = null; 
      input.hide (); 
      validate (); 
      try { 
        o.close (); 
      } catch (IOException ex) { 
        ex.printStackTrace (); 
      } 
    } 
  } 
 
  public boolean handleEvent (Event e) { 
    if ((e.target == input) && (e.id == Event.ACTION_EVENT)) { 
      try { 
        o.writeUTF ((String) e.arg); 
        o.flush (); 
      } catch (IOException ex) { 
        ex.printStackTrace(); 
        listener.stop (); 
      } 
      input.setText (""); 
      return true; 
    } else if ((e.target == this) && (e.id == Event.WINDOW_DESTROY)) { 
      if (listener != null) 
        listener.stop (); 
      hide (); 
      return true; 
    } 
    return super.handleEvent (e); 
  } 
} 

자바추천학원:
http://www.it-bank.or.kr/prom/java_main.htm
Posted by 김윤석

카테고리

놀며즐기고 공부하기 (685)
 IT 정보 (653)
 재테크 (0)
 엔터테이먼트 (11)
 인터넷마케팅 (0)
 사이트 추천 (1)
사이드바 열기