20145211《信息安全系统设计基础》实验五 网络通信
课程:信息安全系统设计基础
班级:1452 1453
姓名:黄志远 王亦徐
学号:20145211 20145311
实验日期:2016.12.1实验时间:10:10-12:25
实验名称:外设驱动程序设计
实验目的与要求:
1、掌握在ARM开发板实现一个简单的WEB服务器的过程。
2、学习在ARM开发板上的SOCKET网络编程。
3、学习Linux下的signal()函数的使用。实验仪器:
实验仪器 型号 数量 计算机 Lenovo 1 虚拟Linux环境 Redhat 9.0 1 Arm开发板 UP-NETARM2410-CL 1
一、实验内容
1.阅读理解源码
进入07_httpd所在的目录,使用vi编辑器理解源代码。
2.编译应用程序
使用gcc编译器,分别对文件夹下的copy.c和httpd.c进行编译,出现copy和httpd的可执行文件。
3.下载调试
使用NFS服务方式将HPPTD下载到开发板上,并拷贝测试用的网页进行调试
4.本机测试
在台式机的浏览器中输入http://192.168.0.234(234为实验板的IP地址),观察在客户机的浏览器中的链接请求结果和在开发板上的服务器的打印信息。
二、实验代码理解
httpd.c代码分析
/ * httpd.c: A very simple http server
* Copyfight (C) 2003 Zou jian guo <ah_zou@163.com>
* Copyright (C) 2000 Lineo, Inc. (www.lineo.com)
* Copyright (c) 1997-1999 D. Jeff Dionne <jeff@lineo.ca>
* Copyright (c) 1998 Kenneth Albanowski <kjahds@kjahds.com>
* Copyright (c) 1999 Nick Brok <nick@nbrok.iaehv.nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <unistd.h>
#include <ctype.h>
#include "pthread.h"
#define DEBUG
int KEY_QUIT=0;
int TIMEOUT=30; //设置闹钟秒数;
#ifndef O_BINARY
#define O_BINARY 0
#endif
char referrer[128];
int content_length;
#define SERVER_PORT 80
int PrintHeader(FILE *f, int content_type) //发送HTTP协议数据头
{
alarm(TIMEOUT);
fprintf(f,"HTTP/1.0 200 OKn"); //服务器回应http协议数据头的状态行;发送请求成功;
switch (content_type)
{
case 't':
fprintf(f,"Content-type: text/plainn"); //发送纯文本文件信息;
break;
case 'g':
fprintf(f,"Content-type: image/gifn"); //发送gif格式图片信息;
break;
case 'j':
fprintf(f,"Content-type: image/jpegn"); //发送gpeg格式图片信息;
break;
case 'h':
fprintf(f,"Content-type: text/htmln"); //发送html信息;
break;
}
fprintf(f,"Server: uClinux-httpd 0.2.2n"); //发送服务器版本信息;
fprintf(f,"Expires: 0n"); //发送文件永不过期信息;
fprintf(f,"n"); //打印换行符;
alarm(0);
return(0);
}
int DoJpeg(FILE *f, char *name) //对jpeg格式的文件进行处理;
{
char *buf;
FILE * infile;
int count;
if (!(infile = fopen(name, "r"))) { //通过文件名打开一个文件,只读属性;
alarm(TIMEOUT);
fprintf(stderr, "Unable to open JPEG file %s, %dn", name, errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,'j');//发送j类型的http协议数据头信息;
copy(infile,f); /* prints the page */
alarm(TIMEOUT);
fclose(infile);
alarm(0);
return 0;
}
int DoGif(FILE *f, char *name) //对gif格式的文件进行处理;
{
char *buf;
FILE * infile;
int count;
if (!(infile = fopen(name, "r"))) { //通过文件名打开一个文件,只读属性;
alarm(TIMEOUT);
fprintf(stderr, "Unable to open GIF file %s, %dn", name, errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,'g'); //发送g类型的http协议数据头信息
copy(infile,f); /* prints the page */
alarm(TIMEOUT);
fclose(infile);
alarm(0);
return 0;
}
int DoDir(FILE *f, char *name) //对目录进行处理;
{
char *buf;
DIR * dir;
struct dirent * dirent; //dirent不仅仅指向目录,还指向目录中的具体文件,dirent结构体存储的关于文件的信息很少,所以dirent起着一个索引的作用
if ((dir = opendir(name))== 0) { //打开一个目录;
fprintf(stderr, "Unable to open directory %s, %dn", name, errno);
fflush(f);
return -1;
}
PrintHeader(f,'h'); //发送h类型的http协议数据头信息
alarm(TIMEOUT);
fprintf(f, "<H1>Index of %s</H1>nn",name);
alarm(0);
if (name[strlen(name)-1] != '/') { //若名字的后面没有/则默认加上 /;
strcat(name, "/");
}
while(dirent = readdir(dir)) { //读取目录;
alarm(TIMEOUT);
fprintf(f, "<p><a href="/%s%s">%s</p>n", name, dirent->d_name, dirent->d_name);
alarm(0); //发送目录信息;
}
closedir(dir);
return 0;
}
int DoHTML(FILE *f, char *name)
{
char *buf;
FILE *infile; //定义文件流指针
int count;
char * dir = 0;
if (!(infile = fopen(name,"r"))) { //通过文件名打开一个文件,只读属性;
alarm(TIMEOUT);
fprintf(stderr, "Unable to open HTML file %s, %dn", name, errno); //打印打开文件失败信息;
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,'h'); //发送http协议数据报;f表示客户连接的文件流指针用于写入http协议数据头信息;
copy(infile,f); /* prints the page */ //将打开的文件内容通过发送回客户端;
alarm(TIMEOUT);
fclose(infile);
alarm(0);
return 0;
}
int DoText(FILE *f, char *name) //纯文本文件的处理;
{
char *buf;
FILE *infile; //定义文件流指针;
int count;
if (!(infile = fopen(name,"r"))) { //通过文件名打开一个文件,只读属性
alarm(TIMEOUT);
fprintf(stderr, "Unable to open text file %s, %dn", name, errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,'t'); //发送t类型的http协议数据头信息;
copy(infile,f); /* prints the page */
alarm(TIMEOUT);
fclose(infile);
alarm(0);
return 0;
}
int ParseReq(FILE *f, char *r)
{
char *bp; //定义指针bp;
struct stat stbuf;
char * arg; //参数指针;
char * c;
int e;
int raw;
#ifdef DEBUG
printf("req is '%s'n", r); //打印请求命令;例如:GET /img/baidu_sylogo1.gif HTTP/1.1rn
#endif
while(*(++r) != ' '); /*skip non-white space*/ //判断buf中的内容是否为空跳过非空白;
while(isspace(*r)) //判断r所在位置的字符是否为空格若为空格则r指向下一个字符;
r++;
while (*r == '/') //判断r所在位置的字符是否为/若为空格则r指向下一个字符;
r++;
bp = r; //将r所指向的内容赋值给bp bp指向/之后的内容;img/baidu_sylogo1.gif HTTP/1.1rn
while(*r && (*(r) != ' ') && (*(r) != '?'))
r++;//当r不为空,并求 r不为?时r指向下一个字符
#ifdef DEBUG
printf("bp='%s' %x, r='%s' n", bp, *bp,r); //打印 r和bp的值;
#endif
if (*r == '?') //判断 r是否为 ?若为?则执行以下语句;
{
char * e; //定义指针变量;
*r = 0; //将r所在位置处的字符设为; 的ASCII码值是0
arg = r+