getopt

getopt库是用来分析命令行参数的。由Unix标准库提供。 对类似于main函数那样传进来的参数进行解析。如有的参数是 –help 也可以 是-h,同时也可以传递参数,如 –interval 10。getopt可以支持-key 或者-k v。如果需要同时支持–key和-k,就需要用到getopt_long.

因为getopt_long可以支持长短两种参数格式,我们可以只使用这个函数。

相关函数表头文件

#include<unistd.h> #include <getopt.h>

函数声明

int getopt(int argc,char * const argv[ ],const char * optstring);
int getopt_long(int argc, char * const argv[],   const char
*optstring,   const struct option *longopts, int *longindex);
struct option {
const char  *name;       /* 参数名称 */
int          has_arg;    /* 指明是否带有参数 */
int          *flag;      /* flag=NULL时,返回value;不为空时,*flag=val,返回0 */
int          val;        /* 用于指定函数找到选项的返回值或flag非空时指定*flag的值 */
};

变量和参数

比如char*optstring = “ab:c::”;表示

  • 单个字符a 表示选项a没有参数 格式:-a即可,不加参数
  • 单字符加冒号b: 表示选项b有且必须加参数 格式:-b 100或-b100,但-b=100错
  • 单字符加2冒号c:: 表示选项c可以有,也可以无 格式:-c200,其它格式错误

example

#define _GNU_SOURCE
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <signal.h>
#include <getopt.h>
#include <sched.h>
#include <stdbool.h>

#define PORT     111

struct controll_blk
{
    char      role;                         /* 'c' lient or 's' erver */
    int       mode;                         /* 1 - server, 2 - client */
    char     *server_ip;                    /* -c option */
    char     *bind_address;                 /* first -B option */
    int       server_port;
};

const char usage[] = "Usage: newtest [-s|-c host] [options]\n"
                     "       newtest [-h|--help]\n\n"
                     "Server or Client:\n"
                     "  -p, --port      #         server port to listen on/connect to\n"
                     "  -h, --help                show this message and quit\n"
                     "  -B, --bind      <host>    bind to the interface associated with the address <host>\n"
                     "  -s, --server              run in server mode\n"
                     "  -c, --client    <host>    run in client mode, connecting to <host>\n"
                     ;

void timer_set(int interval);

void timer_handler (int signum)
{
    duration--;
}

void timer_init()
{
     struct sigaction sa;

     memset (&sa, 0, sizeof (sa));
     sa.sa_handler = &timer_handler;
     sigaction (SIGALRM, &sa, NULL);
}

void timer_set(int interval)
{
    struct itimerval timer;

    timer.it_value.tv_sec = interval;
    timer.it_value.tv_usec = 0;

    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 0;

    setitimer (ITIMER_REAL, &timer, NULL);
}

static inline void add_to_epfd(int fd, int type, int epfd)
{
    struct epoll_event ev;

    ev.data.fd = fd;
    ev.events = type;
    epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev);
}

int parse_arguments(struct controll_blk *test, int argc, char **argv)
{
    static struct option longopts[] =
    {
        {"port", required_argument, NULL, 'p'},
        {"server", no_argument, NULL, 's'},
        {"client", required_argument, NULL, 'c'},
        {"bind", required_argument, NULL, 'B'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };
    int flag;
    int portno;
    char *endptr;
    char* slash;

    test->pkt_size = 65536;
    while ((flag = getopt_long(argc, argv, "p:sc:l:hP:n", longopts, NULL)) != -1) {
        switch (flag) {
            case 'p':
                portno = atoi(optarg);
                if (portno < 1 || portno > 65535) {
                    i_errno = IEBADPORT;
                    return -1;
                }
                test->server_port = portno;
                break;
            case 's':
                if (test->role == 'c') {
                    i_errno = IESERVCLIENT;
                    return -1;
                }
                test->role = 's';
                test->mode = 1;
                break;
            case 'c':
                if (test->role == 's') {
                    i_errno = IESERVCLIENT;
                    return -1;
                }
                test->role = 'c';
                test->mode = 2;
                test->server_ip = strdup(optarg);
                break;
            case 'B':
                test->bind_address = strdup(optarg);
                test->mode = 1;
                break;
            case 'h':
                printf("%s", usage);
                exit(0);
            default:
                printf("%s", usage);
                exit(1);
        }
    }

    return 0;
}
int sever_proc(){
  while(1)
    {

    }
  }
int client_proc(){
        connfd = socket(AF_INET, SOCK_STREAM, 0);
        if (connect(connfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
          perror("connect failed: ");
          continue;
        }
        add_to_epfd(connfd, EPOLLOUT, epfd);
        timer_set(test.interval);

        nfds = epoll_wait(epfd, events, 65536, eptimeout);
        for (i = 0; i < nfds; i++) {
          timer_set(test.interval);
          bytes = write(events[i].data.fd, buffer, test.pkt_size);
        }
        for (i = 0; i < nsds; i++) {
          close(sds[i]);
        }
 }

int main(int argc, char *argv[])
{
    int listenfd = 0, connfd = 0;
    struct sockaddr_in serv_addr;
    char *buffer;
    int epfd;
    struct epoll_event *events;
    unsigned long *r_bitmap;
    unsigned long *w_bitmap;
    int i;
    int j;
    int bytes;
    struct controll_blk test;
    size_t total = 0;

    memset(&test, 0, sizeof(test));
    if (parse_arguments(&test, argc, argv) < 0) {
        printf(" error - %s\n");
        exit(1);
    }

    memset(&serv_addr, '0', sizeof(serv_addr));

    buffer = malloc(65536);
    r_bitmap = (unsigned long *)malloc(sizeof(unsigned long) * 1024);
    w_bitmap = (unsigned long *)malloc(sizeof(unsigned long) * 1024);
    events = (struct epoll_event *)malloc(sizeof(struct epoll_event) * 10);
    sds = (int *)malloc(sizeof(int) * 10);
    epfd = epoll_create(1);

    serv_addr.sin_family = AF_INET; // IPv4
    if (test.bind_address) {
        serv_addr.sin_addr.s_addr = inet_addr(test.bind_address);
    } else {
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        if (test.server_ip) {
            serv_addr.sin_addr.s_addr = inet_addr(test.server_ip);
        }
    }
    serv_addr.sin_port = htons(test.server_port);

    if (test.role == 's') {
        listenfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
        bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
        listen(listenfd, 65536);
        add_to_epfd(listenfd, EPOLLIN, epfd);
    }

    eptimeout = 1000;
    timer_init();
    last_duration = duration;
    if (test.role == 's') {
      server_proc();
    } else {// C
      client_proc();
    }
}