Linux socket编程之web server
来源:互联网 发布:帽子品牌知乎 编辑:程序博客网 时间:2024/05/21 17:28
源码:
#include<stdio.h>#include<sys/types.h>#include<sys/stat.h>#include<string.h>#include<stdlib.h>#include<unistd.h>#include<sys/socket.h>#include<netinet/in.h>#include<netdb.h>#define BACKLOG 1#define HOSTLEN 256main(int ac, char *av[]){ int sock, fd; FILE *fpin; char request[BUFSIZ]; if ( ac == 1 ) { fprintf(stderr,"usage: ws portnum\n"); exit(1); } sock = make_server_socket( atoi(av[1]) ); if ( sock == -1 ) { printf("cannot make server_socket!\n"); exit(2); } /* main loop here */ while(1) { /* take a call and buffer it */ fd = accept( sock, NULL, NULL ); fpin = fdopen(fd, "r" ); /* read request */ fgets(request,BUFSIZ,fpin); printf("got a call: request = %s", request); read_til_crnl(fpin); /* do what client asks */ process_rq(request, fd); fclose(fpin); }}/* ------------------------------------------------------ * * read_til_crnl(FILE *) * skip over all request info until a CRNL is seen * ------------------------------------------------------ */read_til_crnl(FILE *fp){ char buf[BUFSIZ]; while(fgets(buf,BUFSIZ,fp)!= NULL && strcmp(buf,"\r\n") != 0 );}/* ------------------------------------------------------ * * process_rq( char *rq, int fd ) * do what the request asks for and write reply to fd * handles request in a new process * rq is HTTP command: GET /foo/bar.html HTTP/1.0 * ------------------------------------------------------ */process_rq( char *rq, int fd ){ char cmd[BUFSIZ], arg[BUFSIZ]; /* create a new process and return if not the child */ if ( fork() != 0 ) return; strcpy(arg, "./"); /* precede args with ./ */ if ( sscanf(rq, "%s%s", cmd, arg+2) != 2 ) return; if ( strcmp(cmd,"GET") != 0 ) cannot_do(fd); else if ( not_exist( arg ) ) do_404(arg, fd ); else if ( isadir( arg ) ) do_ls( arg, fd ); else if ( ends_in_cgi( arg ) ) do_exec( arg, fd ); else do_cat( arg, fd );}/* ------------------------------------------------------ * * the reply header thing: all functions need one * if content_type is NULL then don't send content type * ------------------------------------------------------ */header( FILE *fp, char *content_type ){ fprintf(fp, "HTTP/1.0 200 OK\r\n"); if ( content_type ) fprintf(fp, "Content-type: %s\r\n", content_type );}/* ------------------------------------------------------ * * simple functions first: * cannot_do(fd) unimplemented HTTP command * and do_404(item,fd) no such object * ------------------------------------------------------ */cannot_do(int fd){ FILE *fp = fdopen(fd,"w"); fprintf(fp, "HTTP/1.0 501 Not Implemented\r\n"); fprintf(fp, "Content-type: text/plain\r\n"); fprintf(fp, "\r\n"); fprintf(fp, "That command is not yet implemented\r\n"); fclose(fp);}do_404(char *item, int fd){ FILE *fp = fdopen(fd,"w"); fprintf(fp, "HTTP/1.0 404 Not Found\r\n"); fprintf(fp, "Content-type: text/plain\r\n"); fprintf(fp, "\r\n"); fprintf(fp, "The item you requested: %s\r\nis not found\r\n", item); fclose(fp);}/* ------------------------------------------------------ * * the directory listing section * isadir() uses stat, not_exist() uses stat * do_ls runs ls. It should not * ------------------------------------------------------ */isadir(char *f){ struct stat info; return ( stat(f, &info) != -1 && S_ISDIR(info.st_mode) );}not_exist(char *f){ struct stat info; return( stat(f,&info) == -1 );}do_ls(char *dir, int fd){ FILE *fp ; fp = fdopen(fd,"w"); header(fp, "text/plain"); fprintf(fp,"\r\n"); fflush(fp); dup2(fd,1); dup2(fd,2); close(fd); execlp("ls","ls","-l",dir,NULL); perror(dir); exit(1);}/* ------------------------------------------------------ * * the cgi stuff. function to check extension and * one to run the program. * ------------------------------------------------------ */char * file_type(char *f)/* returns 'extension' of file */{ char *cp; if ( (cp = strrchr(f, '.' )) != NULL ) return cp+1; return "";}ends_in_cgi(char *f){ return ( strcmp( file_type(f), "cgi" ) == 0 );}do_exec( char *prog, int fd ){ FILE *fp ; fp = fdopen(fd,"w"); header(fp, NULL); fflush(fp); dup2(fd, 1); dup2(fd, 2); close(fd); execl(prog,prog,NULL); perror(prog);}/* ------------------------------------------------------ * * do_cat(filename,fd) * sends back contents after a header * ------------------------------------------------------ */do_cat(char *f, int fd){ char *extension = file_type(f); char *content = "text/plain"; FILE *fpsock, *fpfile; int c; if ( strcmp(extension,"html") == 0 ) content = "text/html"; else if ( strcmp(extension, "gif") == 0 ) content = "image/gif"; else if ( strcmp(extension, "jpg") == 0 ) content = "image/jpeg"; else if ( strcmp(extension, "jpeg") == 0 ) content = "image/jpeg"; fpsock = fdopen(fd, "w"); fpfile = fopen( f, "r"); if ( fpsock != NULL && fpfile != NULL ) { header( fpsock, content ); fprintf(fpsock, "\r\n"); while( (c = getc(fpfile) ) != EOF ) putc(c, fpsock); fclose(fpfile); fclose(fpsock); } exit(0);}int make_server_socket(int portnum){ return make_server_socket_q(portnum, BACKLOG);}int make_server_socket_q(int portnum, int backlog){ struct sockaddr_in saddr; /* build our address here */ struct hostent *hp; /* this is part of our */ char hostname[HOSTLEN]; /* address */ int sock_id; /* the socket */ sock_id = socket(PF_INET, SOCK_STREAM, 0); /* get a socket */ if ( sock_id == -1 ) return -1; /** build address and bind it to socket **/ bzero((void *)&saddr, sizeof(saddr)); /* clear out struct */ gethostname(hostname, HOSTLEN); /* where am I ? */ hp = gethostbyname(hostname); /* get info about host */ /* fill in host part */ bcopy( (void *)hp->h_addr, (void *)&saddr.sin_addr, hp->h_length); saddr.sin_port = htons(portnum); /* fill in socket port */ saddr.sin_family = AF_INET ; /* fill in addr family */ if ( bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0 ) return -1; /** arrange for incoming calls **/ if ( listen(sock_id, backlog) != 0 ) return -1; return sock_id;}
编译webserver.c为web server
cc webserver.c -o webserver
运行并指定端口号5566
./webserver 5566
事先在web server的 统计目录下创建index.html
然后再浏览器中输入:
http://127.0.0.1:5566/index.html
可以看到浏览器中已经显示你的内容了
——————————————————-
两种服务器的设计方法:
DIY——服务器接收请求,自己处理工作。
代理——服务器接收请求,然后创建一个新进程来处理工作。
每种方法的优缺点:
自己做用于快速简单的任务,代理用于慢速的更加复杂的任务,使用SIGCHLD来阻止僵尸(zombie)问题
这里采用的是代理的方法。
0 0
- Linux socket编程之web server
- linux socket编程-server
- Linux下Socket编程之TCP Server端
- linux socket编程--server端
- Linux编程之socket
- linux编程之socket
- linux socket编程Server简单示例
- linux socket编程之socket()函数介绍
- linux socket网络编程之socket属性
- linux socket编程之socket()函数介绍
- linux socket编程之socket()函数介绍
- Linux学习之socket编程
- linux网络编程之Socket
- Linux 编程之 【socket】 udp
- Linux 编程 之 【socket】 getaddrinfo
- linux之socket编程总结
- Linux之UDP SOCKET 编程
- Socket网络编程之server端
- UVA 122
- Dubbo协议介绍
- 关键字
- 使用Object表示泛型
- 1027. 打印沙漏
- Linux socket编程之web server
- OpenCV 3.10+Visual Studio 2013+Camera
- 微机原理==可编程串行接口8251A(12)
- SQL整理
- AD常用快捷操作(快速过孔,快速布局等)
- eclipse中配置自动生成的注释模板
- java选择排序详解
- 修改ARP缓存表大小
- 文章标题