一个简单网络客户端demo示例

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>  /* basic system data types */
#include <sys/socket.h> /* basic socket definitions */
#include <netinet/in.h> /* sockaddr_in{} and other Internet defns */
#include <arpa/inet.h>  /* inet(3) functions */
#include <errno.h>
#include <unistd.h>
#include <signal.h>

#define MAXSLEEP 128
#define CONNECT_TEST 255

typedef void (*SIG_FUNC)(int);


void sigpipe_handler(int sig)
{
    printf("Get signal PIPE!\n");
}

ssize_t             /* Read "n" bytes from a descriptor. */
readn(int fd, void *vptr, size_t n)
{
    size_t  nleft;
    ssize_t nread;
    char    *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ( (nread = read(fd, ptr, nleft)) < 0) {
            printf("rc < 0, errno = %d\n", errno);
            if (errno == EINTR)
                nread = 0;/* and call read() again */
            else
                return(-1);
        } else if (nread == 0) {
            //printf("nread = 0\n");
            break;      /* EOF */
        }

        nleft -= nread;
        ptr   += nread;
    }
    return(n - nleft);          /* return >= 0 */
}
ssize_t                     /* Write "n" bytes to a descriptor. */
writen(int fd, const void *vptr, size_t n)
{
    size_t      nleft;
    ssize_t     nwritten;
    const char  *ptr;

    ptr = vptr;
    nleft = n;
    while (nleft > 0) {
        if ( (nwritten = write(fd, ptr, nleft)) <= 0) {
            printf("nwritten= %d\n",nwritten);
            if (nwritten < 0 && errno == EINTR)
                nwritten = 0;   /* and call write() again */
            else
                return(-1); /* error */
        }
        printf("nwritten= %d\n",nwritten);
        nleft -= nwritten;
        ptr   += nwritten;
    }
    return(n);
}

int 
connect_retry(int domain, int type, int protocol, const struct sockaddr * addr, socklen_t alen)
{
    int numsec, fd;
    /*
    * try to connect with exponential backoff
    * if connect failed , should socket again
    */
    for (numsec = 1; numsec <= MAXSLEEP; numsec <<= 1)
    {
        if ((fd = socket(domain, type, protocol)) < 0)
        {
            printf("socket error!\n");
            return -1;
        }
        if (connect(fd, addr, alen) == 0)
        {
            /*
            * connect accept,return success
            */
            return fd;
        }
        close(fd);
        /*delay before trying again*/
        if (numsec <= MAXSLEEP/2)
        {
            sleep(numsec);
        }
    }
    return -1;
}

int client_process(int fd)
{
    char buf[100];
    printf("client sleep 10 second and write 100 bytes\n");
    sleep(10);
    writen(fd, buf, 100);
    writen(fd, buf, 100);/*generate SIGPIPE */
    while(1);
    return 0;
}


/*
 * Set signal handler for SIGCHLD,to wait child process,clean zombies
*/
int set_signal(int signo, SIG_FUNC func)
{
    struct sigaction act, oact;
    act.sa_handler = func;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (signo == SIGALRM) 
    {
#ifdef  SA_INTERRUPT
        act.sa_flags |= SA_INTERRUPT;       /* SunOS 4.x */
#endif
    } 
    else        //Only SIGALRM can interrupt the system call, otherwise we restart system call  
    {
#ifdef  SA_RESTART
        act.sa_flags |= SA_RESTART;     /* SVR4, 44BSD */
#endif
    }
    if (sigaction(signo, &act, &oact) < 0)
        return(-1);
    return 0;
}


void usage()
{
    printf("Useage: client [-a IPaddress] [-p port]\n");
}
/*
* we can also use getaddrinfo() function to get (ip and port) 
* from (hostname and servername) 
*/
int main(int argc, char *argv[])
{
    struct sockaddr_in connect_addr;
    int connect_fd, opt, n, command = -1;


    memset(&connect_addr, 0, sizeof(connect_addr));
    //set default IP address and port
    connect_addr.sin_family = AF_INET;
    connect_addr.sin_port = htons(3333);
    if (inet_aton("127.0.0.1",(struct in_addr*)&(connect_addr.sin_addr.s_addr)) == 0){
        printf("inet_aton error!\n");
        exit(1);
    }


    /*
    **use getopt() function to handle argv[]
    ** (global variables) 
    ** optarg: when getopt() return, if the opt has a arg, it will be set to optarg   
    ** opterr: not 0,will print error message; 0,will not print error message
    ** optind: the index of next argv after while loop
    ** optopt: when find a invalid opt, getopt() returns '?' or ':', and the invalid opt is set to optopt
    **
    */
    while ((opt = getopt(argc, argv, "a:p:h")) != EOF){
        switch(opt) {
        case 'a':
            if (inet_aton(optarg,(struct in_addr*)&(connect_addr.sin_addr.s_addr)) == 0)
            {
                printf("inet_aton error!\n");
                exit(1);
            }
            printf("connect IP address = %s\n", optarg);
            break;
        case 'p':
        {
            int port;
            if (sscanf(optarg, "%d", &port) != 1)
            {
                printf("port argv error!\n");
                exit(1);
            }
            connect_addr.sin_port = htons(port);
            printf("connect port = %d\n", port);
            break;
        }
        case 'h':
            usage();
            exit(0);
        default:
            usage();
            exit(0);
        }
    }
    printf("optind=%d\n",optind);
    n = argc - optind;
    if (n != 0){
        usage();
        exit(1);
    }

    /*config net connect*/
    if (set_signal(SIGPIPE, sigpipe_handler) == -1)
    {
        printf("signal SIGPIPE set error!\n");
        exit(1);
    }
    connect_fd = connect_retry(AF_INET, SOCK_STREAM, 0, 
                (struct sockaddr *)&connect_addr, sizeof(connect_addr));
    if (connect_fd < 0)
    {
        printf("connect server failed!\n");
        exit(1);
    }
    client_process(connect_fd);
    exit(0);
}

猜你喜欢

转载自blog.csdn.net/rikeyone/article/details/80973918