流程图
![在这里插入图片描述](https://img-blog.csdnimg.cn/c7dc678ff1cc477dafb0077d6a79e8d6.png)
关键代码
void setup(pthread_attr_t * attrp)
{
pthread_attr_init(attrp);
pthread_attr_setdetachstate(attrp,PTHREAD_CREATE_DETACHED);
time(&server_started);
server_requests=0;
server_bytes_sent=0;
}
pthread_create(&worker,&attr,handle_call,fdptr);
源代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <string.h>
#define HOSTLEN 256
#define BACKLOG 1
int make_server_socket_q(int ,int);
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;
struct hostent* hp;
char hostname[HOSTLEN];
int sock_id;
sock_id=socket(PF_INET,SOCK_STREAM,0);
if(sock_id==-1)
{
return -1;
}
bzero(&saddr,sizeof(saddr));
gethostname(hostname,HOSTLEN);
printf("hostname:%s\n",hostname);
hp=gethostbyname(hostname);
bcopy((void*)hp->h_addr,(void*)&saddr.sin_addr,hp->h_length);
saddr.sin_port=htons(portnum);
saddr.sin_family=AF_INET;
if(bind(sock_id,(struct sockaddr*)&saddr,sizeof(saddr))!=0)
{
return -1;
}
if(listen(sock_id,backlog)!=0)
{
return -1;
}
return sock_id;
}
int connect_to_server(char* host,int portnum)
{
int sock;
struct sockaddr_in servadd;
struct hostent* hp;
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock==-1)
{
return -1;
}
bzero(&servadd,sizeof(servadd));
hp=gethostbyname(host);
if(hp==NULL)
{
return -1;
}
bcopy(hp->h_addr,(struct sockaddr*)&servadd.sin_addr,hp->h_length);
servadd.sin_port=htons(portnum);
servadd.sin_family=AF_INET;
if(connect(sock,(struct sockaddr*)&servadd,sizeof(servadd))!=0)
{
return -1;
}
return sock;
}
#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<dirent.h>
#include<time.h>
#include "socklib.h"
time_t server_started;
int server_bytes_sent;
int server_requests;
int http_reply(int fd,FILE**fpp,int code,char* msg,char* type,char* content)
{
FILE* fp=fdopen(fd,"w");
int bytes=0;
if(fp!=NULL)
{
bytes=fprintf(fp,"HTTP/1.0 %d %s\r\n",code,msg);
bytes+=fprintf(fp,"Content-type:%s\r\n\r\n",type);
if(content)
{
bytes+=fprintf(fp,"%s\r\n",content);
}
}
fflush(fp);
if(fpp)
{
*fpp=fp;
}else{
fclose(fp);
}
return bytes;
}
char* file_type(char* f)
{
char *cp;
if((cp=strrchr(f,'.'))!=NULL)
{
return cp+1;
}
return "";
}
int built_in(char* arg,int fd)
{
FILE* fp;
if(strcmp(arg,"status")!=0)
{
return 0;
}
http_reply(fd,&fp,200,"OK","text/plain",NULL);
fprintf(fp,"Server started:%s",ctime(&server_started));
fprintf(fp,"Total requests:%d\n",server_requests);
fprintf(fp,"Bytes sent out:%d\n",server_bytes_sent);
fclose(fp);
return 1;
}
void setup(pthread_attr_t * attrp)
{
pthread_attr_init(attrp);
pthread_attr_setdetachstate(attrp,PTHREAD_CREATE_DETACHED);
time(&server_started);
server_requests=0;
server_bytes_sent=0;
}
void skip_rest_of_header(FILE* fp)
{
char buf[BUFSIZ];
while (fgets(buf,BUFSIZ,fp)!=NULL&&strcmp(buf,"\r\n")!=0);
}
void sanitize(char* str)
{
char* src,*dest;
src=dest=str;
while (*src)
{
if(strncmp(src,"/../",4)==0)
{
src+=3;
}else if(strncmp(src,"//",2)==0)
{
src++;
}else{
*dest++=*src++;
}
}
*dest='\0';
if(*str=='/')
{
strcpy(str,str+1);
}
if(str[0]=='\0'||strcmp(str,"./")==0||strcmp(str,"./..")==0)
{
strcpy(str,".");
}
}
int not_exist(char* f)
{
struct stat info;
return(stat(f,&info)==-1);
}
void do_404(char* item,int fd)
{
http_reply(fd,NULL,404,"Not Found","text/plain","THe item you seek is not here");
}
void cannot_do(int fd)
{
http_reply(fd,NULL,501,"Not Implemented","text/plain","That command is not implemented");
}
int isadir(char* f)
{
struct stat info;
return(stat(f,&info)!=-1&&S_ISDIR(info.st_mode));
}
int do_ls(char *dir,int fd)
{
DIR* dirptr;
struct dirent *direntp;
FILE* fp;
int bytes=0;
bytes=http_reply(fd,&fp,200,"OK","text/plain",NULL);
bytes+=fprintf(fp,"Listing of Directory %s\n",dir);
if((dirptr=opendir(dir))!=NULL)
{
while(direntp=readdir(dirptr))
{
bytes+=fprintf(fp,"%s\n",direntp->d_name);
}
closedir(dirptr);
}
fclose(fp);
server_bytes_sent+=bytes;
}
int ends_in_cgi(char* f)
{
return (strcmp(file_type(f),"cgi")==0);
}
int do_cat(char* f,int fd)
{
char* extension=file_type(f);
char* content="text/plain";
FILE* fpsock, *fpfile;
int c;
int bytes=0;
if(strcpy(extension,"html")==0)
{
content="text/html";
}else if(strcmp(extension,"gif")==0)
{
content="image/gif";
}else if(strcmp(extension,"jpg")==0)
{
content="image/jpg";
}else if(strcmp(extension,"jpeg")==0)
{
content="image/jpeg";
}
fpsock=fdopen(fd,"w");
fpfile=fopen(f,"r");
if(fpsock!=NULL&&fpfile!=NULL)
{
bytes=http_reply(fd,&fpsock,200,"OK",content,NULL);
while ((c=getc(fpfile))!=EOF)
{
putc(c,fpsock);
bytes++;
}
fclose(fpfile);
fclose(fpsock);
}
server_bytes_sent+=bytes;
}
void process_rq(char *rq,int fd)
{
char cmd[BUFSIZ],arg[BUFSIZ];
if(sscanf(rq,"%s%s",cmd,arg)!=2)
{
return;
}
sanitize(arg);
if(strcmp(cmd,"GET")!=0)
{
cannot_do(fd);
}else if(built_in(arg,fd))
{
;
}
else if(not_exist(arg))
{
do_404(arg,fd);
}else if(isadir(arg))
{
do_ls(arg,fd);
}else{
do_cat(arg,fd);
}
}
void* handle_call(void* fdptr)
{
FILE* fpin;
char request[BUFSIZ];
int fd;
fd=*(int*)fdptr;
free(fdptr);
fpin=fdopen(fd,"r");
fgets(request,BUFSIZ,fpin);
printf("got a call on %d :request = %s",fd,request);
skip_rest_of_header(fpin);
process_rq(request,fd);
fclose(fpin);
}
int main(int ac,char* av[])
{
int sock,fd;
int* fdptr;
pthread_t worker;
pthread_attr_t attr;
void* handle_call(void *);
if(ac==1)
{
fprintf(stderr,"usage : tws portnum\n");
exit(1);
}
sock=make_server_socket(atoi(av[1]));
if(sock==-1)
{
perror("making socket");
exit(2);
}
setup(&attr);
while (1)
{
fd=accept(sock,NULL,NULL);
server_requests++;
fdptr=malloc(sizeof(int));
*fdptr=fd;
pthread_create(&worker,&attr,handle_call,fdptr);
}
}
图片
![在这里插入图片描述](https://img-blog.csdnimg.cn/f80e24898f7844b2923c42a75836e63a.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/a41cc7193ba748e785eda6c259f41866.png)