前言
最近设计了一款用于安防的的产品,产品中集成了一款中移物联网有限公司的NB(MN316)模块。最近设计了一款用于安防的的产品,产品中集成了一款中移物联网有限公司的NB(MN316)模块。产品主要使用 LwM2M协议与物联网平台连接。产品部署已经超过10K,为了对产品MCU固件进行远程更新,经过论证采用socket进行升级。所以对MN316关于socket的tcp相关操作进行了学习使用。并且编写了一个简单的socket server,可以接入一个socket client进行测试NB模块的socket。
一、socket server
socket server 部署在租用的云服务器上。因为是测试所以非常简单,只能接收一个socket client 接入。也就是只有一台设备可以接入。为了测试socket设计了一个简单的协议。在此只测试一条。服务端收到file=V3000.bin,0? 返回1152个字节。为了检查NB接收的数据是否正确,数据内容为0x00~0xFF填充1152个字节的内容。以下是socket代码。该代码试chart GPT提供。我进行了内容的修改。我猜想将来的编程工作可能就是是这样。基础的工作交给机器人完成。机器人提供的代码非常规整。
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#define MAX_READ_LINE 1024
int getFileSize(char *fileName)
{
FILE *file;
long size;
// 打开文件
file = fopen(fileName, "rb");
if( !file){
printf("file fopen fail!\r\n");
return -1;
}
// 将文件指针移动到文件末尾
fseek(file, 0, SEEK_END);
// 获取文件大小
size = ftell(file);
// 关闭文件
fclose(file);
return size;
}
int fread_file(char *file_name, unsigned int offset, unsigned char *buf, int count )
{
FILE *file;
// 打开文件
file = fopen(file_name, "r");
if (file == NULL) {
printf("无法打开文件。\n");
return -1;
}
fseek(file, offset, SEEK_SET);
size_t len = fread(buf,1,count,file);
fclose(file);
return len;
}
void hexToAscII(unsigned char hex, char* H, char* L)
{
unsigned char H_8,L_8;
H_8 = hex>>4;
L_8 = hex&0x0F;
if((H_8>=0)&(H_8<=9)){ *H = H_8+0x30; }
else { *H = (H_8-0x0A)+'a'; }
if((L_8>=0)&(L_8<=9)){ *L = L_8+0x30; }
else { *L = (L_8-0x0A)+'a'; }
}
int main(void) {
char buff[MAX_READ_LINE];
char TX_buff[MAX_READ_LINE];
int recv_len = -1;
int send_len = -1;
int conn_fd = -1;
int ret = -1;
int server_ip_port = 57263;
struct sockaddr_in t_sockaddr;
memset(&t_sockaddr, 0, sizeof(t_sockaddr));
t_sockaddr.sin_family = AF_INET;
t_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
t_sockaddr.sin_port = htons(server_ip_port);
printf("server_ip_port:%d\n",server_ip_port);
unsigned long y= htonl(INADDR_ANY);
unsigned char *c ;
c= (unsigned char *)&y;
printf("y= %02x %02x %02x %02x %ul\n",*c,*(c+1),*(c+2),*(c+3), y);
int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_fd < 0) {
fprintf(stderr, "socket error %s errno: %d\n", strerror(errno), errno);
}
ret = bind(listen_fd,(struct sockaddr *) &t_sockaddr,sizeof(t_sockaddr));
if (ret < 0) {
fprintf(stderr, "bind socket error %s errno: %d\n", strerror(errno), errno);
}
ret = listen(listen_fd, 1024);
if (ret < 0) {
fprintf(stderr, "listen error %s errno: %d\n", strerror(errno), errno);
}
while(1)
{
for(;;) {
conn_fd = accept(listen_fd, (struct sockaddr*)NULL, NULL);
if(conn_fd < 0) {
fprintf(stderr, "accpet socket error: %s errno :%d\n", strerror(errno), errno);
continue;
}
else
{
break;
}
}
int rec_cout=0;
while(1)
{
int cmp_retvalue;
recv_len = recv(conn_fd, buff, MAX_READ_LINE, 0);
buff[recv_len] = '\0';
fprintf(stdout, "recv message from client: %s recv_len:%d,\n", buff,recv_len);
if (recv_len < 0) {
fprintf(stderr, "recv error %s errno: %d\n", strerror(errno), errno);
break;
}
else
{
//rec_cout+=recv_len;
//if(recv_len==0)
//{
// continue;
//}
}
if(strstr(buff,"size="))
{
//size=V3000.bin?
char filename[32]={0};
char *pstrt_start;
char *pstrt_end;
int i;
int fileSize;
pstrt_start=strstr(buff,"=");
pstrt_start++;
pstrt_end=strstr(buff,"?");
i=0;
for(; pstrt_start<pstrt_end; pstrt_start++){
filename[i++] = *pstrt_start;
}
filename[i++]=0;
printf("file name is :%s",filename);
fileSize = getFileSize(filename);
send_len = sprintf(TX_buff,"size=%s,%d,ok\r\n",filename,fileSize);
printf("ACK:%s",TX_buff);
send(conn_fd,TX_buff,send_len,0);
continue;
}
if(strstr(buff,"file="))
{
//file=V3000.bin,0?
/* char filename[32]={0};
int num,i;
char *pstrt_start;
char *pstrt_end;
pstrt_start=strstr(buff,"=");
pstrt_start++;
pstrt_end = strstr(buff,",");
if(pstrt_end)
{
i=0;
for(; pstrt_start<pstrt_end; pstrt_start++)
{
filename[i++] = *pstrt_start;
}
}
filename[i++]=0;
pstrt_start=pstrt_end;
pstrt_start++;
num = atoi(pstrt_start);
unsigned char file_hex[256];
unsigned char file_ASCII[512];
int read_len=fread_file(filename,num*128, file_hex, 128 );
send_len = sprintf(TX_buff,"file=%d,%d,",num,read_len);
char H,L;
for(int n=0, index =0;n<read_len;n++)
{
hexToAscII(file_hex[n], &H, &L);
file_ASCII[index++]=H;
file_ASCII[index++]=L;
}
for(int n=0;n<read_len*2;n++)
{
TX_buff[send_len+n] = file_ASCII[n];
}
int m= send_len+read_len*2;
TX_buff[m++] = '\r'; TX_buff[m++] = '\n';
send(conn_fd,TX_buff,m,0);
printf("send :%s\n",TX_buff);
*/
unsigned char file_hex[1024+128];
for(uint16_t m=0; m<sizeof(file_hex);m++){
file_hex[m] = m;
}
send(conn_fd,file_hex,sizeof(file_hex),0);
continue;
}
if(strstr(buff,"result="))
{
char filename[32]={0};
char result[32]={0};
int num,i;
char *pstrt_start;
char *pstrt_end;
pstrt_start=strstr(buff,"=");
pstrt_start++;
pstrt_end = strstr(buff,",");
//fprintf(stdout, "pstrt_start: %s pstrt_end:%s,\n", pstrt_start,pstrt_end);
if(pstrt_end)
{
i=0;
for(; pstrt_start<pstrt_end; pstrt_start++)
{
filename[i++] = *pstrt_start;
}
}
pstrt_start = pstrt_end;
pstrt_start++;
pstrt_end = strstr(pstrt_start,"\r\n");
if(pstrt_end)
{
i =0;
for(; pstrt_start<pstrt_end; pstrt_start++)
{
result[i++] = *pstrt_start;
}
}
send_len = sprintf(TX_buff,"filename is %s,result is %s\r\n",filename,result);
send(conn_fd,TX_buff,send_len,0);
continue;
}
if(strstr(buff,"quit server"))
{
send_len = sprintf(TX_buff,"server is power off\r\n");
send(conn_fd,TX_buff,send_len,0);
close(conn_fd);
break;
}
send(conn_fd,"no ack\n",strlen("no ack\n"),0);
}
}
close(conn_fd);
conn_fd = -1;
close(listen_fd);
listen_fd = -1;
return 0;
}
/*
size=V3000.bin?
file=V1002.bin,899?\r\n
result=flie name,ok\r\n
result=flie name,fail\r\n
quit server\r\n
公网测试服务器:202.15.10.254 sxjc789
*/
服务器部署在202.15.10.254 服务器上,使用57263端口。
二、NB模块测试
使用串口助手测试
MN316)模块可以通过串口助手测试socket.通过串口助手发送AT指令就可以完成socket 的建立、连接、数据发送以及数据接收。
指令流程如下:
09:11:14.587]发→◇AT
□
[09:11:14.610]收←◆
OK
[09:11:15.386]发→◇AT+CFUN=0
□
[09:11:16.299]发→◇AT+NCSEARFCN
□
[09:11:16.321]收←◆
+CME ERROR:8007
+DBGINFO:FARPS BUSY:AT+CFUN,new:AT+NCSEAR
[09:11:17.739]发→◇AT+NBAND?
□
[09:11:17.762]收←◆
+CME ERROR:8007
+DBGINFO:FARPS BUSY:AT+CFUN,new:AT+NBAND?
[09:11:18.973]发→◇AT+NCONFIG=AUTOCONNECT,1
□
[09:11:19.008]收←◆
+CME ERROR:8007
+DBGINFO:FARPS BUSY:AT+CFUN,new:AT+NCONFI
[09:11:19.153]收←◆
OK
+CGEV:ME PDN DEACT 0
+CGEV:ME DETACH
[09:11:22.868]发→◇AT+NRB
□
[09:11:22.894]收←◆
REBOOTING
[09:11:23.695]收←◆
+MODULE_READY:2
^SIMST:1
[09:11:27.438]收←◆
+CGEV:ME PDN ACT 0
[09:11:27.486]收←◆
+CTZEU:+32,0,2024/04/16,01:11:27
[09:11:30.026]发→◇AT+NBAND=5,8
□
[09:11:30.060]收←◆
OK
[09:11:31.379]发→◇AT+CFUN=1
□
[09:11:31.421]收←◆
OK
[09:11:36.428]发→◇AT+CGATT=1
□
[09:11:36.457]收←◆
OK
[09:11:37.955]发→◇AT+CGATT?
□
[09:11:37.994]收←◆
+CGATT:1
OK
[09:11:42.084]发→◇AT+NSOCR=STREAM,6,57263,1
□
[09:11:42.136]收←◆+NSOCR:0
OK
[09:11:45.706]发→◇AT+NSOCO=0,203.15.10.254,57263
□
[09:11:45.766]收←◆
OK
[09:11:58.003]收←◆
CONNECT OK
[09:12:00.963]发→◇AT+NSOSD=0,17,66696c653d56333030302e62696e2c313f,148
□
[09:12:01.042]收←◆+NSOSD:0,17
OK
[09:12:02.962]收←◆
+NSOSTR:0,148,1
[09:12:20.058]收←◆
+NSONMI:0,1152
[09:12:37.772]发→◇AT+NSORF=0,1152
□
[09:12:37.827]收←◆
+NSORF:0,203.15.10.254,5
[09:12:37.860]收←◆7263,1152,000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D
[09:12:38.501]收←◆2E2F303132333435363738393A3B3C3
[09:12:38.531]收←◆D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868
[09:12:39.220]收←◆788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C
[09:12:39.876]收←◆2C3C4C5C6C7C8C9CACBCCCDCECFD0D1
[09:12:39.907]收←◆D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F,0
OK
2.server socket
总结
– NB 通过spcket可以方便的进行数据传输。