手里的智能锁项目, 最新要新加一个功能,就是通过无线把锁里的开门记录,登记人员这些信息发送出去 ,板子SDK本身是带有WIFI功能的 , 所以我需要实现的功能就两点, 首先 , 把设备(智能锁)连接上WIFI, 第二 , 把数据通过tcp/ip应用层协议的socket协议发送出去 , 就可以了。
我这里讲一下步骤吧 , 首先 , 我电脑端开了一个sockettools监听 , 第二, 配置我板子的ssid以及psk(WiFi账号和密码),第三写一个socket的client的通信实例把数据发送出去。
由于没有用到多线程, socket通信应该算是比较简单的, 分以下几个步骤吧
1 : socket()建立一个套接字, 类似open打开一个文件
2 : 填充struct sockaddr_in结构体, 分别填充sin_family字段, sin_port字段, sin_addr.s_addr字段
3 : connect目标服务器
4 : recv/send
5:close()
好了, 话不多说 , 直接上代码
client.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#define PORT 12333 //服务器端口号
#define SERVERIP "192.168.1.80" //服务器IP地址
//客户端
int main(int argc, char **argv)
{
int sd; //文件描述符
int ret;
//1 创建套接字
sd = socket(AF_INET, SOCK_STREAM, 0);
if (sd == -1) {
printf("socket failed!\n");
return -1;
}
printf("socket success!\n");
// 2 填充struct sockaddr_in结构体
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(PORT);
dest.sin_addr.s_addr = inet_addr(SERVERIP);
// 3 connect
ret = connect(sd, (struct sockaddr *)&dest, sizeof(dest));
if (ret == -1) {
printf("connect failed!\n");
close(sd);
return -1;
} else {
printf("connect success !\n");
}
// 4 发送数据
char *send_buf = "this is ilock x1000 test ...";
int send_len = strlen(send_buf);
ret = send(sd, send_buf, send_len, 0);
if (ret == -1) {
printf("send failed!\n");
return -1;
} else {
printf("send success \n");
}
printf("ret = %d\n", ret);
//5 关闭套接字
char read_buf[128] = {0};
while(read(sd, read_buf, sizeof(read_buf)) < 0);
close(sd);
return 0;
}
服务端的代码也上一份 , 其实很客户端也比较类似 , 只是说第三步connect()改成listen()之后accept()
server.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <syspes.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#define PORT 12333
#define BACKLOG 5
int main(void)
{
int socketfd, new_fd;
int ret, sock_len;
struct sockaddr_in dest_addr, addr_in;
// 1 建立socket
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd == -1) {
perror("socket failed");
goto out;
}
// 2 填充struct sockaddr_in 结构体
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(PORT);
addr_in.sin_addr.s_addr = htonl(INADDR_ANY); //INADDR_ANY宏展开为0.0.0.0, 如果服务端在这个地址上监听, 此时会监听服务器上所有的网卡。
// 3 绑定socketfd和addr_in结构体
ret = bind(socketfd, (struct sockaddr *)&addr_in, sizeof(addr_in));
if (ret < 0) {
perror("bind error !\n");
goto err;
}
// 4 按照addr_in结构体的配置 , 进行监听
listen(socketfd, BACKLOG);
printf("listening ...\n");
char buf[128] = {0};
while (1) {
sock_len = sizeof(struct sockaddr_in);
// 5 建立连接
new_fd = accept(socketfd, (struct sockaddr *)&dest_addr, &sock_len);
if (new_fd == -1) {
printf("accept error !\n");
} else {//此时连接成功
ret = recv(new_fd, buf, sizeof(buf), 0);
if (ret < 0) {
printf("recv error !\n");
} else {
printf("recv : %s \n", buf); //处理接收到的数据,我这里用最简单的打印的方式
}
if (strstr(buf, "x1000") != NULL) { //如果发送的字符串中包含有"x1000" 的话break出循环
close(new_fd);
break;
}
}
}
// 5 close()
close(socketfd);
return 0;
err:
return ret;
out:
return -1;
}
这里多补充一点 INADDR_ANY这个宏
它是用于多IP机器上
比如你的机器有三个ip
192.168.1.80
222.222.222.222
61.1.2.5
如果你serv.sin_addr.s_addr=inet_addr("192.168.1.80");
然后监听100端口
这时其他机器只有connect 192.168.1.80:100才能成功。
connect 222.222.222.222:100和connect 61.1.2.5:100都会失败。
如果serv.sin_addr.s_addr=htonl(INADDR_ANY); 的话,无论连接哪个ip都可以连上的。