知识点1【cgi实现计算器案例】
2、GET的同步方式:
index.html
<html>
<head>
<title>table</title>
<meta charset="UTF-8">
<!--这是描述 js中的函数来之哪个js文件-->
<script type="text/javascript" src="00_js.js"></script>
</head>
<body>
data1:<input type="text" id="data1">
<br>
data2:<input type="text" id="data2">
<br>
结果:<label id="ret"></label>
<br>
<input type="button" value="add" onclick="calc_fun(1);">
<input type="button" value="sub" onclick="calc_fun(0);">
</body>
</html>
00_js.js
function getXMLHttpRequest()
{
var xmlhttp = null;
if (window.XMLHttpRequest)//自动检测当前浏览器的版本,如果是IE5.0以上的高版本的浏览器
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();//创建请求对象
}
else如果浏览器是底版本的
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");//创建请求对象
}
return xmlhttp;//返回请求对象
}
function calc_fun(arg)
{
//1、获取网页输入框的数据data1 data2
var data1 = document.getElementById("data1").value;
var data2 = document.getElementById("data2").value;
//判断data1 data2是否合法
if(isNaN(data1) || isNaN(data2) )
{
document.getElementById("data1").value="";
document.getElementById("data2").value="";
alert("请输入有效的数值");
return;
}
//组包请求报文url "/cgi-bin/calc.cgi?10+20" "/cgi-bin/calc.cgi?10-20"
var url="/cgi-bin/calc.cgi?";
url +=data1;
if(arg == "1")//加
{
url +="+";
}
else if(arg == "0")//减
{
url +="-";
}
url+=data2;
alert("url:"+url);
//创建一个xmlHttpRequest对象
var xmlHttp = null;
xmlHttp = getXMLHttpRequest();
//open
xmlHttp.open("GET", url, false);//false表示同步
//send
xmlHttp.send();//将请求url发送给服务器
//等待服务器的应答(同步)
if(xmlHttp.readyState == 4 && xmlHttp.status==200)
{
//获取服务器的结果
var ret = xmlHttp.responseText;
//将ret赋值给label
document.getElementById("ret").innerHTML=ret;
}
}
04_calc.c
#include<stdio.h>
#include<stdlib.h>
int main()
{
//传输HTML 文本第一行输出的内容必须是"content-type:text/html\n\n"
printf("content-type:text/html\n\n");
//获取服务器的数据 GET方式 QUERY_STRING
char *data = getenv("QUERY_STRING");//data-->"10+20"
//解析data
int data1=0,data2=0;
char ch = 0;
sscanf(data,"%d%c%d", &data1, &ch, &data2);
if(ch == '+')//加法运算
{
//将处理的结果 发送给服务器
printf("%d\n", data1+data2);
}
else if(ch == '-')//减法运算
{
//将处理的结果 发送给服务器
printf("%d\n", data1-data2);
}
return 0;
}
运行结果:
3、POST的异步方式
index.html
<html>
<head>
<title>table</title>
<meta charset="UTF-8">
<!--这是描述 js中的函数来之哪个js文件-->
<script type="text/javascript" src="01_js.js"></script>
</head>
<body>
data1:<input type="text" id="data1">
<br>
data2:<input type="text" id="data2">
<br>
POST结果:<label id="ret"></label>
<br>
<input type="button" value="add" onclick="calc_fun(1);">
<input type="button" value="sub" onclick="calc_fun(0);">
</body>
</html>
01_js.js
function getXMLHttpRequest()
{
var xmlhttp = null;
if (window.XMLHttpRequest)//自动检测当前浏览器的版本,如果是IE5.0以上的高版本的浏览器
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();//创建请求对象
}
else如果浏览器是底版本的
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");//创建请求对象
}
return xmlhttp;//返回请求对象
}
function calc_fun(arg)
{
//1、获取网页输入框的数据data1 data2
var data1 = document.getElementById("data1").value;
var data2 = document.getElementById("data2").value;
//判断data1 data2是否合法
if(isNaN(data1) || isNaN(data2) )
{
document.getElementById("data1").value="";
document.getElementById("data2").value="";
alert("请输入有效的数值");
return;
}
//POST数据是密文传输 不能将数据放入?后面
var url="/cgi-bin/calc.cgi";
//将发送给服务器的数据data
var data="";
data +=data1;
if(arg == "1")//加
{
data +="+";
}
else if(arg == "0")//减
{
data +="-";
}
data+=data2;
alert("data:"+data);
//创建一个xmlHttpRequest对象
var xmlHttp = null;
xmlHttp = getXMLHttpRequest();
//设置回调函数
xmlHttp.onreadystatechange=function(){
if(xmlHttp.readyState == 4 && xmlHttp.status==200)
{
//获取服务器的结果
var ret = xmlHttp.responseText;
//将ret赋值给label
document.getElementById("ret").innerHTML=ret;
}
}
//open POST
xmlHttp.open("POST", url, true);
//POST send 由于url没有数据 所以只能用send将data发送出去
xmlHttp.send(data);//将data发送给服务器
}
05_post.c
#include<stdio.h>
#include<stdlib.h>
int main()
{
//传输HTML 文本第一行输出的内容必须是"content-type:text/html\n\n"
printf("content-type:text/html\n\n");
//获取服务器的数据 POST方式 QUERY_STRING
//1、首先的到数据的长度
char *len = getenv("CONTENT_LENGTH");
//2、根据长度 从标准输入设备 获取内容
char data[128]="";
fgets(data,atoi(len)+1, stdin);//"10+20"
//解析data
int data1=0,data2=0;
char ch = 0;
sscanf(data,"%d%c%d", &data1, &ch, &data2);
if(ch == '+')//加法运算
{
//将处理的结果 发送给服务器
printf("%d\n", data1+data2);
}
else if(ch == '-')//减法运算
{
//将处理的结果 发送给服务器
printf("%d\n", data1-data2);
}
return 0;
}
运行结果:
4、POST的同步方式
index.html
<html>
<head>
<title>table</title>
<meta charset="UTF-8">
<!--这是描述 js中的函数来之哪个js文件-->
<script type="text/javascript" src="02_js.js"></script>
</head>
<body>
data1:<input type="text" id="data1">
<br>
data2:<input type="text" id="data2">
<br>
POST同步结果:<label id="ret"></label>
<br>
<input type="button" value="add" onclick="calc_fun(1);">
<input type="button" value="sub" onclick="calc_fun(0);">
</body>
</html>
02_js.js
function getXMLHttpRequest()
{
var xmlhttp = null;
if (window.XMLHttpRequest)//自动检测当前浏览器的版本,如果是IE5.0以上的高版本的浏览器
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();//创建请求对象
}
else如果浏览器是底版本的
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");//创建请求对象
}
return xmlhttp;//返回请求对象
}
function calc_fun(arg)
{
//1、获取网页输入框的数据data1 data2
var data1 = document.getElementById("data1").value;
var data2 = document.getElementById("data2").value;
//判断data1 data2是否合法
if(isNaN(data1) || isNaN(data2) )
{
document.getElementById("data1").value="";
document.getElementById("data2").value="";
alert("请输入有效的数值");
return;
}
//POST数据是密文传输 不能将数据放入?后面
var url="/cgi-bin/calc.cgi";
//将发送给服务器的数据data
var data="";
data +=data1;
if(arg == "1")//加
{
data +="+";
}
else if(arg == "0")//减
{
data +="-";
}
data+=data2;
alert("data:"+data);
//创建一个xmlHttpRequest对象
var xmlHttp = null;
xmlHttp = getXMLHttpRequest();
//open POST
xmlHttp.open("POST", url, false);//false 同步
//POST send 由于url没有数据 所以只能用send将data发送出去
xmlHttp.send(data);//将data发送给服务器
if(xmlHttp.readyState == 4 && xmlHttp.status==200)
{
//获取服务器的结果
var ret = xmlHttp.responseText;
//将ret赋值给label
document.getElementById("ret").innerHTML=ret;
}
}
05_post.c
#include<stdio.h>
#include<stdlib.h>
int main()
{
//传输HTML 文本第一行输出的内容必须是"content-type:text/html\n\n"
printf("content-type:text/html\n\n");
//获取服务器的数据 POST方式 QUERY_STRING
//1、首先的到数据的长度
char *len = getenv("CONTENT_LENGTH");
//2、根据长度 从标准输入设备 获取内容
char data[128]="";
fgets(data,atoi(len)+1, stdin);//"10+20"
//解析data
int data1=0,data2=0;
char ch = 0;
sscanf(data,"%d%c%d", &data1, &ch, &data2);
if(ch == '+')//加法运算
{
//将处理的结果 发送给服务器
printf("%d\n", data1+data2);
}
else if(ch == '-')//减法运算
{
//将处理的结果 发送给服务器
printf("%d\n", data1-data2);
}
return 0;
}
运行结果:
知识点2【web点灯】
了解led原理图:
点亮灯 GPIO为低电平:
GPIOA 32管脚 GPIOB 32管脚
GPIOC7--->gpio71
GPIOC11--->gpio75
GPIOC12--->gpio76
开发板上的程序 必须使用交叉编译器:arm-linux-gcc
index.html
<html>
<head>
<title>table</title>
<meta charset="UTF-8">
<!--这是描述 js中的函数来之哪个js文件-->
<script type="text/javascript" src="03_js.js"></script>
</head>
<body>
<img id="led1" src="./image/led_off.png">
<img id="led2" src="./image/led_off.png">
<img id="led3" src="./image/led_off.png">
<br>
<input type="button" value="开关" id="btn1" onclick="deal_led('led1');">
<input type="button" value="开关" id="btn2" onclick="deal_led('led2');">
<input type="button" value="开关" id="btn3" onclick="deal_led('led3');">
</body>
</html>
03_js.js
function getXMLHttpRequest()
{
var xmlhttp = null;
if (window.XMLHttpRequest)//自动检测当前浏览器的版本,如果是IE5.0以上的高版本的浏览器
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();//创建请求对象
}
else如果浏览器是底版本的
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");//创建请求对象
}
return xmlhttp;//返回请求对象
}
function deal_led(arg)//arg就是img的id led1 led2 led3
{
var url="/cgi-bin/led.cgi?";
url+=arg;
var path = document.getElementById(arg).src;
if(path.indexOf("led_off",0) != -1)
{
document.getElementById(arg).src = "./image/led_on.png";
url+=":1";
}
else if(path.indexOf("led_on",0) != -1)
{
document.getElementById(arg).src = "./image/led_off.png";
url+=":0";
}
//创建xmlhttp对象
var xmlhttp = getXMLHttpRequest();
//设置回调函数
xmlhttp.onreadystatechange=function(){
//alert("xmlHttp.readyState="+xmlHttp.readyState,+",xmlHttp.status="+xmlHttp.status);
if(xmlhttp.readyState == 4 && xmlhttp.status==200)
{
//获取服务器的结果
var ret = xmlhttp.responseText;
alert("ret="+ret);
}
}
//open
xmlhttp.open("GET",url, true);//url="/cgi-bin/led.cgi?led2:1"
//send
xmlhttp.send();
}
led.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
void led_init()
{
//判断GPIO是否在系统中打开
if(access("/sys/class/gpio/gpio71/value", F_OK))//不存在
{
system("echo 71 > /sys/class/gpio/export");//到处IO口
}
if(access("/sys/class/gpio/gpio75/value", F_OK))//不存在
{
system("echo 75 > /sys/class/gpio/export");//到处IO口
}
if(access("/sys/class/gpio/gpio76/value", F_OK))//不存在
{
system("echo 76 > /sys/class/gpio/export");//到处IO口
}
//设置IO的方向(输出 输入)
system("echo out > /sys/class/gpio/gpio71/direction");
system("echo out > /sys/class/gpio/gpio75/direction");
system("echo out > /sys/class/gpio/gpio76/direction");
//将所有的灯灭掉
system("echo 1 > /sys/class/gpio/gpio71/value");
system("echo 1 > /sys/class/gpio/gpio75/value");
system("echo 1 > /sys/class/gpio/gpio76/value");
}
void set_led(int led, int on_off)
{
//判断哪一个灯
if(led == 1)
{
//判断开关状态
if(on_off == 1)//亮
{
//io口 输出低电平
system("echo 0 > /sys/class/gpio/gpio71/value");
}
else if(on_off == 0)//灭
{
system("echo 1 > /sys/class/gpio/gpio71/value");
}
}
else if(led == 2)
{
//判断开关状态
if(on_off == 1)//亮
{
//io口 输出低电平
system("echo 0 > /sys/class/gpio/gpio75/value");
}
else if(on_off == 0)//灭
{
system("echo 1 > /sys/class/gpio/gpio75/value");
}
}
else if(led == 3)
{
//判断开关状态
if(on_off == 1)//亮
{
//io口 输出低电平
system("echo 0 > /sys/class/gpio/gpio76/value");
}
else if(on_off == 0)//灭
{
system("echo 1 > /sys/class/gpio/gpio76/value");
}
}
}
int main()
{
//传输HTML 文本第一行输出的内容必须是"content-type:text/html\n\n"
printf("content-type:text/html\n\n");
//获取服务器的数据 GET方式 QUERY_STRING
char *data = getenv("QUERY_STRING");//data-->"10+20"
//解析data="led2:1"
int led =0, on_off = 0;
sscanf(data,"led%d:%d", &led, &on_off);
//初始化设备
led_init();
//设置灯的状态
set_led(led, on_off);
return 0;
}
知识点3【路由器项目】
不同网段通信的桥梁
将我们的ubuntu作为路由器。
//ubuntu里
//1、创建一个原始套接字 用来收发数据
int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
//2、创建一个线程 用来接受网络数据recvfrom
unsigned char buf[1500]="";
int len = recvfrom(sockfd, buf);
3、判断buf中的目的mac地址 和 路由器的哪块网卡的mac相同 就表明哪块网卡收到
4、buf中帧类型0x0800提取目的IP,如果目的IP和路由器的某块网卡是同一个网段,
数据就从该网卡出去(src_mac该网卡的mac 目的mac为目的主机mac)
5、buf中帧类型0x0800提取目的IP,入宫目的IP和路由器的所有网卡都不同一个网段,
查看路由表 寻找下一跳 查看路由器的哪块网卡 和下一跳同一个网段,还数据就从
改网卡 发送到下一跳(src_mac该网卡的mac 目的mac为下一跳mac)
注意:以上目的主机或者下一跳的mac 如果没有记录记得用arp获取 并存入arp表中
2、和路由器交互(终端、网页)(创新)
3、win10配置(静态的):只需将网关设置eth0的IP
4、手机设置(静态的):ip:192.168.1.3 网关是192.168.1.2
5、虚拟的设置:
添加网卡:
设置成桥接模式:
给eth0设置指定的IP
添加新的连接:
配置成功:
基本功能完成:
如果win10 ping通 手机
手机 ping通 win10
创新:
1、多网卡 3个
2、防火墙不转发
3、动态获取ip mac
补充思路:
unsigned char phone_mac[]={};
unsigned char phone_ip[]={};
unsigned char win_mac[]={};
unsigned char win_ip[]={};
int main()
{
int sockfd = sockfd(原始套接字);
//获取网络接口
getinterface();
while(1)
{
int len = recvfrom(sokcfd, buf,sizeof(buf),0,NULL,NULL);
//转发ip报文
unsigned short mac_type = ntohs(*(unsigned short *)(buf+12));
if(mac_type == 0x0800)//转发
{
//判断 buf中的目的IP 和 路由器的哪块网卡同一个网段
unsigned char *dst_ip = buf+14+16;
int i=0;
for(i=0;i<interface_num;i++)
{
if(memcmp(dst_ip, net_interface[i].ip, 3) == 0 && \
memcmp(dst_ip, net_interface[i].ip, 4) != 0)
{
//修改buf中源mac未路由器的接口mac
memcpy(buf+6, net_interface[i].mac, 6);
//修改目的mac
#if 0
//固定
if(memcmp(dst_ip, phone_ip, 4) == 0)
memcpy(buf, phone_mac, 6);
else if(memcmp(dst_ip, win_ip, 4) == 0)
memcpy(buf, win_mac, 6);
#else
//从arp表中查找dst_ip对应的mac
unsigned char *dst_mac = find_from_arp();
if(dst_mac == NULL)
{
//发送arp请求
break;
}
else if(dst_mac != NULL)
{
memcpy(buf, dst_mac, 6);
}
#endif
my_sendto(sockfd, net_interface[i].name, buf,len, );
break;
}
}
//目的ip和路由器的所有接口都不在同一个网段
if(i == interface_num)
{
//分析路由器表
}
}
else if(mac_type == 0x0806)//arp 应答 更新arp表
{
}
}
}