网络socket编程基于DS18B20获取温度并上报服务器(服务器)

能够支持多个客户端的并发访问(上报数据库相关代码在客户端实现了)
采用命令行参数解析监听相关端口

直接上代码
socket_server.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <pthread.h>
#include <getopt.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <sys/resource.h>
#include <signal.h>

#define MAX_EVENTS 512
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
int g_stop=0;

static inline void print_usage(char *progname);
int socket_server_init(char *listen_ip, int listen_port);
void set_socket_rlimit(void);
void sig_handle(int signum);

int main(int argc, char **argv)
{
        int listenfd, connfd;
        int serv_port = 0;
        int daemon_run = 0;
        char *progname = NULL;
        int opt;
        int rv;
        int i, j;
        int found;
        char buf[1024];
        int epollfd;
        struct epoll_event event;
        struct epoll_event event_array[MAX_EVENTS];
        int events;
         /*参数解析*/
        struct option long_options[] =
        {
                {"daemon", no_argument, NULL, 'b'},
                {"port", required_argument, NULL, 'p'},
                {"help", no_argument, NULL, 'h'},
                {NULL, 0, NULL, 0}
        };
        progname = basename(argv[0]);
        /* 传入命令行参数*/
        while ((opt = getopt_long(argc, argv, "bp:h", long_options, NULL)) != -1)
        {
                switch (opt)
                {
                        case 'b':
                                daemon_run=1;
                                break;
                        case 'p':
                                serv_port = atoi(optarg);
                                break;
                        case 'h': /* Get help information */
                                print_usage(progname);
                                return EXIT_SUCCESS;
                                 default:
                                break;
                }
        }
        /*没有传入端口号*/
        if( !serv_port )
        {
                print_usage(progname);
                return -1;
        }
        set_socket_rlimit(); /* set max open socket count */
        /*socket初始化*/
        if( (listenfd=socket_server_init(NULL, serv_port)) < 0 )
        {
                printf("ERROR: %s server listen on port %d failure\n", argv[0],serv_port);
                return -2;
        }
        printf("%s server start to listen on port %d\n", argv[0],serv_port);
        if( daemon_run )
        {
                daemon(0, 0);
        }
        /*创建一个epoll对象*/
        if( (epollfd=epoll_create(MAX_EVENTS)) < 0 )
        {
                printf("epoll_create() failure: %s\n", strerror(errno));
                return -3;
        }
        event.events = EPOLLIN|EPOLLET;
        event.events = EPOLLIN;
        event.data.fd = listenfd;
        /*把需要监听的listenfd加入到epollfd的兴趣列表中*/
        if( epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &event) < 0)
        {
                printf("epoll add listen socket failure: %s\n", strerror(errno));
                return -4;
        }
        while(!g_stop)
        {
                memset(buf,0,sizeof(buf));

                signal(SIGINT,sig_handle);
                signal(SIGINT,sig_handle);

                /*程序在这阻塞等待时间的发生*/
                events = epoll_wait(epollfd, event_array, MAX_EVENTS, -1);
                if(events < 0)
                {
                        printf("epoll failure: %s\n", strerror(errno));
                        break;
                }
                else if(events == 0)
                {
                        printf("epoll get timeout\n");
                        continue;
                }
                /* rv的返回值表示发生时间的数值,遍历发生的事件*/
                for(i=0; i<events; i++)
                {
                        if ( (event_array[i].events&EPOLLERR) || (event_array[i].events&EPOLLHUP) )
                        {
                                printf("epoll_wait get error on fd[%d]: %s\n", event_array[i].data.fd, strerror(errno));
                                epoll_ctl(epollfd, EPOLL_CTL_DEL, event_array[i].data.fd, NULL);
                                close(event_array[i].data.fd);
                        }
                        /* listenfd发生事件,接受新的客户端的连接 */
                        if( event_array[i].data.fd == listenfd )
                        {
                                if( (connfd=accept(listenfd, (struct sockaddr *)NULL, NULL)) < 0)
                                {
                                        printf("accept new client failure: %s\n", strerror(errno));
                                        continue;
                                }
                                event.data.fd = connfd;
                                event.events = EPOLLIN;
                                /*把新连接的客户端的fd加入到epollfd的兴趣列表中*/
                                if( epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &event) < 0 )
                                {
                                        printf("epoll add client socket failure: %s\n", strerror(errno));
                                        close(event_array[i].data.fd);
                                        continue;
                                }
                                printf("epoll add new client socket[%d] ok.\n", connfd);
                        }
                        else /* 已经连接的客户端的数据到来进行读写操作*/
                        {
                                if( (rv=read(event_array[i].data.fd, buf, sizeof(buf))) <= 0)
                                {
                                        printf("socket[%d] read failure or get disconncet and will be removed.\n",
                                        event_array[i].data.fd);
                                        epoll_ctl(epollfd, EPOLL_CTL_DEL, event_array[i].data.fd, NULL);
                                        close(event_array[i].data.fd);
                                        continue;
                                }
                                else
                                {
                                        printf("socket[%d] read get %d bytes data :%s\n", event_array[i].data.fd, rv,buf);
                                        if( write(event_array[i].data.fd, buf, rv) < 0 )
                                        {
                                                printf("socket[%d] write failure: %s\n", event_array[i].data.fd, strerror(errno));
                                                epoll_ctl(epollfd, EPOLL_CTL_DEL, event_array[i].data.fd, NULL);
                                                close(event_array[i].data.fd);
                                        }
                                }
                        }
                } 
        }
        CleanUp:
        close(listenfd);
        return 0;
}

static inline void print_usage(char *progname)
{
        printf("Usage: %s [OPTION]...\n", progname);
        printf(" %s is a socket server program, which used to verify client and echo back string from it\n",progname);
        printf(" -b[daemon ] set program running on background\n");
        printf(" -p[port ] Socket server port address\n");
        printf(" -h[help ] Display this help information\n");
        printf("\nExample: %s -b -p 8900\n", progname);
        return ;
}
int socket_server_init(char *listen_ip, int listen_port)
{
        struct sockaddr_in servaddr;
        int rv = 0;
        int on = 1;
        int listenfd;
        if ( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        {
                printf("Use socket() to create a TCP socket failure: %s\n", strerror(errno));
                return -1;
        }
        setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(listen_port);
        if( !listen_ip ) /*监听所有的ip地址*/
        {
                servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        }
        else /* 监听指定的ip地址 */
        {
                if (inet_pton(AF_INET, listen_ip, &servaddr.sin_addr) <= 0)
                {
                        printf("inet_pton() set listen IP address failure.\n");
                        rv = -2;
                        goto CleanUp;
                }
        }
        if(bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
        {
                printf("Use bind() to bind the TCP socket failure: %s\n", strerror(errno));
                rv = -3;
                goto CleanUp;
        }
        if(listen(listenfd, 64) < 0)
        {
                printf("Use bind() to bind the TCP socket failure: %s\n", strerror(errno));
                rv = -4;
                goto CleanUp;
        }

CleanUp:
        if(rv<0)
                close(listenfd);
        else
                rv = listenfd;
        return rv;
}

  /* Set open file description count to max */
        void set_socket_rlimit(void)
        {
                struct rlimit limit = {0};
                getrlimit(RLIMIT_NOFILE, &limit );
                limit.rlim_cur = limit.rlim_max;
                setrlimit(RLIMIT_NOFILE, &limit );
                printf("set socket open fd max count to %d\n", limit.rlim_max);
        }

void sig_handle(int signum)
{
          if(SIGTERM==signum)
          {
                printf("catch signal [%d] SIGTERM\n");
                g_stop=1;
          }
          else if(SIGINT==signum)
          {
                printf("catch signal [%d] SIGINT\n");
                g_stop=1;
          }
}

除了自己写的socket_client端连接服务器外,同时使用了TCP_TestTool进行验证:
在这里插入图片描述
结果:在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值