-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.c
221 lines (173 loc) · 6.38 KB
/
server.c
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include <stdio.h>
#include <winsock2.h>
#include <malloc.h>
#pragma comment(lib, "ws2_32.lib") //Winsock Library
#define BUFSIZE 100000
#define BUFSIZE2 400000
#define HEADER_FMT "HTTP/1.1 %d %s\r\nContent-Length: %ld\r\nContent-Type: %s\r\n\r\n"
void fill_header(char *header, int status, long len, char *type){
char status_txt[40];
switch(status){
case 200:
strcpy(status_txt, "OK");
break;
case 404:
strcpy(status_txt, "Not Found");
break;
case 500:
default:
strcpy(status_txt, "Internal Server Error");
break;
}
sprintf(header, HEADER_FMT, status, status_txt, len, type);
}
void delete_view_css() {
if (remove("view.css") == 0) {
printf("view.css deleted successfully\n");
} else {
printf("Unable to delete the file\n");
}
}
int main(int argc, char* argv[]) {
WSADATA wsaData;
int servsock;
SOCKADDR_IN servaddr;
char hello[] = "HTTP/1.1 200 OK\r\n"
"Content-Type: text/html; charset=UTF-8\r\n\r\n"
"<doctype !html><html lang=\"ko\"><head><title>Hello World</title><link rel=\"shortcut icon\" href=\"#\"></head>"
"<body><h1>Hello world!</h1></br>my name is seoyoung. this is my WebServer!</body></html>\r\n";
char szBuff[BUFSIZE2] = "\0";
// port 입력
if (argc < 2) {
printf("Usage: %s {port}\n", argv[0]);
exit(EXIT_FAILURE);
}
int port = atoi(argv[1]);
printf("[INFO] The server will listen to port: %d.\n", port);
// WSA 초기화
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("WSAStartup failed\n");
return 1;
}
// create socket
servsock = socket(AF_INET, SOCK_STREAM, 0);
if (servsock == INVALID_SOCKET) {
perror("[ERROR] can not create socket");
closesocket(servsock);
WSACleanup();
exit(EXIT_FAILURE);
}
// socket structure
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
servaddr.sin_addr.s_addr = INADDR_ANY;
// binding
if (bind(servsock, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
fprintf(stderr, "Bind failed with error: %d\n", WSAGetLastError());
closesocket(servsock);
WSACleanup();
return -1;
}
printf("bind() success\n");
// listen
if (listen(servsock, SOMAXCONN) == SOCKET_ERROR) {
printf("Listen failed with error: %d\n", WSAGetLastError());
closesocket(servsock);
WSACleanup();
return -1;
}
printf("socket() success\n");
// accept
SOCKET clisock;
struct sockaddr_in cliaddr;
int addrlen = sizeof(struct sockaddr_in);
int cli_len;
// char header[BUFSIZE] = "\0";
printf("\n++++Waiting for new connection ++++\n\n");
while (1) {
// header[BUFSIZE] = 0;
clisock = accept(servsock, (struct sockaddr *)&cliaddr, &addrlen);
if (clisock == INVALID_SOCKET) {
printf("Accept failed with error: %d\n", WSAGetLastError());
closesocket(servsock);
WSACleanup();
return -1;
}
printf("client accept() success\n");
printf("accepted connection from %s, port %d\n",
inet_ntoa(cliaddr.sin_addr), htons(cliaddr.sin_port));
cli_len = recv(clisock, szBuff, sizeof(szBuff), 0);
// 종료 조건
if(cli_len == SOCKET_ERROR){
fprintf(stderr, "recv() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
if(clisock == 0){
printf("Client closed connection\n");
closesocket(clisock);
break; // 클라이언트가 연결을 닫으면 서버 종료
}
char header[BUFSIZE2] = "\0";
if (strstr(szBuff, "GET /index.html") != NULL) {
FILE *html_file = fopen("index.html", "r");
if (!html_file) {
printf("Failed to open file\n");
fill_header(header, 200, 0, "text/html");
send(clisock, header, strlen(header), 0);
} else {
fseek(html_file, 0, SEEK_END);
long content_length = ftell(html_file);
fseek(html_file, 0, SEEK_SET);
fill_header(header, 200, content_length, "text/html");
cli_len = send(clisock, header, strlen(header), 0);
size_t bytes_read;
char chunk_header[30] = "\0";
while ((bytes_read = fread(szBuff, 1, sizeof(szBuff), html_file)) > 0) {
//cli_len = send(clisock, szBuff, bytes_read, 0);
// 청크 헤더 작성
sprintf(chunk_header, "%d\r\n", bytes_read);
send(clisock, chunk_header, strlen(chunk_header), 0);
// 청크 데이터 전송
send(clisock, szBuff, bytes_read, 0);
send(clisock, "\r\n", 1, 0);
// Delete view.css if it exists
delete_view_css();
}
// 마지막 청크 전송 (빈 청크)
send(clisock, "0\r\n\r\n", 5, 0);
}
fclose(html_file);
}
else if(strstr(szBuff, "GET / ") != NULL) {
cli_len = send(clisock, hello, sizeof(hello), 0);
fill_header(header, 200, sizeof(szBuff), "text/html");
}
else if (strstr(szBuff, "GET /favicon.ico") != NULL) {
// Ignore favicon requests and send a 404 Not Found response
cli_len = 1;
fill_header(header, 404, 0, "text/html");
send(clisock, header, strlen(header), 0);
}
else{
cli_len = 1;
send(clisock, header, strlen(header), 0);
continue;
}
printf("\nheader: %s\n", header);
printf("Bytes Received: %d, message: %s from %s\n\n", cli_len, szBuff, inet_ntoa(cliaddr.sin_addr));
// header[BUFSIZE] = "\0";
if(cli_len == SOCKET_ERROR){
fprintf(stderr, "recv() failed with error %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
// Close client socket
closesocket(clisock);
// fclose(html_file);
}
// Cleanup
closesocket(servsock);
WSACleanup();
return 0;
}