20145337 《信息安全系统设计基础》实验五 网络通信
北京电子科技学院(BESTI)
实 验 报 告
课程:信息安全系统设计基础 班级: 1453
姓名:马月 吉东云
学号:20135319 20135328
成绩: 指导教师: 娄嘉鹏 实验日期:11.24
实验密级: 预习程度: 实验时间:10:00—12:00
仪器组次: 必修/选修:必修 实验序号:5
实验名称:网络通信
实验目的与要求:
- 掌握在ARM开发板实现一个简单的WEB服务器的过程。
- 学习在ARM开发板上的SOCKET网络编程。
- 学习Linux下的signal()函数的使用。
实验仪器:
- ARM机 1台
- PC机 1台
- REDHAT 1台
一、实验内容
-
阅读理解源码
进入07_httpd所在的目录,使用vi编辑器理解源代码。 -
编译应用程序
使用gcc编译器,分别对文件夹下的copy.c和httpd.c进行编译,出现copy和httpd的可执行文件。
-
下载调试
使用NFS服务方式将HPPTD下载到开发板上,并拷贝测试用的网页进行调试 -
本机测试
在台式机的浏览器中输入http://192.168.0.121,观察在客户机的浏览器中的链接请求结果和在开发板服务器上的打印信息。
二、代码理解
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 OK\n");
switch (content_type)
{
case 't':
fprintf(f,"Content-type: text/plain\n");
break;
case 'g':
fprintf(f,"Content-type: image/gif\n");
break;
case 'j':
fprintf(f,"Content-type: image/jpeg\n");
break;
case 'h':
fprintf(f,"Content-type: text/html\n");
break;
}
fprintf(f,"Server: uClinux-httpd 0.2.2\n");
fprintf(f,"Expires: 0\n");
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, %d\n", name, errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,'j');
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, %d\n", name, errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,'g');
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;
if ((dir = opendir(name))== 0) {
fprintf(stderr, "Unable to open directory %s, %d\n", name, errno);
fflush(f);
return -1;
}
PrintHeader(f,'h');
alarm(TIMEOUT);
fprintf(f, "<H1>Index of %s</H1>\n\n",name);
alarm(0);
if (name[strlen(name)-1] != '/') {
strcat(name, "/");
}
while(dirent = readdir(dir)) {
alarm(TIMEOUT);
fprintf(f, "<p><a href=\"/%s%s\">%s</a></p>\n", name, dirent->d_name, dirent->d_name);
alarm(0);
}
closedir(dir);
return 0;
}
int DoHTML(FILE *f, char *name)
//发送 HTML 文件内容
//参数一写入文件数据信息
//参数二客户请求的文件名
{
char *buf;
FILE *infile;
int count;
char * dir = 0;
if (!(infile = fopen(name,"r"))) {
alarm(TIMEOUT);
fprintf(stderr, "Unable to open HTML file %s, %d\n", name, errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,'h');
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, %d\n", name, errno);
fflush(f);
alarm(0);
return -1;
}
PrintHeader(f,'t');
copy(infile,f); /* prints the page */
alarm(TIMEOUT);
fclose(infile);
alarm(0);
return 0;
}
int ParseReq(FILE *f, char *r)
//解析客户请求,参数一表示客户连接的文件流指针
//参数二,待解析的字符串
{
char *bp;
struct stat stbuf;
char * arg;
char * c;
int e;
int raw;
ifdef DEBUG
printf("req is '%s'\n", r);
endif
while(*(++r) != ' '); /*skip non-white space*/
while(isspace(*r))
r++;
while (*r == '/')
r++;
bp = r;
while(*r && (*(r) != ' ') && (*(r) != '?'))
r++;
ifdef DEBUG
printf("bp='%s' %x, r='%s' \n", bp, *bp,r);
endif
if (*r == '?')
{
char * e;
*r = 0;
arg = r+1;
if (e = strchr(arg,' '))
{
*e = '\0';
}
} else
{
arg = 0;
*r = 0;
}
c = bp;
if (c[0] == 0x20){
c[0]='.';
c[1]='\0';
}
if(c[0] == '\0') strcat(c,".");
if (c && !stat(c, &stbuf))
{
if (S_ISDIR(stbuf.st_mode))
{
char * end = c + strlen(c);
strcat(c, "/index.html");
if (!stat(c, &stbuf))
{
DoHTML(f, c);
}
else
{
*end = '\0';
DoDir(f,c);
}
}
else if (!strcmp(r - 4, ".gif"))
DoGif(f,c);
else if (!strcmp(r - 4, ".jpg") || !strcmp(r - 5, ".jpeg"))
DoJpeg(f,c);
else if (!strcmp(r - 4, ".htm") || !strcmp(r - 5, ".html"))
DoHTML(f,c);
else
DoText(f,c);
}
else{
PrintHeader(f,'h');
alarm(TIMEOUT);
fprintf(f, "<html><head><title>404 File Not Found</title></head>\n");
fprintf(f, "<body>The requested URL was not found on this server</body></html>\n");
alarm(0);
}
return 0;
}
void sigalrm(int signo)
{
exit(0);
}
int HandleConnect(int fd)//控制连接
{
FILE *f;
char buf[160];
char buf1[160];
f = fdopen(fd,"a+");
if (!f) {
fprintf(stderr, "httpd: Unable to open httpd input fd, error %d\n", errno);
alarm(TIMEOUT);
close(fd);
alarm(0);
return 0;
}
setbuf(f, 0);
alarm(TIMEOUT);
if (!fgets(buf, 150, f)) {
fprintf(stderr, "httpd: Error reading connection, error %d\n", errno);
fclose(f);
alarm(0);
return 0;
}
ifdef DEBUG
printf("buf = '%s'\n", buf);
endif
alarm(0);
referrer[0] = '\0';
content_length = -1;
alarm(TIMEOUT);
while (fgets(buf1, 150, f) && (strlen(buf1) > 2)) {
alarm(TIMEOUT);
#ifdef DEBUG
printf("Got buf1 '%s'\n", buf1);
#endif
if (!strncasecmp(buf1, "Referer:", 8)) {
char * c = buf1+8;
while (isspace(*c))
c++;
strcpy(referrer, c);
}
else if (!strncasecmp(buf1, "Referrer:", 9)) {
char * c = buf1+9;
while (isspace(*c))
c++;
strcpy(referrer, c);
}
else if (!strncasecmp(buf1, "Content-length:", 15)) {
content_length = atoi(buf1+15);
}
}
alarm(0);
if (ferror(f)) {
fprintf(stderr, "http: Error continuing reading connection, error %d\n", errno);
fclose(f);
return 0;
}
ParseReq(f, buf);
alarm(TIMEOUT);
fflush(f);
fclose(f);
alarm(0);
return 1;
}
void* key(void* data)
{
int c;
for(;;){
c=getchar();
if(c == 'q' || c == 'Q'){
KEY_QUIT=1;
exit(10);
break;
}
}
}
int main(int argc, char *argv[])
{
int fd, s;
int len;
volatile int true = 1;
struct sockaddr_in ec;
struct sockaddr_in server_sockaddr;
pthread_t th_key;
void * retval;
signal(SIGCHLD, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGALRM, sigalrm);
chroot(HTTPD_DOCUMENT_ROOT);
printf("starting httpd...\n");
printf("press q to quit.\n");
// chdir("/");
if (argc > 1 && !strcmp(argv[1], "-i")) {
/* I'm running from inetd, handle the request on stdin */
fclose(stderr);
HandleConnect(0);
exit(0);
}
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
perror("Unable to obtain network");
exit(1);
}
if((setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&true,
sizeof(true))) == -1) {
perror("setsockopt failed");
exit(1);
}
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(SERVER_PORT);
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(s, (struct sockaddr *)&server_sockaddr,
sizeof(server_sockaddr)) == -1) {
perror("Unable to bind socket");
exit(1);
}
if(listen(s, 8*3) == -1) { /* Arbitrary, 8 files/page, 3 clients */
perror("Unable to listen");
exit(4);
}
pthread_create(&th_key, NULL, key, 0);
/* Wait until producer and consumer finish. */
printf("wait for connection.\n");
while (1) {
len = sizeof(ec);
if((fd = accept(s, (void *)&ec, &len)) == -1) {
exit(5);
close(s);
}
HandleConnect(fd);
}
pthread_join(th_key, &retval);
}
三、遇到的问题及解决过程
- 在实验中修改了makefile,但还是不能make
- 解决方案:和其他同学进行比对,再次修改makefile,成功make,得到copy及httpd