搭建自己的简易服务器(公网)

大部分时候做嵌入式开发的,如果是wifi,可以工作在局域网,至于物联网设备,插手机卡的那种就需要公网ip,测试起来相对比较麻烦,电信宽带用户有的可以映射使用,但是ip会改变,需要一个设备不停的发送心跳,维持这个ip,测试有很大的局限性。域名相对而言较好,但是一旦IP变了,反映时间有点长。花生壳相对而言还是不错的,有流量控制,必须有实际设备。本文不具体讨论上述方式。这里使用一个公网的服务器测试使用,还是免费的哦,目前绝对不花钱,也不搞破解。使用的系统是centos,会c语言即可。(2019-11-3)

搭建自己的简易服务器(公网)_第1张图片 服务器对比

  腾讯云微信操作一下就好了,就不贴图了。搭建服务器具体操作见下图。

搭建自己的简易服务器(公网)_第2张图片

指令说明:

一、 检查服务器是否已经安装

#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)系统,并且编译以及执行。

搭建自己的简易服务器(公网)_第3张图片 上传源文件,编译执行

 

什么是 WinSCP

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机制,对于服务器而言,均衡考虑使用异步较妥当。

能力有限,水平有限,如有错误,恳请留言批评指正。

你可能感兴趣的:(服务器)