[socket programming] 간단한 webserver 구현
2020. 12. 11. 22:49ㆍCS/네트워크
webserver.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
void error_handling(char *message);
int main(int argc, char *argv[]){
int sock_serv;
int sock_clnt;
int port;
struct sockaddr_in addr_serv;
struct sockaddr_in addr_clnt;
char buffer[1024];
char path[1024]; //path 경로 설정
char html[1024];
if(argc!=2){
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
port = atoi(argv[1]);
sock_serv = socket(PF_INET, SOCK_STREAM, 0);
setsockopt(sock_serv, SOL_SOCKET, SO_REUSEADDR, (struct sockaddr*)&addr_serv, sizeof(addr_serv));
if(sock_serv == -1){
error_handling("socket error");
}//소켓 생성
memset(&addr_serv, 0, sizeof(addr_serv));
addr_serv.sin_family = AF_INET;
addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
addr_serv.sin_port = htons(port);
if(bind(sock_serv, (struct sockaddr*)&addr_serv, sizeof(addr_serv)) == -1){
error_handling("bind error!");
}//바인드
if(listen(sock_serv, 5) < -1){
error_handling("listen error!");
}
while(1){
int clnt_addr_size = sizeof(addr_clnt);
sock_clnt = accept(sock_serv,(struct sockaddr*)&addr_clnt,&clnt_addr_size);
if(sock_clnt == -1){
error_handling("accept error!");
break;
}
memset(path,0,1024);
memset(buffer,0,1024); //초기화
memset(html,0,1024);
int ret;
ret = read(sock_clnt, buffer, 1024);
if(buffer[0] == '\0'){
strcpy(buffer,NULL);
}
int i = 0;
int j = 0;
int po = 0;
int check = 0;
for (i = 0; i < strlen(buffer); i++) {
if (buffer[i] == 'G' && buffer[i + 1] == 'E' && buffer[i + 2] == 'T' && buffer[i + 3] == ' ') {
for (j = 0; buffer[i + 4 + j] != ' '; j++) {
path[j] = buffer[i + 4 + j];
}
break;
}else if (buffer[i] == 'P' && buffer[i + 1] == 'O' && buffer[i + 2] == 'S' && buffer[i + 3] == 'T' && buffer[i + 4] == ' ') {
printf("star\n");
po = 1;
break;
}
}
printf("request: %s \n",path);
char *header = "HTTP/1.1 200 OK\n""Content-type: text/html\n""\n";
write(sock_clnt, header, strlen(header));
if (strcmp(path, "/") == 0 || strcmp(path, "/index.html") == 0) {
FILE* file; //파일
if((file = fopen("index.html", "r")) == NULL) {
printf("Error");
exit(1);
}
while (feof(file) == 0) {
fread(buffer, sizeof(char), 1024, file);
strcpy(html,buffer);
memset(buffer, 0, 1024);
}
fclose(file);
write(sock_clnt, html, strlen(html));
}
else if (strcmp(path, "/query.html") == 0) {
FILE* file; //파일
if((file = fopen("query.html", "r")) == NULL) {
printf("Error");
exit(1);
}
while (feof(file) == 0) {
fread(buffer, sizeof(char), 1024, file);
strcpy(html,buffer);
memset(buffer, 0, 1024);
}
fclose(file);
write(sock_clnt, html, strlen(html));
}
else if(po == 1){
char * save;
save = strstr(buffer,"name");
char * t = "</h1>\n";
char * t1 = "</body>";
char * t2 = "</html>";
strcpy(html,
"<!DOCTYPE html>\n""<html>\n""<head>\n"
"<title>POST Example</title>"
"<meta name=\"viewport\" content=\"width=device-width, initial scale=1\">"
"<link rel=\"icon\" href=\"data:,\">"
"</head>\n"
"<body>\n"
"<h2>");
strcat(html,save);
strcat(html,t);
strcat(html,t1);
strcat(html,t2);
write(sock_clnt, html, strlen(html));
}
else {
strcpy(html,
"<!DOCTYPE html>\n"
"<html lang = \"ja\">\n"
"<head>\n"
"<meta charset = \"utf-8\">\n"
"</head>\n"
"<body>\n"
"<h1>404- Not Found</h1>\n"
"</body>"
"</html>");
write(sock_clnt, html, strlen(html));
}
}
close(sock_clnt);
close(sock_serv);
return 0;
}
void error_handling(char *message){
fputs(message, stderr);
fputc('\n',stderr);
exit(1);
}
index.html
<!DOCTYPE html>
<html>
<head>
<title>My Web Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="data:,">
</head>
<body>
<h1>Welcome to My Web Page!</h1>
</body>
</html>
query.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>POST Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="data:,">
</head>
<body>
<h2>Example of sending data using POST</h2>
<form action="/sample" method="post">
Name:
<input type="text" name="name"/><br/>
Student number:
<input type="text" name="snumber"/><p/>
<input type="submit" value="submit"/>
</form>
</body>
</html>
아쉬운 점: 404 page를 내가 입력해서 출력하는 것이 아니라 브라우저 자체의 페이지로 요청받았으면 좋았을 것
'CS > 네트워크' 카테고리의 다른 글
[socket programming] udp를 이용한 파일 전송 프로그램 (0) | 2020.12.11 |
---|---|
[socket programming] tcp 이용한 파일 전송 프로그램 (0) | 2020.12.11 |
socket programming #1 (0) | 2020.12.09 |