wifi智能小车项目(服务器端的登录注册)

本文介绍了一个基于OpenWRT操作系统的WiFi智能小车服务器端实现方案,详细阐述了ser2net、mjpg-stream等组件的功能,并展示了如何使用SQLite3进行用户验证的代码实例。

wifi智能小车项目,服务器端主要是基于路由板上跑一个openwrt操作系统。openwrt配置ser2net、mjpg-stream两个软件,同时配置json、sqlite3;

ser2net-----通过wifi接受上位机发送的指令,将数据原封不动的网口转串口,发给下位机处理;

mjpg-stream-----通过usb输入的视频数据流进行编码,通过wifi通道给上位机解码,输出视屏;

json-----解析上位机发送的json包信息;

sqlite3----将解析的上位机发送的密码和账号插入数据库,每次遍历数据库看是否存在账号,不存在则注册;

------------------------------------------------------------------------------------------------------------

这里就简单的把代码拿出来吧,openwrt的系统裁剪和移植还有交叉编译工具链在没有文档下,花了很多时间,由于细节太多,有需要的可以私聊;

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <json/json.h>
#include <sqlite3.h>
#include <string.h>
/****************************************************************/
#define REGISER   0
#define LOGIN     1

int buf0[]={0};
int buf1[]={1};

void handler_message(int signum)
{
    waitpid(-1,NULL,WNOHANG);//非阻塞
    return;
}


void do_register(int sockfd,sqlite3 *pdb,char *_username,char *_password,char *filename)
{
        int ret=0;
        char sql[1024]={0};
        int nrow=0,ncolumn=0;
        char *errmsg;
        char **dbresult;

        sprintf(sql,"select *from userinfo where userName='%s';",_username);

        ret=sqlite3_open(filename,&pdb);
        if(ret!=SQLITE_OK)
        {
            fprintf(stderr,"fail to sqlite3_open:%s\n",sqlite3_errmsg(pdb));
            return ;
        }
        

        if(sqlite3_get_table(pdb,sql,&dbresult,&nrow,&ncolumn,&errmsg)!=0)
        {
            fprintf(stderr,"sqlite3 get table error:%s\n",errmsg);
            return ;
        }


        /***********查询若用户不存在*****************/
        if(nrow==0)/*******注册**********/
        {

            bzero(sql,sizeof(sql));
            sprintf(sql,"insert into userinfo values('%s','%s');",_username,_password);
            sqlite3_exec(pdb,sql,NULL,NULL,&errmsg);
          //  printf("ok.....\n");


            if(send(sockfd,buf1,sizeof(buf1),0)<0)
            {
                perror("fail to send");
                return ;
            }

        }
        /************查询若用户名存在***************/
        else
        {
            if(send(sockfd,buf1,sizeof(buf1),0)<0)
            {
                perror("fail to send");
                return ;
            }
        }

       sqlite3_free_table(dbresult);
}

void do_login(int sockfd,sqlite3 *pdb,char *_username,char *_password,char *filename)
{

    int ret=0;
    char sql[1024]={0};
    int nrow=0,ncolumn=0;
    char *errmsg;
    char **dbresult;


    sprintf(sql,"select *from userinfo where userName='%s';",_username);

    ret=sqlite3_open(filename,&pdb);
    if(ret!=SQLITE_OK)
    {
        fprintf(stderr,"fail to sqlite3_open:%s\n",sqlite3_errmsg(pdb));
        return ;
    }
        
    /************查询查数据表****************/          
    if(sqlite3_get_table(pdb,sql,&dbresult,&nrow,&ncolumn,&errmsg)!=0)
    {
        fprintf(stderr,"sqlite3 get table error:%s\n",errmsg);
        return ;
    }


    /***********用户不存在*****************/
    if(nrow==0)
    {
        if(send(sockfd,buf0,sizeof(buf0),0)<0)
        {
            perror("fail to send");
            return ;
        }
    }
    /************用户名存在***************/
    else
    {
        if(send(sockfd,buf1,sizeof(buf1),0)<0)
        {
            perror("fail to send");
            return ;
        }
    }
    sqlite3_free_table(dbresult);
    return;

}



void do_client(int sockfd)
{
    int n = 0;
    unsigned char buf[1024]={0};
    json_object *obj;//定义json对象 
    char _username[25];
    char _password[25];     
    int ret=0;
    char sql[1024]={0};
    char *errmsg;
    char **dbresult;
    sqlite3 *pdb=NULL;
    char* filename = "/home/ubuntu/project/carinfo.db";
    

    while(1)
    {
        bzero(buf,sizeof(buf));
        n = recv(sockfd,buf,sizeof(buf),0);
        if(n <= 0)
        {
            perror("fail to recv");
            exit(EXIT_FAILURE);
        }        
/***json解析***/
        printf("recv_buf= %s\n",buf);//接受对方发来的JSON对象
        printf("buf[0]=%d\n",buf[0]);


        obj=json_tokener_parse(buf+1);//解析json对象
        json_object *new_object=json_object_object_get(obj,"userName");//根据键名获取小对象
        printf("%s\n",json_object_get_string(new_object));//获取json对象里的字符串
        strcpy(_username,json_object_get_string(new_object));

        new_object=json_object_object_get(obj,"passWord");//根据键名获取小对象
        printf("%s\n",json_object_get_string(new_object));//获取json对象里的字符串
        strcpy(_password,json_object_get_string(new_object));

/***SQL*******/
        sprintf(sql,"select *from userinfo where userName='%s';",_username);

        ret=sqlite3_open(filename,&pdb);
        if(ret!=SQLITE_OK)
        {
            fprintf(stderr,"fail to sqlite3_open:%s\n",sqlite3_errmsg(pdb));
            return ;
        }
/***登录******/
        if(buf[0]=='1')
        {
              do_login(sockfd,pdb,_username,_password,filename);
        }
/***注册*****/
        else if(buf[0]=='2')
        {
            do_register(sockfd,pdb,_username,_password,filename);
        }
        exit(EXIT_SUCCESS);
}


//./a.out ip port
int main(int argc, const char *argv[])
{
    int listen_fd;
    int connect_fd;
    struct sockaddr_in ser_addr;
    struct sockaddr_in client_addr;
    socklen_t len = sizeof(struct sockaddr);
    int n = 0;
    char buf[1024] = {0};
    pid_t pid;


    if(argc != 3)
    {
        fprintf(stderr,"Uage: %s ip port ",argv[0]);
        exit(EXIT_FAILURE);
    }
    
    if(signal(SIGCHLD,handler_message) == SIG_ERR)
    {
        perror("fail to signal");
        exit(EXIT_FAILURE);
    }
    //1.创建一个监听套接字
    listen_fd = socket(AF_INET,SOCK_STREAM,0);
    if(listen_fd < 0)
    {
        perror("fail to socket");
        exit(EXIT_FAILURE);
    }

    //2.服务器地址赋值
    bzero(&ser_addr,len);
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_port = htons(atoi(argv[2]));
    ser_addr.sin_addr.s_addr = inet_addr(argv[1]);

    //3.绑定套接字
    if(bind(listen_fd,(struct sockaddr *)&ser_addr,len) < 0)
    {
        perror("fail to bind");
        exit(EXIT_FAILURE);
    }

    //4.打开监听,设置监听队列的长度10
    listen(listen_fd,10);
    printf("listen ......I\n");
    while(1)
    {

        connect_fd = accept(listen_fd,(struct sockaddr *)&client_addr,&len);
        if(connect_fd < 0)
        {
            perror("fail to accept");
            exit(EXIT_FAILURE);
        }

        printf("----------------------------------------------------");
        printf("connect_fd = %d\n",connect_fd);
        printf("client_addr.sin_port = %d\n",ntohs(client_addr.sin_port));
        printf("client_addr.sin_addr = %s\n",inet_ntoa(client_addr.sin_addr));

        //
        pid = fork();

        if(pid < 0)
        {
            perror("fail to fork");
            exit(EXIT_FAILURE);
        }else if(pid == 0)    //子进程负责数据的接收
        {
            do_client(connect_fd);
            close(listen_fd);

        }else{
            close(connect_fd);
        }

    }
    
    return 0;
  }
}



Wifi遥控小车使用说明: 本例程采用ESP8266 wifi模块与STM32串口连接,并提供AT指令封装库与STM32通讯,实现如下的通讯方式: 1、硬件部分 Wifi模块丝印图即引脚如下: 硬件连接如下: 2、手机APP部分 APP部分我们采用常用的APP wifi调试软件 ITEAD WIFI,安装完成后打开 如下界面,点击Set up进入设置: 进入后会自动获取到手机的IP,注意手机是连接到一个路由器下的,支持局域网内调试,先设置端口,一般是 8080 然后设置指令,我们使用到了如下红框内的指令,指令协议可以参考工程文件interface.h有如下描述: //指令定义 #define COMM_STOP 'I'//停止 #define COMM_UP 'A'//前进 #define COMM_DOWN 'B'//后退 #define COMM_LEFT 'C'//左转 #define COMM_RIGHT 'D'//右转 指令设置好之后就可以启动服务了,如下点击开始就好了 设置完成后如下,这里记下服务端IP和端口号,我这里是 192.168.31.195,端口 8080 ,然后返回: 3、stm32软件部分 设置完APP软件后,再来修改我们的工程文件,打开工程“wifi遥控小车”,打开main.c文件,修改红框内信息: HOST_NAME和HOST_PORT为手机上面的IP和端口号,SSID为您的路由器名,PSD为路由器密码,修改好后重新编译后下载。 下载完成复位一下,就可以运行了,程序会自动连接手机开启的服务,实现TCP/IP通信,连接成功后,看手机端的设置会有如下提示: 本程序还是用了串口1来输出调试信息,将串口1连接电脑后也会在串口调试助手看到如下信息: 连接成功后即可在如下界面按键,操作小车运行:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

屁小猪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值