기존에 존재하는 아티클인 "HTTP Webserver 만들기"가 버겨웠다면 간단 명료하게 웹서버의 기능을 갖는 네트웍프로그램을 만들어 보도록 합니다. ( 2003/03/18 ) 281
HTTP Webserver만들기 편에서 모두들 이해를 잘했는지가
상당히 궁금하다. 이번 편에서는 아주 간단한 초미니 웹서버를 만드는 방법을
해보겠는데 소켓과 스레드에 대한 내용을 조금만 알고 있고, http protocol의 브라우져가
식별할 수 있는 헤더메시지를 안다면 쉽게 만들수 있을 것이다.
▶ 미니웹서버 만들기
자. 웹서버의 기본작동원리는 무엇일까? 자바로 웹서버를 만든다면 당연히 스레드를 이용할
것이며, c로서 만들게 된다면 각 요청에 대한 process를 fork시켜 서비스 핸들러를 만들어처리를
하게 될 것이란게 머리속에 조금은 들어오나요?
자바로 소켓프로그램을 짜보았다면 순서는 어떻게 될까요?
1. 서버데몬을 구동한다.
2. 클라이언트가 서버측의 서버소켓으로 접근을 시도한다.
3. 서버는 클라이언트와 연결되어질 소켓객체를 생성한다.
자, 이제 4번부터가 P2P방식인지 server daemon방식의 서비스인지가 결정이 날수 있는데 스레드를 생성하지 않고서 직접 클라이언트의 request를 처리한다고 가정합니다.
만약 서비스를 완료하는데 걸리는 시간이 1분이었다고 가정을 하게 된다면 다음 요청을 하게되는
클라이언트는 어떻게 될까요?
connection timeout 또는 connection refused를 경험하게 될 것입니다. 궁금한가요? 직접 짜보세요! 아래와 같은 코드를 이용하여 테스트해보면 될 것입니다.
간단하게 위처럼만 짜보고 테스트해 보세요. 서버는 클라이언트의 요청이 들어오게 되면 1분 동안을 바보처럼 가만히 잠자게 될때 다른 클라이언트로 접근을 시도해 보세요~
결과는 여러분들이 직접 짜보도록 합니다.
각설하고 계속 나가겠습니다. 그러면 위와 같은 서비스의 끊김현상이 발생하지 않고, 클라이언트의 요청을 족족이 모두 서비스가 가능하게 하려면 어떻게 해야 하나요?
답은 바로 위에도 이야기 했던것처럼 스레드입니다.
4. 클라이언트의 요청이 들어오면 해당 소켓을 서비스핸들링을 할 수 있는 스레드로 전이시킨다.
5. 소켓을 넘겨넣은 스레드는 실제 요청이 들어온 클라이언트에게 서비스를 하도록 한다.
6. 요청을 모두 처리했으면 http속성답게 연결을 끊어버린다.
위의 시나리오가 전부입니다.
네트웍프로그램의 불변의 법칙을 아나요? 아주 간단합니다.
간단한 만큼 네트웍프로그래밍 방법을 간단하게 설명하겠습니다.
1. 서버측프로그램을 작성한다.
- 서버소켓을 생성한다.
- 무한루프를 이용하여 서버소켓의 accept()로 클라이언트요청을 기다린다.
- 클라이언트요청이 들어올 경우 서비스를 할 스레드를 생성하고 accept()에 의하여 넘겨진
socket을 스레드측으로 전달한다.
- 서버를 다시 서비스를 계속한다.
2. 클라이언트측 프로그램을 작성한다.
- 서버측으로 접속을 시도할 수 있는 소켓을 IP와 포트로 생성한다.
- 보내고자 하는 데이터를 stream으로 필터링하여 서버로 전송한다.
이런~~ 쓸려니 조금 힘드네요. 네트웍프로그래밍을 자유자재로 하고 싶은가요? 그렇다면 놀새의 이야기를 들어주길 바랍니다.
Thread개념, IO개념만 정확하게 안다면 네트웍프로그램은 51% 정복한 거나 다름 없습니다.
그만 떠들고 프로그램이나 보이라는 소리가 여기저기서 들리는 듯 하네요. 아흐~
자. 프로그램으로 들어갑니다. 먼저 서버소켓을 이용하여 클라이언트의 요청을 받을 수 있는
서버프로그램을 스레드형태로 작성해 보도록 하죠.
▶ 서버측 데몬
▶ 서버측 서비스 스레드
아. 위의 프로그램이 조금이라도 이해가 가나요? 그렇다면 이 글을 읽는 당신~!!! 떠나세요~~~!!
자. 위에서 보게 되면 서버측의 accept()메소드가 수행되게 되면 바로 서비스 핸들러측으로 서버소켓이 넘겨준 Socket객체를 스레드로 넘겨주는 역할을 하게 되고 실제 그 서비스 스레드는
PrintWriter객체를 클라이언트 측에 갖다댄 후 HTTP 프로토콜로 쏴주는 형식을 취하고 있습니다.
여러분들 서블릿을 작성해 보았나요? 그렇다면 reponse.getWriter()를 아시겠죠?
기본적인 서블릿의 getWriter()를 하게 되면 이미 response의 스트림위에 저러한 http protocol의
헤더가 들어있는 것입니다. 저 정보는 누가 해석을 하게 될까요? 바로 브라우져입니다
실행을 해보죠. 설마 실행하는 방법을 모르는 JPer들이 있을까봐 놀새가 친절하게 적고
그 결과까지 적어보도록 하겠습니다.
먼저 컴파일.
javac *java
자, 컴파일이 되었다면 서버데몬을 구동하도록 합니다.
java MiniWebServer
자. 서버가 구동되어서 도스창이 먹통이 된다고 놀라지 않아야 합니다.
"어라? 클라이언트 프로그램이 없는데 저걸 어떻게 테스트해"라고 물어보면 가슴이 저려올 것이에요.
클라이언트 프로그램은 무엇일까요? 바로 바로 웹브라우져입니다.
웹브라우져를 바로 하나 띄워보도록 합니다.
URL입력창에 아래와 같이 입력하도록 합니다.
http://127.0.0.1:9090/
결과값이 아래와 같이 나온다면 대성공입니다.
도스창
web server start!!
client: /127.0.0.1
3397 : 9090
웹브라우져

너무 너무 간단합니다.
아무렇지 않은 코딩이지만 이거 못짜는 분들 너무 많습니다.
HTTP Webserver만들기 편에서 모두들 이해를 잘했는지가
상당히 궁금하다. 이번 편에서는 아주 간단한 초미니 웹서버를 만드는 방법을
해보겠는데 소켓과 스레드에 대한 내용을 조금만 알고 있고, http protocol의 브라우져가
식별할 수 있는 헤더메시지를 안다면 쉽게 만들수 있을 것이다.
▶ 미니웹서버 만들기
자. 웹서버의 기본작동원리는 무엇일까? 자바로 웹서버를 만든다면 당연히 스레드를 이용할
것이며, c로서 만들게 된다면 각 요청에 대한 process를 fork시켜 서비스 핸들러를 만들어처리를
하게 될 것이란게 머리속에 조금은 들어오나요?
자바로 소켓프로그램을 짜보았다면 순서는 어떻게 될까요?
1. 서버데몬을 구동한다.
2. 클라이언트가 서버측의 서버소켓으로 접근을 시도한다.
3. 서버는 클라이언트와 연결되어질 소켓객체를 생성한다.
자, 이제 4번부터가 P2P방식인지 server daemon방식의 서비스인지가 결정이 날수 있는데 스레드를 생성하지 않고서 직접 클라이언트의 request를 처리한다고 가정합니다.
만약 서비스를 완료하는데 걸리는 시간이 1분이었다고 가정을 하게 된다면 다음 요청을 하게되는
클라이언트는 어떻게 될까요?
connection timeout 또는 connection refused를 경험하게 될 것입니다. 궁금한가요? 직접 짜보세요! 아래와 같은 코드를 이용하여 테스트해보면 될 것입니다.
▶ Server측
public MiniWebServer() {
try
{
ServerSocket me = new ServerSocket( 8081 );
Socket client = me.accept();
Thread.sleep(1000 * 60);
System.out.println( "client: " + client.getInetAddress() );
}
catch ( Exception ex ) {
System.out.println( ex + "server start failed!!" );
}
}
▶Client측
public void connect() {
Socket soc = new Socket("127.0.0.1", 8081);
}
public MiniWebServer() {
try
{
ServerSocket me = new ServerSocket( 8081 );
Socket client = me.accept();
Thread.sleep(1000 * 60);
System.out.println( "client: " + client.getInetAddress() );
}
catch ( Exception ex ) {
System.out.println( ex + "server start failed!!" );
}
}
▶Client측
public void connect() {
Socket soc = new Socket("127.0.0.1", 8081);
}
간단하게 위처럼만 짜보고 테스트해 보세요. 서버는 클라이언트의 요청이 들어오게 되면 1분 동안을 바보처럼 가만히 잠자게 될때 다른 클라이언트로 접근을 시도해 보세요~
결과는 여러분들이 직접 짜보도록 합니다.
각설하고 계속 나가겠습니다. 그러면 위와 같은 서비스의 끊김현상이 발생하지 않고, 클라이언트의 요청을 족족이 모두 서비스가 가능하게 하려면 어떻게 해야 하나요?
답은 바로 위에도 이야기 했던것처럼 스레드입니다.
4. 클라이언트의 요청이 들어오면 해당 소켓을 서비스핸들링을 할 수 있는 스레드로 전이시킨다.
5. 소켓을 넘겨넣은 스레드는 실제 요청이 들어온 클라이언트에게 서비스를 하도록 한다.
6. 요청을 모두 처리했으면 http속성답게 연결을 끊어버린다.
위의 시나리오가 전부입니다.
네트웍프로그램의 불변의 법칙을 아나요? 아주 간단합니다.
간단한 만큼 네트웍프로그래밍 방법을 간단하게 설명하겠습니다.
1. 서버측프로그램을 작성한다.
- 서버소켓을 생성한다.
- 무한루프를 이용하여 서버소켓의 accept()로 클라이언트요청을 기다린다.
- 클라이언트요청이 들어올 경우 서비스를 할 스레드를 생성하고 accept()에 의하여 넘겨진
socket을 스레드측으로 전달한다.
- 서버를 다시 서비스를 계속한다.
2. 클라이언트측 프로그램을 작성한다.
- 서버측으로 접속을 시도할 수 있는 소켓을 IP와 포트로 생성한다.
- 보내고자 하는 데이터를 stream으로 필터링하여 서버로 전송한다.
이런~~ 쓸려니 조금 힘드네요. 네트웍프로그래밍을 자유자재로 하고 싶은가요? 그렇다면 놀새의 이야기를 들어주길 바랍니다.
Thread개념, IO개념만 정확하게 안다면 네트웍프로그램은 51% 정복한 거나 다름 없습니다.
그만 떠들고 프로그램이나 보이라는 소리가 여기저기서 들리는 듯 하네요. 아흐~
자. 프로그램으로 들어갑니다. 먼저 서버소켓을 이용하여 클라이언트의 요청을 받을 수 있는
서버프로그램을 스레드형태로 작성해 보도록 하죠.
▶ 서버측 데몬
import java.net.*;
import java.io.*;
public class MiniWebServer extends Thread {
private ServerSocket me;
public MiniWebServer() {
try
{
me = new ServerSocket( 9090 );
}
catch ( IOException ex ) {
System.out.println( ex + "server start failed!!" );
}
}
public void run() {
while ( true ) {
try {
Socket client = me.accept();
System.out.println( "client: " + client.getInetAddress() );
new ServiceHandler( client );
}catch ( Exception ex ){
System.out.println( ex );
}
}
}
public static void main(String[] args) {
MiniWebServer mini = new MiniWebServer();
mini.start();
System.out.println("web server start!!");
}
}
import java.io.*;
public class MiniWebServer extends Thread {
private ServerSocket me;
public MiniWebServer() {
try
{
me = new ServerSocket( 9090 );
}
catch ( IOException ex ) {
System.out.println( ex + "server start failed!!" );
}
}
public void run() {
while ( true ) {
try {
Socket client = me.accept();
System.out.println( "client: " + client.getInetAddress() );
new ServiceHandler( client );
}catch ( Exception ex ){
System.out.println( ex );
}
}
}
public static void main(String[] args) {
MiniWebServer mini = new MiniWebServer();
mini.start();
System.out.println("web server start!!");
}
}
▶ 서버측 서비스 스레드
import java.net.*;
import java.io.*;
class ServiceHandler implements Runnable {
private Socket client;
public ServiceHandler( Socket c ) {
try{
client = c;
System.out.println( client.getPort() + " : " + client.getLocalPort() );
Thread t = new Thread( this );
t.start();
}catch(Exception e) {
}
}
public void run() {
try {
PrintWriter out = new PrintWriter( client.getOutputStream() );
out.print( "HTTP/1.0 OK\r\n" );
out.print( "Server: HTTPServer 1.0\r\n" );
out.print( "Content-Type: text/html\r\n\r\n" );
out.println( "반갑습니다....<hr>" );
out.println( "<br>놀새가 만든 세상... ^^" );
out.close();
}catch ( IOException ex ){
System.out.println( ex );
}
}
}
import java.io.*;
class ServiceHandler implements Runnable {
private Socket client;
public ServiceHandler( Socket c ) {
try{
client = c;
System.out.println( client.getPort() + " : " + client.getLocalPort() );
Thread t = new Thread( this );
t.start();
}catch(Exception e) {
}
}
public void run() {
try {
PrintWriter out = new PrintWriter( client.getOutputStream() );
out.print( "HTTP/1.0 OK\r\n" );
out.print( "Server: HTTPServer 1.0\r\n" );
out.print( "Content-Type: text/html\r\n\r\n" );
out.println( "반갑습니다....<hr>" );
out.println( "<br>놀새가 만든 세상... ^^" );
out.close();
}catch ( IOException ex ){
System.out.println( ex );
}
}
}
아. 위의 프로그램이 조금이라도 이해가 가나요? 그렇다면 이 글을 읽는 당신~!!! 떠나세요~~~!!
자. 위에서 보게 되면 서버측의 accept()메소드가 수행되게 되면 바로 서비스 핸들러측으로 서버소켓이 넘겨준 Socket객체를 스레드로 넘겨주는 역할을 하게 되고 실제 그 서비스 스레드는
PrintWriter객체를 클라이언트 측에 갖다댄 후 HTTP 프로토콜로 쏴주는 형식을 취하고 있습니다.
여러분들 서블릿을 작성해 보았나요? 그렇다면 reponse.getWriter()를 아시겠죠?
기본적인 서블릿의 getWriter()를 하게 되면 이미 response의 스트림위에 저러한 http protocol의
헤더가 들어있는 것입니다. 저 정보는 누가 해석을 하게 될까요? 바로 브라우져입니다
실행을 해보죠. 설마 실행하는 방법을 모르는 JPer들이 있을까봐 놀새가 친절하게 적고
그 결과까지 적어보도록 하겠습니다.
먼저 컴파일.
javac *java
자, 컴파일이 되었다면 서버데몬을 구동하도록 합니다.
java MiniWebServer
자. 서버가 구동되어서 도스창이 먹통이 된다고 놀라지 않아야 합니다.
"어라? 클라이언트 프로그램이 없는데 저걸 어떻게 테스트해"라고 물어보면 가슴이 저려올 것이에요.
클라이언트 프로그램은 무엇일까요? 바로 바로 웹브라우져입니다.
웹브라우져를 바로 하나 띄워보도록 합니다.
URL입력창에 아래와 같이 입력하도록 합니다.
http://127.0.0.1:9090/
결과값이 아래와 같이 나온다면 대성공입니다.
도스창
web server start!!
client: /127.0.0.1
3397 : 9090
웹브라우져

너무 너무 간단합니다.
아무렇지 않은 코딩이지만 이거 못짜는 분들 너무 많습니다.





