{"id":1852,"date":"2019-01-22T12:10:29","date_gmt":"2019-01-22T04:10:29","guid":{"rendered":"https:\/\/www.yusian.com\/blog\/?p=1852"},"modified":"2020-12-02T12:14:01","modified_gmt":"2020-12-02T04:14:01","slug":"%e5%a4%9a%e8%bf%9b%e7%a8%8b%e5%b9%b6%e5%8f%91%e6%9c%8d%e5%8a%a1%e5%99%a8%e7%a8%8b%e5%ba%8f","status":"publish","type":"post","link":"https:\/\/www.yusian.com\/blog\/cpp\/2019\/01\/22\/1210291852.html","title":{"rendered":"\u591a\u8fdb\u7a0b\u5e76\u53d1\u670d\u52a1\u5668\u7a0b\u5e8f"},"content":{"rendered":"<p>1\u3001server.c<\/p>\n<pre><code class=\"language-c line-numbers\">#include \"wrap.h\"\n#include &lt;ctype.h&gt;\n#include &lt;strings.h&gt;\n#include &lt;signal.h&gt;\n#include &lt;wait.h&gt;\n\ntypedef void (*sighandler_t)(int);\nvoid sigchld_handler(int signal)\n{\n    int wstatus;\n    pid_t pid = wait(&amp;wstatus);\n    while(pid &gt; 0){\n        printf(\"close pid %d success...\\n\", pid);\n        pid = wait(&amp;wstatus);\n    }\n}\nvoid response_message(int sfd);\n#define SERVER_PORT 3000\nint main(){\n    int sfd, cfd;\n    \/\/ 1\u3001socket\n    sfd = Socket(AF_INET, SOCK_STREAM, 0);\n    \/\/ 2\u3001bind\n    struct sockaddr_in sockaddr;\n    bzero(&amp;sockaddr, sizeof(sockaddr));\n    sockaddr.sin_family = AF_INET;\n    sockaddr.sin_port = htons(SERVER_PORT);\n    sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);\n    \/\/ inet_pton(AF_INET, \"10.211.55.6\", &amp;sockaddr.sin_addr.s_addr);\n    Bind(sfd, &amp;sockaddr, sizeof(sockaddr));\n    \/\/ 3\u3001listen\n    Listen(sfd, 128);\n    while(1){\n        \/\/ 4\u3001\u5f00\u542f\u76d1\u542caccept\n        struct sockaddr_in addr;\n        bzero(&amp;addr, sizeof(addr));\n        socklen_t length = sizeof(addr);\n        cfd = Accept(sfd, &amp;addr, &amp;length);\n        char buf[BUFSIZ];\n        bzero(buf, BUFSIZ);\n        printf(\"Client connected ip:%s, port:%d\\n\", inet_ntop(AF_INET, &amp;addr.sin_addr.s_addr, buf, BUFSIZ), ntohs(addr.sin_port));\n        pid_t pid = fork();\n        if (pid &lt; 0){\n            perror(\"fork error\");\n            exit(1);\n        }else if(pid == 0){\n            \/\/ \u5b50\u8fdb\u7a0b\n            close(sfd);\n            break;\n        }else{\n            \/\/ \u7236\u8fdb\u7a0b\uff0c\u6ce8\u518c\u4fe1\u53f7\u6355\u83b7\n            sighandler_t handler = signal(SIGCHLD, sigchld_handler);\n            if (handler == SIG_ERR){\n                perror(\"signal error\");\n                exit(1);\n            }\n            close(cfd);\n        }\n    }\n    \/\/ \u5b50\u8fdb\u7a0b\n    if (pid == 0){\n        while(1){\n            response_message(cfd);\n        }\n    }\n    return 0;\n}\n\/\/ \u5ba2\u6237\u7aef\u6d88\u606f\u5904\u7406\u51fd\u6570\nvoid response_message(int cfd)\n{\n    char buf[BUFSIZ];\n    int i;\n    ssize_t n = Readn(cfd, buf, BUFSIZ);\n    if (n == 0){\n        \/*\n           struct sockaddr_in c_addr;\n           socklen_t length = sizeof(c_addr);\n           getsockname(cfd, (struct sockaddr *)&amp;c_addr, &amp;length);\n           printf(\"Client closed ip:%s port:%d\\n\",\n           inet_ntop(AF_INET, &amp;c_addr.sin_addr.s_addr, buf, BUFSIZ),\n           ntohs(c_addr.sin_port));\n           *\/\n        close(cfd);\n        exit(1);\n    }else if(n &lt; 0){\n        close(cfd);\n        perror(\"read error\");\n        exit(1);\n    }\n    for(i = 0; i &lt; n; i++){\n        buf[i] = toupper(buf[i]);\n    }\n    write(cfd, buf, n);\n}\n<\/code><\/pre>\n<p>wrap.h<\/p>\n<pre><code class=\"language-c line-numbers\">#ifndef _WRAP_H_\n#define _WRAP_H_\n#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;unistd.h&gt;\n#include &lt;sys\/socket.h&gt;\n#include &lt;arpa\/inet.h&gt;\n\nint Socket(int domain, int type, int protocol);\nint Bind(int sockfd, const struct sockaddr_in *addr, socklen_t addrlen);\nint Listen(int sockfd, int backlog);\nint Accept(int sockfd, struct sockaddr_in *addr, socklen_t *addrlen);\nint Connect(int sockfd, const struct sockaddr_in *addr, socklen_t addrlen);\nssize_t Readn(int fd, void *buf, size_t count);\n\n#endif\n<\/code><\/pre>\n<p>wrap.c<\/p>\n<pre><code class=\"language-c line-numbers\">#include \"wrap.h\"\n#include &lt;errno.h&gt;\nvoid print_err(const char* descript)\n{\n    perror(descript);\n    exit(1);\n}\n\nint Socket(int domain, int type, int protocol)\n{\n    int ret = socket(domain, type, protocol);\n    if (ret &lt; 1) print_err(\"socket error\");\n    return ret;\n}\n\nint Bind(int sockfd, const struct sockaddr_in *addr, socklen_t addrlen)\n{\n    int ret = bind(sockfd, (struct sockaddr *)addr, addrlen);\n    if (ret &lt; 0) print_err(\"bind error\");\n    return ret;\n}\n\nint Accept(int sockfd, struct sockaddr_in *addr, socklen_t *addrlen)\n{\n    int sfd;\nagain:\n    sfd = accept(sockfd, (struct sockaddr *)addr, addrlen);\n    if (sfd &lt; 0){\n        \/\/ \u963b\u585e\u7b49\u5f85\uff0c\u8003\u8651\u88ab\u4fe1\u53f7\u4e2d\u65ad\u7684\u60c5\u51b5\n        if ((errno == ECONNABORTED) || (errno == EINTR)){\n            goto again;\n        }else{\n            print_err(\"accept error\");\n        }\n    }\n    return sfd;\n}\n\nint Listen(int sockfd, int backlog)\n{\n    int ret = listen(sockfd, backlog);\n    if (ret &lt; 0) print_err(\"listen error\");\n    return ret;\n}\n\nint Connect(int sockfd, const struct sockaddr_in *addr, socklen_t addrlen)\n{\n    int ret = connect(sockfd, (struct sockaddr *)addr, addrlen);\n    if (ret &lt; 0) print_err(\"connect error\");\n    return ret;\n}\n\nssize_t Readn(int fd, void *buf, size_t count)\n{\n    size_t readed = 0;\/\/ \u5df2\u8bfb\u6570\n        size_t remain = count;\/\/ \u672a\u8bfb\u6570\n    while(remain &gt; 0){\n        int n = read(fd, buf+readed, remain);\n        if (n &lt; 0){    \/\/ \u5f02\u5e38\u5904\u7406\n            if (errno == EINTR){\n                n = 0;\/\/ \u4fe1\u53f7\u4e2d\u65ad\uff0c\u7ee7\u7eed\u5faa\u73af\n            }else{\n                return n;\/\/ \u5f02\u5e38\u60c5\u51b5\u76f4\u63a5\u8fd4\u56de\n            }\n        }else if (n &lt; remain){\n            remain -= n;\n            break;\n        }\n        readed += n;\n        remain -= n;\n    }\n    return count - remain;\/\/ \u8fd4\u56de\u5e94\u8bfb\u6570-\u672a\u8bfb\u6570\n}\n<\/code><\/pre>\n<p>\u8fd0\u884c\u7ed3\u679c\uff1a<\/p>\n<pre><code class=\"language-cmd line-numbers\">parallels@ubuntu:~\/Linux\/mp-socket$ .\/server.out\nClient connected ip:10.211.55.2, port:49399\nClient connected ip:10.211.55.2, port:49400\nclose pid 5702 success...\nclose pid 5745 success...\n^C\nparallels@ubuntu:~\/Linux\/mp-socket$\n<\/code><\/pre>\n<p>2\u3001client.c<\/p>\n<pre><code class=\"language-c line-numbers\">#include \"wrap.h\"\n#include &lt;unistd.h&gt;\n#include &lt;string.h&gt;\n\n#define SERVER_PORT 3000\n#define SERVER_IP \"10.211.55.6\"\nint main(){\n    int sfd = Socket(PF_INET, SOCK_STREAM, 0);\n\n    struct sockaddr_in svr_addr;\n    svr_addr.sin_family = PF_INET;\n    svr_addr.sin_port = htons(SERVER_PORT);\n    \/\/ \u6e050\u64cd\u4f5c\n    memset(&amp;svr_addr.sin_addr.s_addr, 0, sizeof(svr_addr.sin_addr.s_addr));\n    \/\/ \u5c06\u70b9\u5206\u5341\u8fdb\u5236\u5b57\u7b26\u4e32\u8f6c\u4e3a\u5b57\u8282\u5e8f\n    inet_pton(PF_INET, SERVER_IP, &amp;svr_addr.sin_addr.s_addr);\n    \/\/ \u53d1\u8d77\u7f51\u7edc\u8fde\u63a5\n    Connect(sfd, &amp;svr_addr, sizeof(svr_addr));\n    printf(\"\u670d\u52a1\u5668\u8fde\u63a5\u6210\u529f\uff01\\n\");\n    char buf[BUFSIZ];\n    while(1){\n        \/\/ \u8bfb\u53d6\u8f93\u5165\u6d41\n        fgets(buf, sizeof(buf), stdin);\n        \/\/ \u5199\u5165\u5957\u63a5\u5b57\n        write(sfd, buf, strlen(buf));\n        \/\/ \u8bfb\u53d6\u670d\u52a1\u5668\u54cd\u5e94\n        int n = read(sfd, buf, sizeof(buf));\n        \/\/ \u5c06\u7ed3\u679c\u8f93\u51fa\u5230\u6807\u51c6\u8f93\u51fa\u6d41\n        write(STDOUT_FILENO, buf, n);\n    }\n    close(sfd);\n    return 0;\n}\n<\/code><\/pre>\n<p>\u8fd0\u884c\u7ed3\u679c<\/p>\n<pre><code class=\"language-cmd line-numbers\">yusian@SianMac2:~\/Linux\/socket$ .\/client.out\n\u670d\u52a1\u5668\u8fde\u63a5\u6210\u529f\uff01\nadf\nADF\naaa\nAAA\n^C\nyusian@SianMac2:~\/Linux\/socket$\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>1\u3001server.c #include &#8220;wrap.h&#8221; #include &lt;ctype.h&gt; #include &lt;strings.h&gt; #include &lt;signal.h&gt; #include &lt;wait.h&gt; typedef void (*sighandler_t)(int); void sigchld_handler(int signal) { int wstatus; pid_t pid = wait(&amp;wstatus); while(pid &gt; 0){ printf(&#8220;close pid %d success&#8230;\\n&#8221;, pid); pid = wait(&amp;wstatus); } } void response_message(int sfd); #define SERVER_PORT 3000 int main(){ int sfd, cfd; \/\/ 1\u3001socket sfd = Socket(AF_INET, SOCK_STREAM, 0); [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[88],"tags":[310,322,321],"class_list":["post-1852","post","type-post","status-publish","format-standard","hentry","category-cpp","tag-linux","tag-322","tag-321"],"_links":{"self":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/posts\/1852","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/comments?post=1852"}],"version-history":[{"count":0,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/posts\/1852\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/media?parent=1852"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/categories?post=1852"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/tags?post=1852"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}