查看: 11598|回复: 4

Arduino+w5100使用String类 解析GET请求

[复制链接]
  • TA的每日心情
    奋斗
    2015-10-30 10:45
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2015-11-7 21:44 | 显示全部楼层 |阅读模式
    本帖最后由 某1o 于 2015-11-7 22:35 编辑

    大家肯定用过arduino内置的webserver例程,不过客户端请求是一个字符一个字符输出的,
    没办法直接接收和处理信息,需要把这些字符连接起来再进行解析,在这里我使用了String这个类,
    来方便的完成我们需要的功能。

    首先来定义一个字符串型的变量res和一个整形变量resend
    res用来存储请求信息 resend 用来控制结束接收


    设置resend初值为1
    设置res初值为"",也就是没有东西,
    不赋初值的话可能会发生一些不可预料的事情,因为编译器不会帮你把变量的初始值设置为空。

    在接收请求之前 我们需要了解一下HTTP请求的格式:

    kittenblock中小学创客名师推荐的图形化编程软件

    GET /path/file?name=value HTTP/1.0换行符
    HOST:  myarduino.ip换行符
    

    在这里 我们只需要接收一行请求,我们最终的目的是要获取GET 和HTTP中间的请求路径和表单信息

    res接收客户端的请求

    kittenblock中小学创客名师推荐的图形化编程软件

    
    //前面省略一些代码 这些代码可以在arduinoIDE例程Webserver中找到
    char c = client.read();//从客户端读取一个字符
    //如果c接收到换行符res就停止接收,为了只读取一行请求
        if (c != '\n' && resend) {
              res += c;
            } else {
              resend = 0;
            }



    经过多次循环res接收了一行请求,会停止再接收信息,以免干扰我们进行字符串拆分
    如果要接收完整的请求 可以直接使用res += c; 去掉if语句使用。

    接下来进行字符串的切割(Arduino官网的Wiki讲的很详细 https://www.arduino.cc/en/Reference/StringObject 大家可以详细阅读一下)

    kittenblock中小学创客名师推荐的图形化编程软件

    //判断字符串"GET “和" HTTP“在res中的位置,如不存在则值是-1   !=的意思是“不等于”
    if ((res.indexOf("GET ") != -1) && (res.indexOf(" HTTP") != -1)) {
                //判断是否存在字符?
                if (res.indexOf('?') != -1) {
    //从res中截取出GET表单数据 。res.substring(起始位置,结束位置)
                  query = res.substring(res.indexOf('?') + 1, res.indexOf(" HTTP"));
    //从res中截取出请求路径
                  path = res.substring(res.indexOf("GET ") + 4, res.indexOf('?'));
                } else {
                  path = res.substring(res.indexOf("GET ") + 4, res.indexOf(" HTTP"));
                }


    res.substring(res.indexOf('?') + 1, res.indexOf(" HTTP"));
    这行代码我来解释一下 res.substring(起始位置,结束位置)就是截取一个字符串的一部分字符,从”起始位置“一直截到”结束位置“
    而括号里面的res.indexOf('?') 则是获取?这个字符在res这个字符串中最先出现的位置 +1就是?的下一个字符位置


    PS:单个字符要用''单引号括起来 多个字符则需要用""双引号括起来!


    现在GET请求就已经解析完了,path就是请求路径,query就是表单信息,
    当然,也可以进一步处理,这里不再演示。


    完整代码参考:

    kittenblock中小学创客名师推荐的图形化编程软件

    #include <SPI.h>
    #include <Ethernet.h>
    
    byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};//mac地址
    IPAddress ip(192, 168, 31, 177);//ip地址
    EthernetServer server(80);//访问端口
    String fakename="Nginx/1.8.0 (Ubuntu 12.04 LTS)";//装逼参数(伪装服务器)
    
    void setup() {
      Serial.begin(9600);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for Leonardo only
      }
      Ethernet.begin(mac, ip);
      server.begin();
      Serial.print("ip:");
      Serial.println(Ethernet.localIP());
    }
    
    
    void loop() {
      EthernetClient client = server.available();
      if (client) {
        Serial.println("new client");
        String res="" ,query="",path="";
        int resend = 1;
        boolean currentLineIsBlank = true;
        while (client.connected()) {
          if (client.available()) {
            char c = client.read();
            //Serial.write(c);
            //只读取一行
            if (c != '\n' && resend) {
              res += c;
            } else {
              resend = 0;
            }
    
            if (c == '\n' && currentLineIsBlank) {
              //判断GET头完整性
              if ((res.indexOf("GET ") != -1) && (res.indexOf(" HTTP") != -1)) {
                //判断是否存在get参数
                if (res.indexOf('?') != -1) {
                  query = res.substring(res.indexOf('?') + 1, res.indexOf(" HTTP"));
                  path = res.substring(res.indexOf("GET ") + 4, res.indexOf('?'));
                } else {
                  path = res.substring(res.indexOf("GET ") + 4, res.indexOf(" HTTP"));
                }
                
                Serial.println(res);
                Serial.println("GET:"+query);
                Serial.println("path:"+path);
                client.println("HTTP/1.1 200 OK");
                client.println("Server: "+fakename);//装逼参数
                client.println("Content-Type: text/html");
                client.println("Connection: close");  
                client.println();
                client.println("<!DOCTYPE HTML><html><head></head><body><h1>200 Success</h1>GET:"+query+"<br />PATH:"+path+"<hr /><p>"+fakename+"</p></body></html>");
                break;
              } else {
                //GET头不完整 返回错误信息
                client.println("HTTP/1.1 403 Forbidden");
                client.println("Server: "+fakename);//装逼参数(伪装服务器)
                client.println("Content-Type: text/html");
                client.println("Connection: close");  
                client.println();
                client.println("<!DOCTYPE HTML><html><head></head><body><h1>403 Forbidden</h1><hr /><p>"+fakename+"</p></body></html>");
                break;
              }
            }
              if (c == '\n') {
                // you're starting a new line
                currentLineIsBlank = true;
              }
              else if (c != '\r') {
                // you've gotten a character on the current line
                currentLineIsBlank = false;
              }
            }
          }
          // give the web browser time to receive the data
          delay(1);
          // close the connection:
          client.stop();
          Serial.println("client disconnected");
          
        }
      }
    运行效果:
    QQ截图20151107214258.png

    QQ截图20151107214101.png

    写在最后

    C语言入门参考书推荐:C Primer Plus(中文版)

    HTTP协议指南 : HTTP权威指南
  • TA的每日心情
    奋斗
    2015-10-30 10:45
  • 签到天数: 2 天

    [LV.1]初来乍到

     楼主| 发表于 2015-11-7 21:52 | 显示全部楼层
    占楼 以后更新用
  • TA的每日心情
    奋斗
    2020-4-7 14:48
  • 签到天数: 954 天

    [LV.10]以坛为家III

    发表于 2015-11-7 23:02 | 显示全部楼层
    虽然看不懂,不过知道很厉害!

    该用户从未签到

    发表于 2018-8-27 17:41 | 显示全部楼层
    请问楼主,如果我把html文件和css文件放在sd卡里面打开时能否跳转到我我html中写的网页中去?能否实现用户通过网页控制arduino?
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    热门推荐

    《Color Unit免费申请试用》
    《Color Unit免费申请试用
    COLOR 是一款颜色识别 Unit,其内部集成TCS3472彩色光数字转换器,能够将其检测到颜色
    编译时空白行出现stray '\345' in program
    编译时空白行出现stray &#
    【原创】 drawbot平面关节scara机械臂写字机 画画机器人直播...
    【原创】 drawbot平面关节
    这个项目上个月就在做了,结构和代码反反复复改了多次,加上自己又太忙,一直没来得及
    siri+小爱+小度+天猫控制灯
    siri+小爱+小度+天猫控制
    以上是颜色代码 本程序控制的是8266的 io 0 默认上电LOW 有需求可以知己改写 siri
    siri控制8266
    siri控制8266
    //本程序是操作8266的GPIO 0 口// 程序如下 #include const char* ssid = "TP-11222";
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
    快速回复 返回顶部 返回列表