利用socket编写简单的web 服务器

 

项目名称:编写简单的web 服务器

主要目的:练习socket 编程、socket并发服务器

可行性分析:

时间 :2天;

涉及知识:socket 编程、进程或线程的应用、web 服务器的服务形式

需求分析:

1、客户端向服务器发送请求;

2、服务器对请求进行应答;

3、服务器对不规范的域名进行纠正,发送到客户端;

4、服务器遍历目录,若没找到请求的文件或目录,提示客户端东西没找到

5、若存在,服务器向客户端发送请求的服务;

6、关闭链接

7、可同时进行多客户端的连接

8、动态功能,请求的数据具有新的位置且更改是永久的(保留功能)

概要设计:

客户端用IE代替

服务器端阻塞等待

clientHandler()处理收发

详细设计:

1、写一个服务器程序main.c;

2、clientHandler()函数:

取得客户端请求的内容;

从取得内容中分离出请求的文件路径;

遍历查找客户端请求的内容,在服务器端是否存在;

若存在,则把内容读到客户端

不存在,提示客户端

编码:

在链接http://download.csdn.net/source/1261937

测试:

用 网管大师(追踪者)-数据包捕获器 V 1.281 专用版 抓包查看各种数据

(网管大师(追踪者)-数据包捕获器 V 1.281 专用版.rar 链接http://download.csdn.net/source/1261950

打开保存的Google 网页、ifeng 网页

打开一些文本文件

打开一些图片

维护:

相关知识:

stat  函数:取得文件的属性

例:

#include <sys/stat.h>

#inlcude <unistd.h>

int main()

{

struct stat buf;

stat("/etc/passwd", &buf);

printf("/etc/passwd  file size = %d /n", buf.st_size);

}

http状态指示码查看

http://blog.csdn.net/xiaozhi_su/archive/2009/04/30/4140426.aspx

客户端发给服务器的请求信息(其第一句必须要有,且其行末必须是回车换行):

GET /index.html HTTP/1.1     // 其中index.html 是请求的文件

Accept:image/gif.image/jpeg,*/*

Accept-Language:zh-cn

Connection:Keep-Alive

Host:localhost

Accept-Encoding:gzip,deflate

服务器发给客户端的应答信息:(可选的)

char *resp_head = "HTTP/1.1 200 OK/r/n" /

"Content-Type: text/html/r/n" /

"Content-Length:%ld/r/n" /

"/r/n";

char *not_found = "HTTP/1.1 404 Not Found/r/n" /

"Content-Type: text/html/r/n" /

"Content-Length: 40/r/n" /

"/r/n" /

"<HTML><BODY>File not found</BODY></HTML>";

char *bad_request = "HTTP/1.1 400 Bad Request/r/n" /

"Content-Type: text/html/r/n" /

"Content-Length: 39/r/n" /

"/r/n" /

"<h1>Bad Request (Invalid Hostname)</h1>";

char *moved_permanently =

"HTTP/1.1 301 Moved Permanently/r/n"/

"Content-Length: 147/r/n" /

"Content-Type: text/html/r/n" /

"Location: %s/r/n" /

"/r/n" /

"<head><title>Document Moved</title></head><body><h1>Object Moved</h1>This document may be found <a HREF=/"%s/">here</a></body>";

用 fprintf 或 sprintf 函数往char *resp_head 写入格式化数据 %ld

fprintf用法: 

FILE *fp = fdopen(connfd, “w”); //connfd 为由 accept 返回的句柄,转换为文件指针

fprintf(fp, resp_head,  buf.st_size);    //buf.st_size 由stat 函数取得

fflush(fp); // 冲出到客户端

Sprintf用法:

Char buf[4096];

sprintf(buf,  resp_head,  buf.st_size);   // 注意buf 元素个数要比  strlen(resp_head) 大

write(connfd, buf, strlen(buf));

用进程实现并发服务器的核心代码:

先要理解的两点:

关闭socket创建的套接字将导致服务器无法继续接受新的连接,但不会影响已经建立的连接

关闭accept返回的套接字将导致它所代表的连接被关闭,但不会影响服务器的监听

......

if((pid = fork()) == 0)

 {

// Child close listening socket

close(sockfd);

ClientHandler(&connfd);

// Process done with this client, close it

close(connfd);

// Child exit

exit(0);

else 

{

// Parent close the accepted connection

close(connfd);

}

用线程实现的并发服务器核心代码

void *Client_Process(void *arg)// 客户端服务程序

{

int acptSock = (int)arg;

ClientHandler(&acptSock);

close(acptSock);

return;

}

acptSock = accept(lstnSocket,

(struct sockaddr *)&pin,

&address_size);

if(acptSock > 0)

{

          pthread_create(&thread_id, NULL,

          (void *)Client_Process,

          (void *)acptSock);

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值