您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 销售管理 > Windows下C++实现WEB服务器
自己研究了好几天终于写出来一个,哈哈,当然也从网上得到了很多的帮助拉。谢谢大家咯!这个版本还不是很完善,但Web服务器的基本框架已经出来了,还有部分的功能需要进行进一步的测试和修改。虽然说C的开发比较慢,对于程序员来说比较难以操作,但通过用C写这些很底层的东西,可以更好的了解的象java的socket中的工作原理。有一定的帮助!以下是源代码:#includewinsock.h#includesys/stat.h#includeiostreamusingnamespacestd;#defineSERVER_PORT10000//自定义的服务端口#defineHOSTLEN256//主机名长度#defineBACKLOG10//同时等待的连接个数intsendall(ints,char*buf,int*len){inttotal=0;//已经发送字节数intbytesleft=*len;//还剩余多少字节intn;while(total*len){n=send(s,buf+total,bytesleft,0);if(n==-1){break;}total+=n;bytesleft-=n;}*len=total;//返回实际发送出去的字节数returnn==-1?-1:0;//成功发送返回0失败-1}voidwrong_req(intsock){char*error_head=HTTP/1.0501NotImplemented\r\n;//输出501错误intlen=strlen(error_head);if(sendall(sock,error_head,&len)==-1){//向客户发送printf(Sendingfailed!);return;}char*error_type=Content-type:text/plain\r\n;len=strlen(error_type);if(sendall(sock,error_type,&len)==-1){printf(Sendingfailed!);return;}char*error_end=\r\n;len=strlen(error_end);if(sendall(sock,error_end,&len)==-1){printf(Sendingfailed!);return;}char*prompt_info=Thecommandisnotyetcompleted\r\n;len=strlen(prompt_info);if(sendall(sock,prompt_info,&len)==-1){printf(Sendingfailed!);return;}}boolnot_exit(char*arguments){structstatdir_info;return(stat(arguments,&dir_info)==-1);}voidfile_not_found(char*arguments,intsock){char*error_head=HTTP/1.0404NotFound\r\n;//构造404错误headintlen=strlen(error_head);if(sendall(sock,error_head,&len)==-1){//向客户端发送printf(Sendingerror!);return;}char*error_type=Content-type:text/plain\r\n;len=strlen(error_type);if(sendall(sock,error_type,&len)==-1){printf(Sendingerror!);return;}char*error_end=\r\n;len=strlen(error_end);if(sendall(sock,error_end,&len)==-1){printf(Sendingerror!);return;}charprompt_info[50]=Notfound:;strcat(prompt_info,arguments);len=strlen(prompt_info);if(sendall(sock,prompt_info,&len)==-1){//输出未找到的文件printf(Sendingerror!);return;}}voidsend_header(intsend_to,char*content_type){char*head=HTTP/1.0200OK\r\n;//正确的头部信息intlen=strlen(head);if(sendall(send_to,head,&len)==-1){//向连接的客户端发送数据printf(Sendingerror);return;}if(content_type){//content_type不为空chartemp_1[30]=Content-type:;//准备好要连接的字串strcat(temp_1,content_type);//构造content_typestrcat(temp_1,\r\n);len=strlen(temp_1);if(sendall(send_to,temp_1,&len)==-1){printf(Sendingerror!);return;}}}char*file_type(char*arg){char*temp;//临时字符串指针if((temp=strrchr(arg,'.'))!=NULL){//取得后缀returntemp+1;}return;//如果请求的文件名中没有.则返回空串}voidsend_file(char*arguments,intsock){char*extension=file_type(arguments);//获得文件后缀名char*content_type=text/plain;//初始化type='text/plain'FILE*read_from;//本地文件指针从该文件中读取.html.jpg等intreaded=-1;//每次读得的字节数if(strcmp(extension,html)==0){//发送内容为htmlcontent_type=text/html;}if(strcmp(extension,gif)==0){//发送内容为gifcontent_type=image/gif;}if(strcmp(extension,jpg)==0){//发送内容为jpgcontent_type=image/jpg;}read_from=fopen(arguments,r);//打开用户指定的文件准备读取if(read_from!=NULL){//指针不为空charread_buf[128];//读文件时的字节缓存数组send_header(sock,content_type);//发送协议头send(sock,\r\n,2,0);//再加一个\r\n不能缺少格式要求while(!feof(read_from)){//判断文件是否已经结束fgets(read_buf,128,read_from);//读取intlen=strlen(read_buf);if(sendall(sock,read_buf,&len)==-1){//发送数据printf(Sendingerror!);//出现发送错误显示到控制台继续发送continue;}}}}voidhandle_req(char*request,intclient_sock){charcommand[BUFSIZ];//保存解析到的命令字段GETPUTchararguments[BUFSIZ];//保存解析到的请求的文件strcpy(arguments,./);//注意该符号在不同操作系统的区别if(sscanf(request,%s%s,command,arguments+2)!=2){return;//解析出错在返回}printf(handle_cmd:%s\n,command);//向控制台输出此时的命令printf(handle_path:%s\n,arguments);//向控制台输出此时的请求路径if(strcmp(command,GET)!=0){//请求命令格式是否正确wrong_req(client_sock);return;}if(not_exit(arguments)){//请求的文件是否存在file_not_found(arguments,client_sock);return;}send_file(arguments,client_sock);//命令格式及请求路径正确则发送数据return;}intmake_server_socket(){structsockaddr_inserver_addr;//服务器地址结构体inttempSockId;//临时存储socket描述符tempSockId=socket(PF_INET,SOCK_STREAM,0);if(tempSockId==-1){//如果返回值为-1则出错return-1;}server_addr.sin_family=AF_INET;server_addr.sin_port=htons(SERVER_PORT);server_addr.sin_addr.s_addr=inet_addr(127.0.0.1);//本地地址memset(&(server_addr.sin_zero),'\0',8);if(bind(tempSockId,(structsockaddr*)&server_addr,sizeof(server_addr))==-1){//绑定服务如果出错则返回-1printf(binderror!\n);return-1;}if(listen(tempSockId,BACKLOG)==-1){//开始监听printf(listenerror!\n);return-1;}returntempSockId;//返回取得的SOCKET}voidmain(intargc,char*argv[]){WSADATAwsaData;if(WSAStartup(MAKEWORD(1,1),&wsaData)!=0){fprintf(stderr,WSAStartupfailed.\n);exit(1);}printf(Mywebserverstarted...\n);intserver_socket;//服务器的socketintacc_socket;//接收到的用户连接的socketintsock_size=sizeof(structsockaddr_in);structsockaddr_inuser_socket;//客户连接信息server_socket=make_server_socket();//创建服务器端的socketif(server_socket==-1){//创建socket出错printf(Serverexception!\n);exit(2);}while(true){acc_socket=accept(server_socket,(structsockaddr*)&user_socket,&sock_size);//接收连接//coutinet_ntoa(user_socket.sin_addr)endl;//测试用:-)//intnumbytes;charbuf[100];if((numbytes=recv(acc_socket,buf,99,0))==-1){perror(recv);exit(1);}//printf(buf...%s,buf);//测试用handle_req(buf,acc_socket);}}和我的上一篇文章是一起写的,呵呵,大家给提点意见啊。:-)#includewinsock.h
本文标题:Windows下C++实现WEB服务器
链接地址:https://www.777doc.com/doc-3941877 .html