Socket PRGM: chat_p2p

来源:互联网 发布:微机原理接口编程题 编辑:程序博客网 时间:2024/06/07 07:07
//client_p2p#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#define ERR_EXIT(m)                        \            do                             \            {                              \                perror(m);                 \                exit(EXIT_FAILURE);        \                                           \            }while(0)struct packet{    int len;    char buf[1024];};void sig(int num){    switch (num)    {    case SIGUSR1:        printf("client recv signal %d, exit...\n", num);        exit(0);        break;    default:        break;    }}ssize_t readn(int fd, void *buf, size_t count){    size_t nleft = count;    ssize_t nread;    char *bufp = (char*)buf;    while (nleft > 0)    {        if ((nread = read(fd, bufp, nleft)) < 0)        {            if (errno == EINTR)                continue;            return -1;        }        else if (nread == 0) //若对方已关闭            return count - nleft;        bufp += nread;        nleft -= nread;    }    return count;}ssize_t writen(int fd, const void *buf, size_t count){    size_t nleft = count;    ssize_t nwritten;    char *bufp = (char*)buf;    while (nleft > 0)    {        if ((nwritten = write(fd, bufp, nleft)) < 0)        {            if (errno == EINTR)                continue;            return -1;        }        else if (nwritten == 0)            continue;        bufp += nwritten;        nleft -= nwritten;    }    return count;}void read_service (int conn){    struct packet recvbuf;    int n;    while (1)    {        memset(&recvbuf, 0, sizeof(recvbuf));        int ret = readn(conn, &recvbuf.len, 4);        if (ret == -1)            ERR_EXIT("read failed");        else if (ret < 4)        {            printf("server close\n");            break;        }        n = ntohl(recvbuf.len);        ret = readn(conn, recvbuf.buf, n);        if (ret == -1)            ERR_EXIT("read");        else if (ret < n)        {            printf("server close\n");            break;        }        fputs(recvbuf.buf, stdout);    }    return ;}void write_service (int conn){    struct packet sendbuf;    int n;    while (1)    {        memset(&sendbuf, 0, sizeof(sendbuf));        if (fgets(sendbuf.buf, sizeof(sendbuf.buf), stdin) == NULL)            ERR_EXIT("fgets failed");        n = strlen(sendbuf.buf);        sendbuf.len = htonl(n);        writen(conn, &sendbuf, 4 + n);    }    close(conn);    return ;}int main(){    int sockfd;    //建立socket    sockfd = socket(AF_INET, SOCK_STREAM, 0);    if (sockfd == -1)    {        perror("create socket failed");        return 1;    }    //connect 连接server    struct sockaddr_in serveraddr_in;    memset(&serveraddr_in, 0, sizeof(serveraddr_in));    serveraddr_in.sin_family = AF_INET;    serveraddr_in.sin_port = htons(12345);   /* port in network byte order */    serveraddr_in.sin_addr.s_addr = inet_addr("127.0.0.1");    if ( connect(sockfd, (struct sockaddr *)&serveraddr_in, sizeof(serveraddr_in) ) == -1)    {        perror("connect failed");        return 1;    }    if ( signal(SIGUSR1, sig) == SIG_ERR )    {        perror("install signal error");    }    int pid = fork();    if (pid == 0)    {        //业务        while (1)        {            read_service(sockfd);            kill(getppid(), SIGUSR1);            close(sockfd);            exit (1);        }    }    else    {        write_service(sockfd);    }    return 0;}

//server_p2p#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#define ERR_EXIT(m)                        \            do                             \            {                              \                perror(m);                 \                exit(EXIT_FAILURE);        \                                           \            }while(0)/* struct sockaddr {               sa_family_t sa_family;               char        sa_data[14];           } struct sockaddr_in {               sa_family_t    sin_family;               in_port_t      sin_port;               struct in_addr sin_addr;           }; struct in_addr {               uint32_t       s_addr;           };*//*    typedef void (*sighandler_t)(int);    sighandler_t signal(int signum, sighandler_t handler);*/struct packet{    int len;    char buf[1024];};void sig(int num){    switch (num)    {    case SIGUSR1:        printf("server recv signal %d, exit...\n", num);        exit(1);        break;    default:        break;    }}ssize_t readn(int fd, void *buf, size_t count){    size_t nleft = count;    ssize_t nread;    char *bufp = (char*)buf;    while (nleft > 0)    {        if ((nread = read(fd, bufp, nleft)) < 0)        {            if (errno == EINTR)                continue;            return -1;        }        else if (nread == 0) //若对方已关闭            return count - nleft;        bufp += nread;        nleft -= nread;    }    return count;}ssize_t writen(int fd, const void *buf, size_t count){    size_t nleft = count;    ssize_t nwritten;    char *bufp = (char*)buf;    while (nleft > 0)    {        if ((nwritten = write(fd, bufp, nleft)) < 0)        {            if (errno == EINTR)                continue;            return -1;        }        else if (nwritten == 0)            continue;        bufp += nwritten;        nleft -= nwritten;    }    return count;}void read_service (int conn){    struct packet recvbuf;    int n;    while (1)    {        memset(&recvbuf, 0, sizeof(recvbuf));        int ret = readn(conn, &recvbuf.len, 4);        if (ret == -1)            ERR_EXIT("read failed");        else if (ret < 4)        {            printf("client close\n");            break;        }        n = ntohl(recvbuf.len);        ret = readn(conn, recvbuf.buf, n);        if (ret == -1)            ERR_EXIT("read");        else if (ret < n)        {            printf("client close\n");            //printf("\n\nclient %s:%d  disconn\n\n", inet_ntoa(clientaddr_in.sin_addr), ntohs(clientaddr_in.sin_port));            break;        }        fputs(recvbuf.buf, stdout);    }    return ;}void write_service (int conn){    struct packet sendbuf;    int n;    while (1)    {        memset(&sendbuf, 0, sizeof(sendbuf));        if (fgets(sendbuf.buf, sizeof(sendbuf.buf), stdin) == NULL)            ERR_EXIT("fgets failed");        n = strlen(sendbuf.buf);        sendbuf.len = htonl(n);        writen(conn, &sendbuf, 4 + n);    }    close(conn);    return ;}int main(){    int serverfd;    //建立socket    serverfd = socket(AF_INET, SOCK_STREAM, 0);    if (serverfd == -1)    {        perror("create socket failed");        return 1;    }    //给TCP设置地址可重用    int on = 1;    if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)    {        printf("setsockopt failed %s\n", strerror(errno));        return EXIT_FAILURE;    }    //bind 绑定端口,IP    struct sockaddr_in serveraddr_in;    memset(&serveraddr_in, 0, sizeof(serveraddr_in));    serveraddr_in.sin_family = AF_INET;    serveraddr_in.sin_port = htons(12345);   /* port in network byte order */    serveraddr_in.sin_addr.s_addr = inet_addr("0.0.0.0");    if ( bind(serverfd, (struct sockaddr *)&serveraddr_in, sizeof(serveraddr_in)) == -1)    {        perror("bind failed");        return 1;    }    //listen 被动套接字,监听端口    if (listen(serverfd, 20) == -1)    {        perror("listen failed");        return 1;    }    //while(1)    {        //accept 阻塞等待client连接        int clientfd = -1;        struct sockaddr_in clientaddr_in;        memset(&clientaddr_in, 0, sizeof(clientaddr_in));        socklen_t clientaddr_len = sizeof(clientaddr_in);        if ( (clientfd = accept(serverfd, (struct sockaddr *)&clientaddr_in, &clientaddr_len) ) == -1)        {            perror("accept failed");            return 1;        }        else        {            printf("\n\nclient %s:%d  connected\n\n", inet_ntoa(clientaddr_in.sin_addr), ntohs(clientaddr_in.sin_port));        }        if ( signal(SIGUSR1, sig) == SIG_ERR )        {            perror("install signal error");        }        int pid = fork();        if (pid == 0)        {            //子进程关闭被动套接字            close(serverfd);            //业务            while (1)            {                read_service(clientfd);                kill(getppid(), SIGUSR1);                close(clientfd);                exit (1);            }        }        else        {            write_service(clientfd);        }    }    return 0;}