服务器支持多线程,一个简单的HTTP服务器(多线程)

为了更好的了解HTTP协议, 特意谢了一个简单HTTP服务器, 代码只有400行. 因为很简单, 所以效率也不怎么高,

而且支持的特性也不多, 不过也可以运行, 性能跟Apache差不多.

=============================================================================================

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define BUFFER_INIT_SIZE 512

enum {

mickey_reading_header_stage,

mickey_writing_header_stage,

mickey_writing_body_stage,

mickey_closing_stage

};

enum {

mickey_http_ok,

mickey_http_notfound,

mickey_http_error

};

enum {

mickey_method_get,

mickey_method_head,

mickey_method_unknow

};

typedef struct {

char

*buff;

int

size;

int

free;

} mickey_buffer_t;

typedef struct {

int

sock;

mickey_buffer_t *request;

mickey_buffer_t *response;

int

keepalive;

int

method;

mickey_buffer_t *uri;

int

status;

int

stage;

FILE

*handle;

} mickey_connection_t;

static int srv_sock;

mickey_buffer_t *mickey_buffer_new() {

mickey_buffer_t *object;

object =

malloc(sizeof(*object));

if (object)

{

object->buff = malloc(BUFFER_INIT_SIZE + 1);

if (!object->buff) {

free(object);

return NULL;

}

object->size = BUFFER_INIT_SIZE;

object->free = BUFFER_INIT_SIZE;

}

return

object;

}

int mickey_buffer_append_length(mickey_buffer_t *buf, void

*data, int length) {

int lack,

need = 0;

char

*temp;

if (length

> buf->free) {

lack = length - buf->free;

while (need < lack)

need += BUFFER_INIT_SIZE;

temp = realloc(buf->buff, buf->size +

need + 1);

if (!temp)

return -1;

buf->buff = temp;

buf->size += need;

buf->free += need;

}

memcpy(buf->buff + (buf->size -

buf->free), data, length);

buf->free -= length;

buf->buff[buf->size -

buf->free] = '\0';

return

0;

}

int mickey_buffer_append(mickey_buffer_t *buf, void *data)

{

return

mickey_buffer_append_length(buf, data, strlen((char *)data));

}

int mickey_buffer_find_string(mickey_buffer_t *buf, char *str)

{

int idx =

buf->size - buf->free;

int slen =

strlen(str);

int i;

for (i = 0;

i < idx; i++) {

if (idx - i >= slen) {

if (!memcmp(buf->buff + i, str, slen)) return

1;

} else {

break;

}

}

return

0;

}

int mickey_buffer_length(mickey_buffer_t *buf) {

return

buf->size - buf->free;

}

void mickey_buffer_print(mickey_buffer_t *buf) {

fprintf(stderr, "%s", buf->buff);

}

void mickey_buffer_clean(mickey_buffer_t *buf) {

buf->free = buf->size;

}

void mickey_buffer_free(mickey_buffer_t *buf) {

if

(!buf)

return;

if

(buf->buff)

free(buf->buff);

free(buf);

}

int mickey_header_finish(mickey_connection_t *conn) {

int end =

conn->request->size -

conn->request->free;

if

(conn->request->buff[end - 1] == '\n'

&&

conn->request->buff[end - 2] == '\r'

&&

conn->request->buff[end - 3] == '\n'

&&

conn->request->buff[end - 4] ==

'\r')

return 1;

return

0;

}

void mickey_parse_header(mickey_connection_t *conn) {

char

*eol;

char

method[16], uri[256], protocol[32];

eol =

strchr(conn->request->buff,

'\n');

if (eol ==

NULL) {

conn->stage = mickey_closing_stage;

return;

}

if (*(eol-1)

== '\r')

*(eol-1) = '\0';

*eol =

'\0';

sscanf(conn->request->buff, "s %6s

2s", method, uri, protocol);

if

(!strcmp(method, "GET")) {

conn->method = mickey_method_get;

} else if

(!strcmp(method, "HEAD")) {

conn->method = mickey_method_head;

} else

{

conn->method = mickey_method_unknow;

}

mickey_buffer_append(conn->uri, ".");

mickey_buffer_append(conn->uri, uri);

if

(mickey_buffer_find_string(conn->uri, "..")) {

fprintf(stderr, "[x] mickey found connection header exists

(..)\n");

conn->stage = mickey_closing_stage;

}

}

void connection_reading_header(mickey_connection_t *conn)

{

char

buff[1024];

int

nrecv;

nrecv =

read(conn->sock, buff, 1024);

if (nrecv

> 0) {

mickey_buffer_append_length(conn->request, buff,

nrecv);

if (mickey_header_finish(conn)) {

mickey_parse_header(conn);

conn->stage = mickey_writing_header_stage;

}

} else

{

fprintf(stderr, "[x] mickey cannot read data from

connection.\n");

conn->stage = mickey_closing_stage;

}

}

void connection_make_header(mickey_connection_t *conn) {

struct stat

stat_buf;

if

(stat(conn->uri->buff,

&stat_buf) == -1) {

conn->status = mickey_http_notfound;

mickey_buffer_append(conn->response, "HTTP/1.0 404

Not Found\r\n");

} else

{

if (S_ISDIR(stat_buf.st_mode)) {

mickey_buffer_append(conn->uri, "index.html");

if (stat(conn->uri->buff,

&stat_buf) == -1) {

conn->status = mickey_http_notfound;

mickey_buffer_append(conn->response, "HTTP/1.0 404

Not Found\r\n");

} else {

char content_length[256];

conn->handle =

fopen(conn->uri->buff, "r");

if (!conn->handle) {

mickey_buffer_append(conn->response, "HTTP/1.0 500

Internal Server Error\r\n");

} else {

mickey_buffer_append(conn->response, "HTTP/1.0 200

OK\r\n");

sprintf(content_length, "Content-Length: %d\r\n",

stat_buf.st_size);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值