SIM868——GPRS调试之公网IP端口无法映射的解决方法

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/w464960660/article/details/83416349

【基于公网IP映射端口】:我们做SIM868模块调试GPRS数据传输功能的时候,往往会利用公网IP地址进行数据传输,大致步骤是:
1)先查询公网IP(百度查IP或者通过路由器查询WAN口IP);
在这里插入图片描述
2)再查询自己电脑内网IP(方法很多);
3)登录路由器控制界面,设置虚拟服务器,写入内网IP及端口号;
在这里插入图片描述
4)利用TCP/UDP Socket工具创建服务器,监听对应的端口,这时就可以进行GPRS模块和对应本地电脑的数据传输了;
在这里插入图片描述
5)GPRS模块端串口连接电脑,利用串口调试助手进行的AT命令控制(无括号备注,均需勾选“发送新行”):
AT+CSQ //查询网络信号质量
AT+CREG? //查询网络注册情况
AT+CGATT? //查询模块是否附着 GPRS 网络
AT+CSTT=“CMNET” //根据实际网络设置 APN,这里为移动
AT+CIICR //激活移动场景
AT+CIFSR //获得本地 IP 地址
AT+CIPSTART=“TCP”,“113.0.80.201”,3389 //建立 TCP/IP 连接 // 测试时公网动态 IP:113.0.80.201
AT+CIPSEND(出现>后,去掉 “发送新行”,再写要发送的数据)
1A(16进制发送)
以上便可以实现GPRS的数据传输,在串口调试助手与TCP/UDP Socket 工具间可看到数据传输。

【问题】:以上是在百度查到的公网IP及路由器查到WAN IP一致的情况下实现的,但是会存在查询结果不一致的情况(现在外网地址不够用,所以很多运营商都将用户设为内网),如移动、铁通等用户,这种情况下无法用上述设置路由器 虚拟服务器的方法实现端口映射,这时候该怎么破?

【解决办法】:利用花生壳的内网穿透功能实现(我绝对不是给它做广告的,只是确实好用~ :) )
下载花生壳软件,并注册,在内网穿透中添加映射:
在这里插入图片描述

这时候记住外网访问地址及内网主机地址,接着重复上述的步骤5),只是把:
AT+CIPSTART=“TCP”,“113.0.80.201”,3389 IP地址修改为花生壳中内网穿透的“外网地址”,端口号设为同样的就OK了;
在这里插入图片描述

【注意】:
1、这里的“外网地址”是在注册花生壳时免费提供给你的域名;
2、使用花生壳内网穿透的好处不仅是解决公网端口无法映射的问题,还解决了公网IP变化的问题(动态IP分配导致的变化,对应用者而言,公网IP变化,原来烧进MCU中的程序就要重新改变,否则无法使用);

展开阅读全文

socket和映射IP端口的问题

03-09

情况描述:rn192.168.0.122 这台电脑是网关(window2003server),而邮件服务器保存在192.168.0.123 这台电脑上,用的是IP端口映射,就是说192.168.0.123是通过192.168.0.122上网并且发送邮件的,可是在外网发送电子邮件过来的时候都要通过192.168.0.122所以192.168.0.123得到的数据包的来源全部都表明是192.168.0.122的,这样就无法验证对方的IP地址了,使用函数:rnrn#include "../common/commonstruct.hpp"rnrnint main(int argc, char *argv[])rnrn //常用变量rn BQ_UserInfo User[MAXUSER]; //用户数组rn BQ_Message MainMessage; //主消息rn BQ_User Users[2]; //用户列表,用户login的时候,就把这个值写入rn int flag = -1; //标志值rn int i=0;rnrn //-----------------------------------------------------rn strcpy(Users[0].name,"qdragon");rn Users[0].status = 1;rnrn strcpy(Users[1].name,"zhangxiu");rn Users[1].status = 1;rn //-----------------------------------------------------rnrn pid_t forkid,forkid_rcvmssge; //进程rnrn //IPC所用变量rn int msqid_main; //主IPC通道,客户信息都发送到这里,然后通过这个IPC进行分发rn int msqid_rcmgs; //获取信息的PIDrnrn //socket所用变量rn struct sockaddr_in my_addr;rn struct sockaddr_in their_addr;rn socklen_t sin_size;rn int sockfd,new_fd,addr_len; //socket 句柄rn int is_connected[MAXSOCKFD],fd;rn sin_size = sizeof(struct sockaddr_in);rn addr_len = sizeof(struct sockaddr_in);rn fd_set readfds; //是否选定的宏rn int numbytes; //接收数据量rnrn //开始程序rn //建立TCP套接口rn if((sockfd = socket(AF_INET,SOCK_STREAM,0))==-1)rn rn perror("socket");rn exit(1);rn rnrn int optval, opelen=sizeof(int);rn setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,opelen); //设定IP和PORT可以重用rnrn //初始化结构体,并绑定SERVER_PORT端口rn my_addr.sin_family = AF_INET;rn my_addr.sin_port = htons(SERVER_PORT);rn my_addr.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY 代表本机IP地址rn bzero(&(my_addr.sin_zero),8);rn //绑定套接口rn if(bind(sockfd,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)rn rn perror("bind");rn exit(-1);rn rnrn //创建监听套接口rn if(listen(sockfd,LISTENNUM)==-1)rn rn perror("listen");rn exit(-1);rn rnrn for(fd=0;fd Login Welcome!\n",MainMessage.FromUser.name);rn sprintf(MainMessage.Message,"hi! <%s> Welcome",MainMessage.FromUser.name);rn strcpy(MainMessage.ToUser,MainMessage.FromUser.name);rn rn else if(strcmp(MainMessage.mtext,"logout")==0)rn rn printf("User <%s> Logout ByeBye!\n",MainMessage.FromUser.name);rn sprintf(MainMessage.Message,"bye! <%s> Welcome",MainMessage.FromUser.name);rn strcpy(MainMessage.ToUser,MainMessage.FromUser.name);rn rn else if(strcmp(MainMessage.mtext,"nouser")==0)rn rn printf("Sorry You Can't send message!\n");rn strcpy(MainMessage.ToUser,MainMessage.FromUser.name);rn sprintf(MainMessage.Message,"Sorry You Can't send message!");rn MainMessage.M_Len=strlen(MainMessage.Message);rn MainMessage.mtype=1;rn strcpy(MainMessage.FromUser.name,"Administrator");rn MainMessage.FromUser.status = 1;rn rn elsern rn //根据要求把消息投递给相应的用户rn int i=0;rn for (i=0;i<2;i++)rn rn if (strcmp(MainMessage.ToUser,Users[i].name)==0)rn rn flag = 1;rn break;rn rn rn //判断是否有用户rn if (flag==1)rn rn my_addr.sin_port = Users[i].port;rn// my_addr.sin_addr.s_addr = inet_addr(Users[i].hostname);rn my_addr.sin_addr.s_addr = Users[i].sock_addr;rn rn elsern rn sprintf(MainMessage.Message,"Sorry No This User<%s>!",MainMessage.ToUser);rn printf("No this User<%s>\n",MainMessage.ToUser);rn strcpy(MainMessage.ToUser,MainMessage.FromUser.name);rn MainMessage.M_Len=strlen(MainMessage.Message);rn MainMessage.mtype=1;rn strcpy(MainMessage.mtext,"message");rn strcpy(MainMessage.FromUser.name,"Administrator");rn MainMessage.FromUser.status = 1;rn rn rnrn //一切完毕后发送rn if((numbytes=sendto(sockfd,(void *)&MainMessage, sizeof(MainMessage), 0, (struct sockaddr *)&my_addr, addr_len))<0)rn rn perror("sendto");rn exit(0);rn rnrn if (numbytes==0)rn printf("Can't sendto UDP!!\n");rn elsern printf("sendto UDP %d!!\n",numbytes);rnrn //关闭套接字rn close(sockfd);rn exit(0);rn rn rn rn if (forkid_rcvmssge<0)rn rn //如果FORK建立不成功rn printf("Can't Create fork = forkid_rcvmssge!\n");rn exit(0);rn rnrnrn //消息接受进程创建完毕------------------------------------------------------rnrn while(1)rn rn //如果建立连接,将产生一个全新的套接字rn FD_ZERO(&readfds);rn FD_SET(sockfd,&readfds);rn for(fd=0;fd 论坛

没有更多推荐了,返回首页