代码拉取完成,页面将自动刷新
#include <dirent.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <mstring.h>
#include <mime.h>
int run = 1;
//当按下ctrl-c时,执行此函数
void stop(int sig)
{
if (sig == SIGINT)
{
run = 0;
}
}
//将socket设置成非阻塞模式
void setSocketNIO(int sock)
{
int flag = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flag | O_NONBLOCK);
}
//将sock注册到efd指定的epoll中
void registerSocket(int efd, int sock)
{
struct epoll_event ev;
ev.data.fd = sock;
ev.events = EPOLLIN || EPOLLET;
epoll_ctl(efd, EPOLL_CTL_ADD, sock, &ev);
}
//接受客户端连接并将连接注册到epoll
void acceptSock(int efd, int sock)
{
struct sockaddr_in cli;
int len = sizeof(cli);
int c = accept(sock, (struct sockaddr *)&cli, &len);
setSocketNIO(c);
registerSocket(efd, c);
}
//关闭并将socket从epoll中移除
void removeSock(int efd, int sock)
{
close(sock);
epoll_ctl(efd, EPOLL_CTL_DEL, sock, NULL);
}
//处理客户端连接
//根据url向客户端返回文件
void handle(int efd, int sock)
{
char ch;
int status = 0;
int isHeader = 1;
MString url = newString(), surl = newString();
char* curDir = getcwd(NULL, 0);
addRawString(&url, curDir);
free(curDir);
//处理request header
while (isHeader && (read(sock, &ch, sizeof(ch)) > 0 || errno == EAGAIN))
{
switch (status)
{
case 0:
if (ch == ' ')
{
status = 1;
}
else if (ch == '\n')
{
status = 3;
}
else if (ch == ':')
{
status = 5;
}
break;
case 1:
if (ch == ' ')
{
status = 2;
}
else if (ch == '\n')
{
status = 3;
}
else
{
addChar(&url, ch);
addChar(&surl, ch);
}
break;
case 2:
if (ch == '\n')
{
status = 3;
}
break;
case 3:
if (ch == '\r')
{
status = 4;
}
else
{
status = 0;
}
break;
case 4:
isHeader = 0;
break;
case 5:
if (ch == '\n')
{
status = 3;
}
else if (ch == ' ')
{
status = 6;
}
else
{
status = 7;
}
break;
case 6:
if (ch == '\n')
{
status = 3;
}
else
{
status = 7;
}
break;
case 7:
if (ch == '\n')
{
status = 3;
}
break;
}
}
struct stat buf;
stat(url.data, &buf);
if (access(url.data, 0) == 0 && S_ISREG(buf.st_mode))
{
FILE *fp = fopen(url.data, "rb");
fseek(fp, 0, SEEK_END);
long fileSize = ftell(fp);
rewind(fp);
MString ans = newString(), length = numToMStr(fileSize);
char *buffer = (char *)malloc(fileSize);
fread(buffer, fileSize, 1, fp);
fclose(fp);
addRawString(&ans, "HTTP/1.1 200 OK\r\nCache-Control: no-store\r\nContent-Type: ");
addRawString(&ans, getMimeType(url.data));
addRawString(&ans, "\r\nContent-Length: ");
addMString(&ans, length);
addRawString(&ans, "\r\n\r\n");
addRawString(&ans, buffer);
free(buffer);
write(sock, ans.data, ans.ptr);
freeString(ans);
freeString(length);
}
else if (access(url.data, 0) == 0 && S_ISDIR(buf.st_mode))
{
MString ans = newString(), data = newString();
addRawString(&ans, "HTTP/1.1 200 OK\r\nCache-Control: no-store\r\nContent-Type: text/html\r\nContent-Length: ");
addRawString(&data, "<!DOCTYPE html><html><head><meta charset=\"utf-8\" /></head><body><ul>");
struct dirent *filename;
DIR* dp = opendir(url.data);
while(filename = readdir(dp))
{
if (strcmp(filename->d_name, "..") != 0 && strcmp(filename->d_name, ".") != 0)
{
addRawString(&data, "<li><a href=\"");
addMString(&data, surl);
addRawString(&data, filename->d_name);
addRawString(&data, "\">");
addRawString(&data, filename->d_name);
addRawString(&data, "</a></li>");
}
}
addRawString(&data, "</ul></body></html>");
MString length = numToMStr(data.ptr);
addMString(&ans, length);
addRawString(&ans, "\r\n\r\n");
addMString(&ans, data);
write(sock, ans.data, ans.ptr);
freeString(ans);
freeString(data);
freeString(length);
}
else
{
char* ans = "HTTP/1.1 404 Not Found\r\nCache-Control: no-store\r\nContent-Type: text/html\r\nContent-Length: 23\r\n\r\n<h1>page not found</h1>";
write(sock, ans, strlen(ans));
}
freeString(url);
freeString(surl);
}
int main()
{
signal(SIGINT, stop); //按ctrl-C后停止程序
int epl = epoll_create(1);
//创建服务器socket
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
perror("创建服务器socket失败");
close(epl);
return -1;
}
setSocketNIO(sock);
//对socket进行监听绑定
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8080);
serverAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
int res = bind(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (res == -1)
{
perror("绑定服务器socket失败");
close(sock);
close(epl);
return -1;
}
listen(sock, 20);
registerSocket(epl, sock);
//处理客户端连接
while (run)
{
struct epoll_event events[50];
int n = epoll_wait(epl, events, 50, 0);
if (n < 0)
{
perror("epoll error");
close(sock);
close(epl);
return -1;
}
for (int i = 0; i <= n && run; i++)
{
int fd = events[i].data.fd;
if (fd == sock)
{
acceptSock(epl, fd);
}
else if (events[i].events & EPOLLHUP)
{
removeSock(epl, fd);
}
else if(events[i].events & EPOLLIN)
{
handle(epl, fd);
}
}
}
close(sock);
close(epl);
return 0;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。