BLOG ARTICLE Applet | 1 ARTICLE FOUND

  1. 2008/03/13 Servlet Applet 간의 TCP IP 통신

사용자 삽입 이미지
이번 아티클의 주제는 Applet과 Servlet을 이용한 Chatting 이다. Applet에서는 Client Socket을 이용하고  Servlet에서는 Server Socket을 이용하여 서로 통신을 하게 된다.

▶ Servlet의 작동

흔히 chatting은 Server application과 Client Application혹은 Applet으로 만들어 진다

이번에는 Server를 Servlet으로 구현 하고 Client를 Applet으로 혹은 Application으로 접속하는
Program을 만들어 보도록 하자

Server가 Servlet으로 만들어 지면 그만큼 Code가 줄어 들고 multi Thread로 동작하는 특성을 살린다면 상당히 간편하게 구현 하실 수 있다. 또한 기존에 Servlet이나 JSP로 만들어진 Web Site에 Chatting을 붙이기 위해서 별도의 Server Application을 만들지 않고도 가능하다.

먼저 Servlet을 보도록 하자.

ChatServlet.java


import java.net.*;
import java.util.*;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;

public class ChatServlet extends HttpServlet implements Runnable {
 

 public void init(ServletConfig conf) throws ServletException {
  super.init(conf);
  Thread t = new Thread(this);
  t.setDaemon(true);
  t.start();
 }
 
    public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException {
        PrintWriter pw=null;
        res.setContentType("text/html");
        try {
            pw = res.getWriter();
        } catch(IOException e) { System.err.println("getWriter failed"); }
        pw.println("<html>");
        pw.println("<head>");
        pw.println("<title>Test Chat Applet</title>");
        pw.println("</head>");
        pw.println("<body>");
        pw.println("<applet  codebase=\"../../\" code=\"ChatClient.class\"  width=450 height=300>");
        pw.println("</applet>");
        pw.println("</body>");
        pw.println("</html>");
        pw.close();
    }

    public void run() {
        ServerSocket ss;
        try {
            ss = new ServerSocket(7777);
        } catch(IOException e) {
            System.err.println("ServerSocket failed");
            return;
        }
        while(true) {
            Socket s = null;
            try {
                s = ss.accept();
            } catch (IOException e) { System.err.println("accept failed"); }
            ChatThread ct = new ChatThread(s);
            ct.setDaemon(true);
            ct.start();
        }
    }

}

class ChatThread extends Thread {
    static Vector v = new Vector();
    Socket s;

    public ChatThread(Socket s) {
        this.s = s;
    }

    public void run() {
        InputStream is=null;
        OutputStream os=null;
        try {
            is = s.getInputStream();
        } catch(IOException e) { System.err.println("getInputStream failed"); }
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        try {
            os = s.getOutputStream();
        } catch(IOException e) { System.err.println("getOutputStream failed"); }
        PrintWriter pw = new PrintWriter(os, true);
        v.addElement(pw);
       
        while(true) {
            String s=null;
            try {
                s = br.readLine();
                if(s == null) {
                    return;
                }
            } catch(IOException e) {
                System.err.println("readLine failed");
                return;
            }
            for(int i=0; i<v.size(); i++) {
                PrintWriter p = (PrintWriter)v.elementAt(i);
                p.println(s+"|"+v.size());
                if(p.checkError()) {
                    v.removeElementAt(i);
                    i--;
                }
            }
        }
    }
}
 

ChatServlet.java 에서는 순수하게 Client 에서 Request만을 담당하고 ChatThread.java 에서는 Service를 담당하는 code가 들어간다

여기서 Server Socket을 일던하게 Open하고 기다린다

▶ Applet코드의 작성

ChatClient.java


import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.util.*;

public class ChatClient extends Applet implements Runnable, ActionListener {
  Label lbl1 = new Label();
  TextField txtName = new TextField("", 10);
  Button btnConn = new Button();
  TextArea txtReceive = new TextArea("");
  TextField txtSend = new TextField("");

  Socket socket;
  BufferedReader din;
  PrintWriter dout;
  boolean fConnecting = false;
  Thread listener;
  String name="";
  Label label=new Label("접속자");
  TextField count=new TextField("",2);

  public ChatClient() {
  }

  public void init() {
 
    makeUi();
   
  }
  public void makeUi(){
    setLayout(new BorderLayout());
   
   Panel p = new Panel();
   lbl1.setText("이름");
    btnConn.setLabel("연결");
    count.setEditable(false);
    btnConn.addActionListener(this);
    p.add(lbl1);
    p.add(txtName);
    p.add(btnConn);
 p.add(label);
 p.add(count);
   
    txtReceive.setEditable(false);
 txtReceive.setBackground(Color.white);
 txtReceive.setForeground(Color.blue);
    txtSend.addActionListener(this);

    add(p, BorderLayout.NORTH);
    add(txtReceive, BorderLayout.CENTER);
    add(txtSend, BorderLayout.SOUTH);

  }

  public void actionPerformed(ActionEvent e) {
   Object s = e.getSource();
 
    if(s == btnConn) btnConn_actionPerformed(e);
    else if(s == txtSend) txtSend_actionPerformed(e);
  }

  void btnConn_actionPerformed(ActionEvent e) {
    try {
      if(fConnecting) {
        btnConn.setLabel("연결");
        txtName.setEditable(true);
        txtSend.setEditable(false);
        txtName.requestFocus();
        fConnecting = false;
        listener.destroy();
        din.close();
        dout.close();
        socket.close();
      } else {
        if(txtName.getText().equals("")) {
          return;
        }
  name=txtName.getText();
        btnConn.setLabel("종료");
        txtName.setEditable(false);
        txtSend.setEditable(true);
        txtSend.requestFocus();
        fConnecting = true;
        socket = new Socket("localhost", 7777);
        din = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        dout = new PrintWriter(socket.getOutputStream(), true);
     listener = new Thread(this);
        listener.start();
      }
    } catch(IOException ioe) {}
  }

  void txtSend_actionPerformed(ActionEvent e) {
      dout.println("["+name+"]"+txtSend.getText());
      txtSend.setText("");
  }

  public void run() {
   while(true) {
     try {
        String s = din.readLine();
   StringTokenizer st=new StringTokenizer(s);
   String msg=st.nextToken("|");
   String size=st.nextToken();
        txtReceive.append(msg + "\n");
   count.setText(size);
     } catch(IOException ioe) {}
   }
  }
}
 

여기서는 Client Socket을 만들어서 Server와의 접속을 하게 된다.

다음 Server로 부터 받은 결과를 화면에 출력 한다.

* 실행 방법

1. Servlet을 Server의 Servlet 위치이 존재하는 위치에 올려 놓는다.

2. Applet이 존재하는 위치에 대해 codebase를 지정한다

3. Applet은 Doc즉 web Service dir에 위치 시킨다.

4. client 에서 browser에서 Servlet을 호출한다.


간단하게 Applet과 Servlet과의 TCP/IP 통신에 대해 살펴보았다.

이 예에서는 Server쪽의 Code가 상당히 줄어 들면서 관리가 편해진다.

하지만 이러한 예에서의 문제점은 Server쪽에서는 80 Port 즉 HTTP Port가 아닌 다른 일정한 Server Socket Port를 열어 놓아야 한다는 것이 가장 문제이다. 또한 Server 와 Client 간에 TCP/IP로 일정하게 계속 접속하고 있다는 것도 Server쪽에 무리를 주는 하나의 예가 될수 있다는 것이다.

이런 Chatting이 아닌 다른 Applet과 Servlet과의 통신은 단지 Applet에서는 get,post방식을 이용하여 servlet과 접속하는 예를 이용하여 Client쪽에서 접속한다면 Server 쪽의 Security측면에서도 많은 잇점을 가질수 있다.


 

크리에이티브 커먼즈 라이센스
Creative Commons License
2008/03/13 09:41 2008/03/13 09:41