嵌入式技术
一、测试环境说明
程序测试硬件为:树莓派3B+ ,以及4根杜邦线,1块面包板,1个蓝色led灯
杜邦线均为公-母线, 其母头分别接树莓派40GPIO口处的 3.3v(pin1),GND(pin39),pin11,pin18
LED灯的 正极连 pin18,负极连pin1 (在面包板上)
接pin11的杜邦线另一端公头悬空,测试时可分别在面包板上与 pin1 或 pin39 连接,模拟一个拨动开关(如果有拨动开关可以直接利用)
基本系统:rasbian
nodejs:10.2.1
npm:6.1.0
gcc: 6.3.0
wiringPi & gpio:2.46
-------------------------------------------
二、关键代码解析
1. 利用wiringPi和socket编写本地tcp服务,具体代码见项目代码 rpi-express-demo/localSvc/server.c
#include #include #include #include #include #include #include #include #include #include #include #include #include #define SERVER_PORT 5555#define LEDpin 5#define KEYpin 0#define LINE_MAX 1024int setLEDon(void){ // 定义亮灯处理 digitalWrite(LEDpin,HIGH); return HIGH;} int setLEDoff(void){ // 定义灭灯处理 digitalWrite(LEDpin,LOW); return LOW;} int getKEY( ){ // 获取灯状态值 return digitalRead(KEYpin);}int main(){ //调用socket函数返回的文件描述符int serverSocket; //声明两个套接字sockaddr_in结构体变量,分别表示客户端和服务器struct sockaddr_in server_addr;struct sockaddr_in clientAddr;int addr_len = sizeof(clientAddr);//用于接收连接,因为只有一个,所以同时只允许一个连接int client;char buffer[ LINE_MAX ];char rtmsg[ LINE_MAX ];int iDataNum;int LEDflag = LOW ;int KEYflag ;char *LED_ON = "on" ;char *LED_OFF = "off" ;char *KEY_GET = "get" ;char *CLOSE_MSG = "quit"; int Ec=0;/ //socket函数,失败返回-1 //int socket(int domain, int type, int protocol); //第一个参数表示使用的地址类型,一般都是ipv4,AF_INET //第二个参数表示套接字类型:tcp:面向连接的稳定数据传输SOCK_STREAM //第三个参数设置为0if((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("socket");return 1;}bzero(&server_addr, sizeof(server_addr)); //初始化服务器端的套接字,并用htons和htonl将端口和地址转成网络字节序server_addr.sin_family = AF_INET;server_addr.sin_port = htons(SERVER_PORT); //ip可是是本服务器的ip,也可以用宏INADDR_ANY代替,代表0.0.0.0,表明所有地址server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //对于bind,accept之类的函数,里面套接字参数都是需要强制转换成(struct sockaddr *) //bind三个参数:服务器端的套接字的文件描述符, if(bind(serverSocket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){perror("connect");return 1;} //设置服务器上的socket为监听状态if(listen(serverSocket, 15) < 0) {perror("listen");return 1;}while(1){printf("Listening on port: %d ", SERVER_PORT); //调用accept函数后,会进入阻塞状态 //accept返回一个套接字的文件描述符,这样服务器端便有两个套接字的文件描述符, //serverSocket和client。 //serverSocket仍然继续在监听状态,client则负责接收和发送数据 //clientAddr是一个传出参数,accept返回时,传出客户端的地址和端口号 //addr_len是一个传入-传出参数,传入的是调用者提供的缓冲区的clientAddr的长度,以避免缓冲区溢出。 //传出的是客户端地址结构体的实际长度。 //出错返回-1client = accept(serverSocket, (struct sockaddr*)&clientAddr, (socklen_t*)&addr_len);if(client < 0){perror("accept");continue;}printf(" recv client data...n"); //inet_ntoa ip地址转换函数,将网络字节序IP转换为点分十进制IP //表达式:char *inet_ntoa (struct in_addr);printf("IP is %s ", inet_ntoa(clientAddr.sin_addr));printf("Port is %d ", htons(clientAddr.sin_port));while(1){iDataNum = recv(client, buffer, 1024, 0);if(iDataNum <= 0){ Ec++; if(Ec>5) break;continue;}buffer[iDataNum] = '