태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

eternally full with hope...

블로그 이미지
영원히 희망으로 가득하길...
by eternalbleu
  • 464618Total hit
  • 101Today hit
  • 316Yesterday hit

'네트워크'에 해당되는 글 5건

  1. 2006/05/22
    분산처리 ㅡ.ㅡ
  2. 2006/04/13
    웹서버 소스
  3. 2006/03/30
    열혈강의 TCP/IP 소켓 프로그래밍
  4. 2006/03/22
    간만에 쓰는 레포트... 장애가 많다.
  5. 2006/03/07
    네트워크 강의...

요즘 준비중인 프로그램이 있습니다. 이녀석이 약간은 분산처리와 비슷한 냄새를 풍기는 놈인데... 이녀석을 다루면서 요즘 참 네트워크를 잘 짜기도 힘들겠구나 싶습니다.

제가 말하는 녀석은 C/S모델이 아닌 말그대로 분산형 처리. Self Routing, Self Recovery 모델을 지원하는 네트워크를 구성하는 녀석들을 말합니다. 이 녀석들을 보면 이 프로로콜을 고안하고 구현한 사람들이 결코 평범한 두뇌를 자랑하는 사람이 아니라는 생각이 듭니다. 각자가 C/S 모두인 이 녀석들은 조금만 컨트롤을 잘못해도 네트웍 전체가 엉켜버리는 군요.

아 답답해... ㅡ.ㅡ;; 그래도 결국엔 네트워크를 붙이는 일을 성공했습니다. 이제 제가 구현하려고 한 프로그램의 대충 50% 정도가 완성된 것 같습니다. 아직도 멀었네요. 한 한달은 빡시게 굴러야 완성되지 않을까 싶습니다. ㅜ.ㅜ

TRACKBACK 0 AND COMMENT 0

/************************************************************************
Multithreaded Web Server

written by eternalbleu
************************************************************************/
#include <STDIO.H>
#include <STDLIB.H>
#include <STRING.H>
#include <WINSOCK2.H>
#include <PROCESS.H>

// Constant
#define HUG_BUFFSIZE 2048
#define MID_BUFFSIZE 1024
#define SMA_BUFFSIZE 32
#define MAX_FILENAME 256

// Error Code
#define STATECODE_BAD_REQUEST 400
#define STATECODE_NOT_FOUND 404
#define STATECODE_OK 200

// Send HTTP Replay to Client
void SendReply(SOCKET clnt, UINT statusType, char *filename);
char* GetStatusLine(UINT type = STATECODE_OK);
char* GetErrorContent(UINT type);
int GetContentLength(FILE* fp);
char* GetContentType(char* filename);

void ErrorHandling(const char* message); // Error Message Handling
UINT WINAPI ClientConnect(void* argv); // Thread Proc

int main(int argc, char** argv)
{
WSADATA wsaData;
SOCKET servSock;
SOCKET clntSock;
SOCKADDR_IN servAddr;
SOCKADDR_IN clntAddr;

HANDLE hThread;
DWORD dwThreadID;

if (argc != 2) {
printf("SIMPLE WEBSERVER. written by youngchang. \n USAGE: %s <PORT>\n", argv[0]);
exit(1);
}

// DLL loading
if ( WSAStartup(MAKEWORD(2, 2), &amp;wsaData) != 0 )
ErrorHandling("WSAStartup() error occured.");

// socket creation &amp; initialize
if ( (servSock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET )
ErrorHandling("socket() error occured.");

// 서버 소켓 설정
memset((void*)&amp;servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET; // IPv4 주소 체계 이용
servAddr.sin_addr.s_addr = htonl( INADDR_ANY ); // 서버 주소 할당. 임의의 주소가 될 수 있어야함.
servAddr.sin_port = htons( atoi(argv[1]) ); // 인자로 받은 숫자를 이용 포트를 할당

// server socket setting
if ( bind(servSock, (SOCKADDR*)&amp;servAddr, sizeof(servAddr) ) == SOCKET_ERROR )
ErrorHandling("bind() error occured.");

// wait for request from client
if ( listen(servSock, 5) == SOCKET_ERROR )
ErrorHandling("listen() error occured.");

// requested from client
while(1) {
// 서버 대기 소켓으로 연결 요청이 들어온 클라이언트와의 소켓을 생성
int clntAddrSize = sizeof(clntAddr);
if ( (clntSock = accept(servSock, (SOCKADDR*)&amp;clntAddr, &amp;clntAddrSize)) == INVALID_SOCKET )
ErrorHandling("accept() error occured.");

// 클라이언트의 정보 출력
#ifdef _DEBUG
printf("REQUEST FROM %s : %d\n", inet_ntoa(clntAddr.sin_addr), ntohs(clntAddr.sin_port));
#endif
// 클라이언트 연결 쓰레드 생성
hThread = (HANDLE)_beginthreadex(NULL, 0, ClientConnect, (void*)clntSock, 0, (unsigned*)&amp;dwThreadID);
if (hThread == NULL)
ErrorHandling("_beginthreadex() error occured.");
}

// socket destroy
closesocket(servSock);

// DLL Unloading
WSACleanup();
return 0;
}

/************************************************************************
ClientConnect 합당한 에러메시지를 출력하며 프로그램을 종료한다.

@ argv 쓰레드프로세저의 인자. 이 경우 클라이언트와 연결된 소켓이 인자임.

# return 에러발생시 1, 정상 종료시 0
************************************************************************/
UINT WINAPI ClientConnect(void* argv)
{
SOCKET clntSock = (SOCKET)argv; // 클라이언트 소켓
char request[HUG_BUFFSIZE] = {0,}; // 요청 라인 (string)
char filename[MAX_FILENAME] = {0,}; // 요청 파일 (string)
char method[SMA_BUFFSIZE] = {0,}; // 요청 방식 (METHOD)

recv(clntSock, request, sizeof(request), 0);

if ( strstr(request, "HTTP/") == NULL ) // HTTP 요청인지 검사
{
closesocket(clntSock);
return 1;
}

// HTTP 요청 정보 출력
#ifdef _DEBUG
fputs("[BEG]\n", stdout);
fputs(request, stdout);
fputs("\n[END]\n", stdout);
#endif

strcpy(method, strtok(request, " ")); // HTTP 요청 방식 (METHOD) 얻기
if (strcmp(method, "GET")) // POST 메소드인 경우 에러 처리
SendReply(clntSock, STATECODE_BAD_REQUEST, NULL);

strcpy(filename, strtok(NULL, " ")); // HTTP 요청 파일 얻기

SendReply(clntSock, STATECODE_OK, filename);
return 0;
}

/************************************************************************
SendReply 클라이언트에게 알맞은 정보를 송신한다.

@ clnt 연결된 클라이언트와의 통신 소켓
@ statusType 답신 메시지의 종류를 송신한다
@ filename 클라이언트에게 보낼 파일 이름
************************************************************************/
void SendReply(SOCKET clnt, UINT statusType, char *filename)
{
// HEADER
char statusLine[SMA_BUFFSIZE] = {0,}; // 상태 라인
char contentLength[SMA_BUFFSIZE]= {0,}; // 내용 길이
char contentType[SMA_BUFFSIZE] = {0,}; // 내용 종류
char serverName[] = "Server:Simple Web Server v1.0\r\n"; // 서버 정보

// DATA
FILE* fp; // 전송 파일 파온터
char buffer[HUG_BUFFSIZE] = {0,}; // 전송 버퍼

// pre-process filename
if ( strlen(filename) == 1 &amp;&amp; !strcmp(filename, "/") ) strcpy(filename, "/index.html");
if ( *filename == '/' ) filename++;

// file open
if ( statusType == STATECODE_OK &amp;&amp; (fp = fopen(filename, "rb")) == NULL ) {
statusType = STATECODE_NOT_FOUND;
}
strcpy(statusLine, GetStatusLine(statusType)); // 상태 라인 정보 얻기
strcpy(contentType, GetContentType(filename)); // 내용 종류 얻기
sprintf(contentLength, "Content-length:%d\r\n", GetContentLength(fp)); // 내용 길이 정보 얻기

// Send HTTP Header
send(clnt, statusLine, strlen(statusLine), 0);
send(clnt, serverName, strlen(serverName), 0);
send(clnt, contentLength, strlen(contentLength), 0);
send(clnt, contentType, strlen(contentType), 0);

// Transmit error page data
if (statusType != STATECODE_OK)
{
char tmpbuf[MID_BUFFSIZE] = {0,};
strcpy(tmpbuf, GetErrorContent(statusType));
send(clnt, tmpbuf, strlen(tmpbuf), 0);
closesocket(clnt);
return;
}

// Send HTTP Data
size_t length = 0;
do {
length = fread(buffer, sizeof(char), sizeof(buffer), fp);
send (clnt, buffer, length, 0);
} while(!feof(fp));

closesocket(clnt);
}

/************************************************************************
GetStatusLine
@ type 상태 라인을 얻기위한 상수 값

# return 상태 라인 정보
************************************************************************/
char* GetStatusLine(UINT type)
{
switch(type)
{
case STATECODE_OK:
return "HTTP/1.0 200 OK\r\n";
break;

case STATECODE_BAD_REQUEST:
return "HTTP/1.0 400 Bad Request\r\n";
break;

case STATECODE_NOT_FOUND:
return "HTTP/1.0 404 Not Found\r\n";
break;

default:
return "HTTP/1.0 400 Bad Request\r\n";
break;
}
}

/************************************************************************
GetErrorContent 에러 코드에 따른 페이지 전송

@ type 에러 코드 상수

# return 에러코드에 맞는 페이지의 스트링
************************************************************************/
char* GetErrorContent(UINT type)
{
char buffer[HUG_BUFFSIZE] = {0,};
switch(type)
{
case STATECODE_NOT_FOUND:
strcpy(buffer,
"<FONT size=5>404 NOT FOUND</FONT>
ERROR OCCURED. CHECK FILENAME."
);
break;
case STATECODE_BAD_REQUEST:
strcpy(buffer,
"<FONT size=5>400 BAD REQUEST</FONT>
ERROR OCCURED. CHECK REQ METHOD."
);
break;
default:
strcpy(buffer,
"<FONT size=5>400 BAD REQUEST</FONT>
ERROR OCCURED. CHECK REQ METHOD."
);
break;
}
return buffer;
}

/************************************************************************
GetContentType 파일의 이름을 기반으로 파일의 MIME 타입의 스트링을 리턴한다.

@ filename 타입을 알아야할 파일의 이름

# return 파일의 MIME 타입 스트링
************************************************************************/
char* GetContentType(char* filename)
{
char retvalue[SMA_BUFFSIZE];

for(UINT i = 0; i &lt; strlen(filename); i++)
*(filename+i) = tolower( *(filename+i) );

if ( strstr(filename, ".html") != NULL || strstr(filename, ".htm") != NULL )
sprintf(retvalue, "Content-type:%s\r\n\r\n", "text/html");

if ( strstr(filename, ".txt") != NULL )
sprintf(retvalue, "Content-type:%s\r\n\r\n", "text/plain");

if ( strstr(filename, ".jpeg") != NULL || strstr(filename, ".jpg") != NULL )
sprintf(retvalue, "Content-type:%s\r\n\r\n", "image/jpeg");

if ( strstr(filename, ".png") != NULL )
sprintf(retvalue, "Content-type:%s\r\n\r\n", "image/pjpeg");

if ( strstr(filename, ".gif") != NULL )
sprintf(retvalue, "Content-type:%s\r\n\r\n", "image/gif");

if ( strstr(filename, ".bmp") != NULL )
sprintf(retvalue, "Content-type:%s\r\n\r\n", "image/x-xbitmap");

return retvalue;
}

/************************************************************************
GetContentLength 요청 받은 파일의 크기를 바이트 단위로 리턴한다. (in byte)

@ fp 요청 받은 파일의 포인터

# return file size (in byte)
************************************************************************/
int GetContentLength(FILE* fp)
{
if (fp == NULL) return 0;

unsigned int length = 0;
char buf[HUG_BUFFSIZE];
while ( !feof(fp) )
{
length += fread(buf, sizeof(char), sizeof(buf), fp);
}
fseek(fp, 0, SEEK_SET); //rewind(fp);

return length;
}

/************************************************************************
ErrorHandling 합당한 에러메시지를 출력하며 프로그램을 종료한다.

@ message 프로그램 에러 메시지
************************************************************************/
void ErrorHandling(const char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}


윈도우 환경에서 동작하는 서버입니다. 약간의 수정을 하면 리눅스 환경에서도 사용 가능함.
TRACKBACK 0 AND COMMENT 0

열혈강의TCP/IP 소켓 프로그래밍

네트워크 숙제 및 이번학기 내 프로젝트 진행을 위해서 소켓 프로그래밍을 공부하면서, 보게된 책이다.

정가는 25,000원이나, 새거같은 중고서적으로 7,000원에 구입했다. -_-;

책의 내용은 소켓을 처음접하는 사람에게 아주 적합하게 구성되어있고, 만약 TCP, UDP 에 대한 이론적인 지식이 있고, 쓰레드 및 프로세스에 관련된 개념들만 있다면 가벼운 마음으로 빠르게 읽을 수 잇는 책이었다.

무엇보다 마음에 드는 것은 소스인데, 소스가 단순하며 동일한 기능의 프로그램을 서로다른 구현법으로 접근해서 나가는 방식이기 때문에 굉장히 좋다.

책의 전반에 걸쳐서 에코서버, 클라이언트를 작성하며, 중간중간에 프로세스나 입출력 함수에 관한 예제를 따로 첨부되있다.

저자는 독자를 거의 컴맹 수준(프로그래머를 기준으로 -_-)으로 놓고 설명을 했기 때문에 쓰레드 및 TCP에 대해서 약간의 지식이 있는 상태에서 책을 본다면 지루하게 느껴질 수도 잇다.

초보자를 위한 책인 만큼 플랫폼을 유닉스, 윈도우에 관련하여 모두 설명을 하며, 두가지 플랫폼의 공통점과 차이점을 알려줄 수 잇도록 많이 배려한 책이다.

단점이라 한다면 앞에서도 말했듯이 시스템 프로그래밍을 약간 해본 사람이라면 지루할 정도로 소켓 프로그래밍 이외의 내용(동기화 및 표준 IO)을 많이 다루고 잇기 때문에 빠른시간내에 주파하려는 사람이 볼만한 책은 아닌듯 하다.

7,000원에 사본 사람으로서 -_-;; 만족한다 ㅋㅋ

입문서로 이만한 책이 없을듯~~~

빠른 시일내에 소켓프로그램에 대한 지식을 습득하려한다면???

more..

TRACKBACK 0 AND COMMENT 0

오늘 드디어 이번학기의 첫번째 레포트를 끝냈습니다.

저의 경우에는 레포트 하나를 쓰는데도 적게는 7~10시간 가량을 투자하기 때문에 항상 레포트를 쓸때마다 진이 빠지고는 합니다. 더구나 근 3달만에 처음으로 만드는 포멀한 문서인지라서 영 글의 구성이 떠오르질 않아서 더욱 힘들었습니다.

어쨋든 레포트를 끝냈다는 기쁨이 먼저 오네요.

과정에서 한번은 파일이 깨졌다는 메시지를 격기도 하고.. ^^; 이번에 MS Word 에 문서 복구 기능이라는 것을 처음으로 써봤습니다. (어디가 깨졌던 것인지를 모르겠지만.. 거의 원본 제가 작성한 그대로 나오더군요.)

드디어 학기가 시작된 기분이 듭니다.

이제 다음레포트로!!!

웹서버 만들러가쉐~

TRACKBACK 0 AND COMMENT 0

2학기 데통시간

-_- 교수님께 세마포어 관련 질문으로 건방지다는 말을 듣고... ;;

공부해서 총점 97 학점 A+ 를 받았다. (사실 필 받았다-_- 이런걸 보면 역시나 전형적인 A形;;;)

그리고 다시 듣는다. 네트워크 ...

이번에는 첫수업에 또 말쌈;;

"거참 넌 3학년인데 왜 이거 듣노~~ 니가 노트북 가저와~라"

ㅡ,.ㅡ;;

나랑 원수지신건가 컥;;


여하튼 프로젝트 일정이 나왔다. 프로젝트는 총 4가지..

1. ethereal 을 통한 TCP/IP 패킷 분석

2. winsock 을 이용한 webserver 제작

3. winsock 을 이용한 패킷 분석기 제작

4. web proxy 제작


ㅡㅡ 뭐 난이도는 생각보다는 별로 안어려울듯;;

ㅋㅋ 교수님이랑 원수진듯 말해도 -_- 이만큼 깔끔한 프로젝트 나오는 과목이 없다;;;

(대체로 프로젝트 주는 과목은 스펙이 너저분해서.. 시작부터 짜증난다.)

자자~ 오늘도 열심히!!!

TRACKBACK 0 AND COMMENT 0

ARTICLE CATEGORY

분류 전체보기 (782)
Re: myself (441)
Favorite things (241)
CS&E (71)
Portfolio (22)
삼성SDS (0)

CALENDAR

«   2008/07   »
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

ARCHIVE