zoukankan      html  css  js  c++  java
  • WebService的简单实现

    WebService的简单实现

    一、socket主机创建和使用过程

    1、socket()//创建套接字

    2、Setsockopt()//将套接字属性设置为允许和特定地点绑定

    3、Bind()//将套接字绑定特定地址端口

    4、Listen()//打开监听端口属性

    以下重复进行

    5、Accept()//接收客户端的连接请求

    6、Read()//从客户端读数据

    7、Write()//将处理好的结果发送给客户端

    二、HTTP传输协议

    基于socketTCP通信,按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请求信息,发送网页文件。处理404403等错误。

    *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服务器的地址

    portweb服务器的端口

    @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, 0, 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 " ); exit(101); };

    res = listen(res_socket,5);

    if(res) { printf( "listen port is error ; " ); 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, 0, MAX);

    sprintf(buf, "HTTP/1.0 %d %s ", status, s_status);

    sprintf(buf, "%sServer: Reage Web Server ", buf);

    sprintf(buf, "%sContent-Type: %s ", buf, filetype);

    write(conn_socket, buf, strlen(buf));

    /*

    @description:向客户端发送错误页面信息

    @parameter

    conn_socket:套接字描述符。

    status:http协议的返回状态码。

    @s_status:http协议的状态码的含义

    @filetype:向客户端发送的文件类型

    @msg:错误页面信息内容

    */

    void send_page_error(int conn_socket, int status, char *s_status, 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, status, s_status, "text/html");

    write(conn_socket, buf, 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 ");

    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 ");

    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, 404, "Not found", "Not found<br/> Reage couldn't read the file ");

    return 0;

    }

    buf[MAX-1] = 0;//将文件内容缓冲区最后的位设置位结束标志。

    //发送文件的内容

        while( (tmp= read(f, buf, MAX-1)) && EOF != tmp ){

    write(conn_socket, buf, 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 ");

    line = 0;

    //从客户端获取请求信息

    while(0 == (tmp = read( conn_socket, buf, MAX-1) ) || tmp != EOF ){

    buf[MAX-1]=0;

    break;//我只使用了第一行的请求信息,所以丢弃其他的信息

      } 

    //send_http_head(conn_socket, 200, "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(" ");

    exit(0);

    }

    ======================================================================


  • 相关阅读:
    maven安装以及eclipse配置maven
    jquery 图片文件转base64 显示
    Java 解析Excel文件为JSON
    Dropwizard框架入门
    使用Spring Security和OAuth2实现RESTful服务安全认证
    SQL语句大小写是否区分的问题,批量修改整个数据库所有表所有字段大小写
    13个可实现超棒数据可视化效果的Javascript框架
    C#创建数字证书并导出为pfx,并使用pfx进行非对称加解密
    C#使用RSA证书文件加密和解密示例
    C# 中使用 RSA加解密算法
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3192081.html
Copyright © 2011-2022 走看看