大部分时候做嵌入式开发的,如果是wifi,可以工作在局域网,至于物联网设备,插手机卡的那种就需要公网ip,测试起来相对比较麻烦,电信宽带用户有的可以映射使用,但是ip会改变,需要一个设备不停的发送心跳,维持这个ip,测试有很大的局限性。域名相对而言较好,但是一旦IP变了,反映时间有点长。花生壳相对而言还是不错的,有流量控制,必须有实际设备。本文不具体讨论上述方式。这里使用一个公网的服务器测试使用,还是免费的哦,目前绝对不花钱,也不搞破解。使用的系统是centos,会c语言即可。(2019-11-3)
腾讯云微信操作一下就好了,就不贴图了。搭建服务器具体操作见下图。
指令说明:
一、 检查服务器是否已经安装
#rpm -qa |grep vsftpd
二、安装 如果输入上面的命令提示没有,那么进行安装
#yum install -y vsftpd
三、检查服务是否正常启动
1、启动 vsftp 服务
#systemctl start vsftpd
2、检查服务是否正常启动
#ps -ef|grep vsftpd
这个表示ftp 已经正常启动
3、把服务添加到开机启动项
#systemctl enabled vsftpd
四、修改 配置文件
1、进到安装vsftpd安装目录
#cd /etc/vsftpd
2、编辑 vsftpd.conf 配置文件
# vi /etc/vsftpd/vsftpd.conf
修改 一下几个地方 分别打开:
write_enable=YES
local_enable=YES
上述是服务器端安装ftp。
以下是通过winscp上传源文件到服务器(centos)系统,并且编译以及执行。
WinSCP 是一个 Windows 环境下使用的 SSH 的开源图形化 SFTP 客户端。同时支持 SCP 协议。它的主要功能是在本地与远程计算机间安全地复制文件,并且可以直接编辑文件。
centos系统安装了一个ftp,目的是windows系统可以通过它上传文件到服务器,并且可以在线编辑源文件,非常方便。
以下是服务器测试代码
server.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define PORT 12301
#define MAXSIZE 1024
#define LISTENQ 5
#define FDSIZE 1000
#define EPOLLEVENTS 100
//函数声明
//创建套接字并进行绑定
static int socket_bind(int port);
//IO多路复用epoll
static void do_epoll(int listenfd);
//事件处理函数
static void
handle_events(int epollfd,struct epoll_event *events,int num,int listenfd,char *buf);
//处理接收到的连接
static void handle_accpet(int epollfd,int listenfd);
//读处理
static void do_read(int epollfd,int fd,char *buf);
//写处理
static void do_write(int epollfd,int fd,char *buf);
//添加事件
static void add_event(int epollfd,int fd,int state);
//修改事件
static void modify_event(int epollfd,int fd,int state);
//删除事件
static void delete_event(int epollfd,int fd,int state);
int main(int argc,char *argv[])
{
int listenfd;
listenfd = socket_bind(PORT);
listen(listenfd,LISTENQ);
do_epoll(listenfd);
return 0;
}
static int socket_bind(int port)
{
int listenfd;
struct sockaddr_in servaddr;
listenfd = socket(AF_INET,SOCK_STREAM,0);
if (listenfd == -1)
{
perror("socket error:");
exit(1);
}
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /*任意本地地址*/
servaddr.sin_port = htons(port);
if (bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1)
{
perror("bind error: ");
exit(1);
}
return listenfd;
}
static void do_epoll(int listenfd)
{
int epollfd;
struct epoll_event events[EPOLLEVENTS];
int ret;
char buf[MAXSIZE];
memset(buf,0,MAXSIZE);
//创建一个描述符
epollfd = epoll_create(FDSIZE);
//添加监听描述符事件
add_event(epollfd,listenfd,EPOLLIN);
for ( ; ; )
{
//获取已经准备好的描述符事件
ret = epoll_wait(epollfd,events,EPOLLEVENTS,-1);
handle_events(epollfd,events,ret,listenfd,buf);
}
close(epollfd);
}
static void
handle_events(int epollfd,struct epoll_event *events,int num,int listenfd,char *buf)
{
int i;
int fd;
//进行选好遍历
for (i = 0;i < num;i++)
{
fd = events[i].data.fd;
//根据描述符的类型和事件类型进行处理
if (fd == listenfd)//有新的连接
handle_accpet(epollfd,listenfd);
else if (events[i].events & EPOLLIN)//接收到数据,读socket
do_read(epollfd,fd,buf);
else if (events[i].events & EPOLLOUT)//有数据待发送,写socket
do_write(epollfd,fd,buf);
}
}
static void handle_accpet(int epollfd,int listenfd)
{
int clifd;
struct sockaddr_in from;
socklen_t len = sizeof(from);
clifd = accept(listenfd,(struct sockaddr*)&from,&len);
if (clifd == -1)
perror("accpet error:");
else
{
printf("accept a new client: %s:%d\n",inet_ntoa(from.sin_addr),from.sin_port);
//添加一个客户描述符和事件
add_event(epollfd,clifd,EPOLLIN);
}
}
static void do_read(int epollfd,int fd,char *buf)
{
int nread;
nread = read(fd,buf,MAXSIZE);
if (nread == -1)
{
perror("read error:");
close(fd);
delete_event(epollfd,fd,EPOLLIN);
}
else if (nread == 0)
{
fprintf(stderr,"client close.\n");
close(fd);
delete_event(epollfd,fd,EPOLLIN);
}
else
{
printf("read message is : %s\r\n",buf);
//修改描述符对应的事件,由读改为写
modify_event(epollfd,fd,EPOLLOUT);
}
}
static void do_write(int epollfd,int fd,char *buf)
{
int nwrite;
nwrite = write(fd,buf,strlen(buf));
if (nwrite == -1)
{
perror("write error:");
close(fd);
delete_event(epollfd,fd,EPOLLOUT);
}
else
//修改描述符对应的事件,由写改为读
modify_event(epollfd,fd,EPOLLIN);
memset(buf,0,MAXSIZE);
}
static void add_event(int epollfd,int fd,int state)
{
struct epoll_event ev;
ev.events = state;
ev.data.fd = fd;
epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&ev);
}
static void delete_event(int epollfd,int fd,int state)
{
struct epoll_event ev;
ev.events = state;
ev.data.fd = fd;
epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&ev);
}
static void modify_event(int epollfd,int fd,int state)
{
struct epoll_event ev;
ev.events = state;
ev.data.fd = fd;
epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&ev);
}
客户端源代码是采用比select机制要好的epoll机制,对于服务器而言,均衡考虑使用异步较妥当。
能力有限,水平有限,如有错误,恳请留言批评指正。