欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

html+php+c 实现web关灯

程序员文章站 2022-03-15 12:36:00
...

前言

一些人能够很快地学习一项新的技能并快速的进步,除了自身的努力以外常常伴有强烈的学习兴趣。一路走来,从底层硬件到应用层软件都有所接触,但却没有demo出任何有意义的小成果,十分遗憾。从本文开始,我将以自身的兴趣点出发去实现一些生活中的小demo。

远程控灯

床头有一盏台灯,每天早上出宿舍门时都得重新爬上床去关电,这样甚是麻烦。于是出现了一个远程关灯的想法。方案研究如下:

使用php的socket接口连接linux下的socket。这就需要了解一点点html, js, php的东西,实测可行。

html+php+c 实现web关灯

实现步骤

<!DOCTYPE html>
<html>
    <head>
        <title>LED Ctl</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <div style="width:100%;text-align:center">
            <form action="client.php?action=open" method="post">
                <input type="submit" value="打开">
            </form>
            <br/>
            <form action="client.php?action=close" method="post">
                <input type="submit" value="关闭">
            </form>
        </div>
    </body>
</html>

这里将按钮命令传递到php接口时耗费了很多时间,毕竟前端小白…

  • php client 端编写
<?php

$in=$_GET['action'];  

error_reporting(E_ALL);
set_time_limit(0);

$port = 2017;
$ip = "127.0.0.1";

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket < 0) 
    echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";
else 
    echo "socket create ok...\n";

echo "connect ip: '$ip' port: '$port'...\n";

$result = socket_connect($socket, $ip, $port);

if ($result < 0) 
    echo "connect failed.\nReason: ($result) " . socket_strerror($result) . "\n";
else 
    echo "connect ok...\n";

if(!socket_write($socket, $in, strlen($in))) 
{
    echo "socket_write() failed: reason: " . socket_strerror($socket) . "\n";
}
else 
{
    echo "send cmd ok...\n";
}

echo "close socket...\n";
socket_close($socket);

?>
  • linux server 端编写
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>
#include <stdio.h> 
#include <stdlib.h>     /*标准函数库定义*/    
#include <unistd.h>     /*Unix 标准函数定义*/    
#include <fcntl.h>      /*文件控制定义*/    
#include <termios.h>    /*PPSIX 终端控制定义*/    
#include <errno.h>      /*错误号定义*/    
#include <sys/types.h>     
#include <sys/stat.h> 

#define server_port 2017 //server本地端口
#define u8 unsigned char 

static int connfd = 0;//当前建立的socke描述符

/*******************************************************************  
* 名称:            start_server  
* 功能:            开启本地server,并进入数据接收阻塞模式(线程)
* 入口参数:        func(buff,len)  
                    buff - 接收数据缓冲区 
                    len  - 接收数据缓冲区的字节数
* 出口参数:        正确返回为0,错误返回为-1 
*******************************************************************/  

int start_server(void (*func)(u8 *,int))
{  
    //1.创建通信端点:套接字  
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);     
    if(sockfd < 0)  
    {  
        perror("socket can't build");  
        exit(-1);  
    }  

    //设置本地地址结构体  
    struct sockaddr_in my_addr;  
    bzero(&my_addr, sizeof(my_addr));            // 清空,保证最后8字节为0      
    my_addr.sin_family = AF_INET;                // ipv4  
    my_addr.sin_port   = htons(server_port);     // 端口  
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // ip,INADDR_ANY为通配地址其值为0  

    //2.绑定:将本地ip、端口与套接字socket相关联起来  
    int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));  
    if( err_log != 0)  
    {  
        perror("binding error");  
        close(sockfd);        
        exit(-1);  
    }  

    //3.监听,监听套接字改为被动,创建连接队列  
    err_log = listen(sockfd, 10);   
    if(err_log != 0)  
    {  
        perror("listen error");  
        close(sockfd);        
        exit(-1);  
    }     

    printf("listen client @port=%d...\n",server_port);  

    while(1)  
    {     
        struct sockaddr_in client_addr;  
        socklen_t cliaddr_len = sizeof(client_addr);         
        char cli_ip[INET_ADDRSTRLEN] = "";  

        u8 buff[512];//接受数据缓冲区
        int len;//实际接受到的数据长度

        //4.从完成连接队列中提取客户端连接  
        connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);         
        if(connfd < 0)  
        {  
            perror("accept error");  
            continue;  
        }  

        inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);  
        printf("----------------------------------------------\n");  
        printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port));  

        while((len=recv(connfd, buff, sizeof(buff), 0)) > 0) // 接收数据  
        {  
            (*func)((u8*)buff,len);//将接收到的数据传至函数指针
        }  

        close(connfd); //关闭已连接套接字  
        printf("client closed!\n");  
    }  

    close(sockfd); //关闭监听套接字  

    return 0;  
}

/*******************************************************************  
* 名称:            tcp_send_data  
* 功能:            server向client发送字节流
* 入口参数:        buff - 发送数据缓冲区 
                    len  - 发送数据缓冲区的字节数
* 出口参数:        正确返回为0,错误返回为-1 
*******************************************************************/  
int tcp_send_data(u8* buff,int len)
{
    if(send(connfd, buff, len, 0)<0)
    {
        printf("tcp send data error\n");
        exit(-1);
    }
    return 0;
}

void myfunc(u8* buffer,int len)
{
    printf("%s\n",buffer);
    if(strcmp(buffer,"open")==0)
    {
        printf("cmd : open\n");
        system("sudo ./gpio on");
    } 
    if(strcmp(buffer,"close")==0)
    {
        printf("cmd : close\n");
        system("sudo ./gpio off");
    }
    memset(buffer,0,len);
}

int main()
{
    u8* buf;
    int len;
    start_server(myfunc);
}
  • linux gpio 控制(Nanopi-T3)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#define GPIOC_BASE_ADDRESS   (0xC001C000)
#define MAP_SIZE 40

#define GPIOCOUT *(unsigned int *)base
#define GPIOCOUTENB *(unsigned int *)(base+0x04)
#define GPIOCALTFN0 *(unsigned int *)(base+0x20)

static int dev_fd;

int main(int argc, char **argv)
{
    dev_fd = open("/dev/mem", O_RDWR | O_NDELAY);
    if (dev_fd < 0)
    {
        printf("open(/dev/mem) failed.");
        return 0;
    }
    unsigned int base = (unsigned int)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, 
                                           MAP_SHARED, dev_fd, GPIOC_BASE_ADDRESS );

    //GPIO7-排针编号17
    GPIOCALTFN0 &= ~(3<<8);
    GPIOCALTFN0 |= (1<<8);
    GPIOCOUTENB |= (1<<4);

    if(strcmp(argv[1],"on")==0)
    {
        printf("turn on\n");
        GPIOCOUT |= (1<<4);
    }
    else if(strcmp(argv[1],"off")==0)
    {
        printf("turn off\n");
        GPIOCOUT &= ~(1<<4);
    }

    printf("%s\n",argv[1]);

    if(dev_fd)
        close(dev_fd);
    munmap((unsigned int *)base,MAP_SIZE);
    return 0;
}
  • 拷贝index.html client.php/var/www/html/目录下,并将server设置为开机启动。
相关标签: demo