WebService的简单实现
一、socket主机创建和使用过程
1、socket()//创建套接字
2、Setsockopt()//将套接字属性设置为允许和特定地点绑定
3、Bind()//将套接字绑定特定地址端口
4、Listen()//打开监听端口属性
以下重复进行
5、Accept()//接收客户端的连接请求
6、Read()//从客户端读数据
7、Write()//将处理好的结果发送给客户端
二、HTTP传输协议
基于socket的TCP通信,按HTTP传输协议格式化传输内容。
示例:
1、客户端发送HTTP请求
GET /txt?hal=1000 HTTP/1.1
Host: localhost:1024
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:2.0) Gecko/20100101 Firefox/4.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
GET:发送HTTP请求的方法,还可以是SET或者POST
/txt?hal=1000是请求根目录下的txt文件内容并传入参数hal=1000
HTTP/1.1 表示HTTP版本是1.1
2、服务端传回HTTP响应
HTTP/1.0 200 OK
Server: Reage Web Server
Content-Type: text/html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- copyright (c) 2000-2008 Quadralay Corporation. All rights reserved. -->
<head>
<title>WebWorks Help 5.0</title>
</head>
<body>wuff</body>
</html>
前面四行(包括空行)是消息体,后面是消息。一般要指明消息体的长度,方便客户端的接收处理。
三、示例程序
======================================================================
/* *主要实现功能,处理浏览器的get请求信息,发送网页文件。处理404、403等错误。 *1.实现绑定本机机器的1024端口作为ReageWeb服务提供网页服务的端口。(避免与机器上装有web服务器产生端口冲突) *2.实现get获取网页方式。 *3.实现index.html作为网站的首页面 * 作者:Reage * blog:http://blog.csdn.net/rentiansheng */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #include <string.h> #include <sys/stat.h> #include <signal.h> #define MAX 1024 int res_socket; void app_exit(); /* @description:开始服务端监听 @parameter ip:web服务器的地址 port:web服务器的端口 @result:成功返回创建socket套接字标识,错误返回-1 */ int socket_listen( char *ip,unsigned short int port){ int res_socket; //返回值 int res,on; struct sockaddr_in address; struct in_addr in_ip; res = res_socket = socket(AF_INET,SOCK_STREAM,0); setsockopt(res_socket,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); memset(&address,sizeof(address)); address.sin_family = AF_INET ; address.sin_port =htons(port); address.sin_addr.s_addr = htonl(INADDR_ANY); //inet_addr("127.0.0.1"); res = bind( res_socket,(struct sockaddr *) &address,sizeof( address ) ); if(res) { printf( "port is used,not to repeat bind\n" ); exit(101); }; res = listen(res_socket,5); if(res) { printf( "listen port is error ;\n" ); exit( 102 ); }; return res_socket ; } /* @description:向客户端发送网页头文件的信息 @parameter conn_socket:套接字描述符。 status:http协议的返回状态码。 @s_status:http协议的状态码的含义 @filetype:向客户端发送的文件类型 */ void send_http_head(int conn_socket,int status,char *s_status,char *filetype){ char buf[MAX]; memset(buf,MAX); sprintf(buf,"HTTP/1.0 %d %s\r\n",status,s_status); sprintf(buf,"%sServer: Reage Web Server\r\n",buf); sprintf(buf,"%sContent-Type: %s\r\n\r\n",buf,filetype); write(conn_socket,strlen(buf)); } /* @description:向客户端发送错误页面信息 @parameter conn_socket:套接字描述符。 status:http协议的返回状态码。 @s_status:http协议的状态码的含义 @filetype:向客户端发送的文件类型 @msg:错误页面信息内容 */ void send_page_error(int conn_socket,char *msg){ char buf[MAX] ; sprintf(buf,"<html><head></head><body><h1> %s </h1><hr>Reage Web Server 0.01</body></head>",msg); send_http_head(conn_socket,s_status,"text/html"); write(conn_socket,strlen(buf)); } /* @description:向客户端发送文件 @parameter conn_socket:套接字描述符。 @file:要发送文件路径 */ int send_html(int conn_socket,char *file){ int f; char buf[MAX]; int tmp; struct stat file_s; //如果file为空,表示发送默认主页。主页暂时固定 if(0 == strlen(file)){ strcpy(file,"index.html"); } //如果获取文件状态失败,表示文件不存的,发送404页面,暂时404页面内容固定。 if(stat(file,&file_s) ){ send_page_error(conn_socket,404,"Not found","Not found<br/> Reage does not implement this mothod\n"); return 0; } //如果不是文件或者无读权限,发送无法读取文件 if( !(S_ISREG(file_s.st_mode)) || !(S_IRUSR & file_s.st_mode) ){ send_page_error(conn_socket,403,"Forbidden","Forbidden<br/> Reage Couldn't read the file\n"); return 0; } //发送头文件,现在只提供html页面 send_http_head(conn_socket,200,"OK","text/html" ); f = open(file,O_RDONLY); if(0 > f){ //打开文件失败,发送404页面,其实感觉发送5xx也可以的,服务器内部错误 send_page_error(conn_socket,"Not found<br/> Reage Couldn't read the file\n"); return 0; } buf[MAX-1] = 0;//将文件内容缓冲区最后的位设置位结束标志。 //发送文件的内容 while( (tmp= read(f,MAX-1)) && EOF != tmp ){ write(conn_socket,strlen(buf)); } } /* @description:提取url中可用的信息。访问的网页和数据访问方式 @parameter: conn_socket:与客户端链接的套接字 uri:要处理的url,注意不是浏览器中的url,而是浏览器发送的http请求 @resutl: */ int do_uri(int conn_socket,char *uri){ char *p; p=strchr(uri,'?'); if(p){ *p = 0; p++;} send_html(conn_socket,uri); } void ulog(char *msg){} void print(char *msg){ ulog(msg); printf(msg); } int main(int argc,char * argv[] ){ int conn_socket; int tmp ; int line ; struct sockaddr_in client_addr; char buf[MAX]; int len = sizeof(client_addr); char method[100],uri[MAX],version[100]; char pwd[1024]; res_socket = socket_listen( "127.0.0.1",1024) ; //当按ctrl+c结束程序时调用,使用app_exit函数处理退出过程 signal(SIGINT,app_exit); while(1){ conn_socket = accept( res_socket,(struct sockaddr * )&client_addr,&len ); printf("reage\n"); line = 0; //从客户端获取请求信息 while(0 == (tmp = read( conn_socket,MAX-1) ) || tmp != EOF ){ buf[MAX-1]=0; break;//我只使用了第一行的请求信息,所以丢弃其他的信息 } //send_http_head(conn_socket,"text/html"); sscanf(buf,"%s %s %s",method,uri,version); //目前只处理get请求 if(!strcasecmp(method,"get")) //send_html(conn_socket,"h.html"); do_uri(conn_socket,uri+1); close(conn_socket); } } void app_exit(){ //回复ctrl+c组合键的默认行为 signal (SIGINT,SIG_DFL); //关闭服务端链接、释放服务端ip和端口 close(res_socket); printf("\n"); exit(0); }
======================================================================
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。