zoukankan      html  css  js  c++  java
  • 阻塞式I/O实现简单TCP通信

    一、技术简介

     (1)服务端打开两个端口9999和6666监听外来连接;

     (2)服务端的子进程通过端口9999监听外来消息,通过端口6666发送消息;

     (3)客户端的子进程处理外来消息,父进程发送消息

    二、服务器程序

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <sys/un.h>
    
    #define SERV_PORT1 9999
    #define SERV_PORT2 6666
    #define MAXLINE 4096
    
    #define SA struct sockaddr
    
    void send_msg(int);
    void listen_msg(int, const struct sockaddr*);
    char *sock_ntop(const struct sockaddr*, socklen_t);
    
    int main(int argc, char *argv[]) {
        int listenfd1, connfd1;
        int listenfd2, connfd2;
        pid_t childpid;
        socklen_t clilen1, clilen2;
        struct sockaddr_in servaddr1, servaddr2;
        struct sockaddr_in cliaddr1, cliaddr2;
    
        listenfd1 = socket(AF_INET, SOCK_STREAM, 0);
        listenfd2 = socket(AF_INET, SOCK_STREAM, 0);
    
        bzero(&servaddr1, sizeof(servaddr1));
        servaddr1.sin_family = AF_INET;
        servaddr1.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr1.sin_port = htons(SERV_PORT1);
    
        bzero(&servaddr2, sizeof(servaddr2));
        servaddr2.sin_family = AF_INET;
        servaddr2.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr2.sin_port = htons(SERV_PORT2);
    
        bind(listenfd1, (SA *)&servaddr1, sizeof(servaddr1));
        bind(listenfd2, (SA *)&servaddr2, sizeof(servaddr2));
    
        listen(listenfd1, 1);
        listen(listenfd2, 1);
    
        clilen1 = sizeof(cliaddr1);
        clilen2 = sizeof(cliaddr2);
        connfd1 = accept(listenfd1, (SA *)&cliaddr1, &clilen1);
        connfd2 = accept(listenfd2, (SA *)&cliaddr2, &clilen2);
    
        if (connfd1 && connfd2) {
            if ( (childpid = fork()) == 0) {
              close(listenfd2);
              close(connfd2);
              close(listenfd1);
              listen_msg(connfd1, (SA *)&cliaddr1);
              close(connfd1);
              exit(0);
          }
          close(listenfd1);
          close(connfd1);
          close(listenfd2);
          send_msg(connfd2);
          close(connfd2);
        }
        exit(0);
    }
    
    void listen_msg(int sockfd, const struct sockaddr *addr) {
        ssize_t n;
        char buf[MAXLINE];
    
        while ( (n = read(sockfd, buf, MAXLINE)) > 0) {
          printf("[%s]: ", sock_ntop(addr, sizeof(addr)));
          fputs(buf, stdout);
          bzero(buf, sizeof(buf));
        }
    }
    
    void send_msg(int sockfd) {
        char buf[MAXLINE];
    
        while (fgets(buf, MAXLINE, stdin) != NULL) {
            write(sockfd, buf, sizeof(buf));    
        }
    }
    
    char *sock_ntop(const struct sockaddr *sa, socklen_t salen) {
    
        char portstr[8];
        static char str[128];
    
        switch (sa->sa_family) {
            case AF_INET: {
                struct sockaddr_in    *sin = (struct sockaddr_in *) sa;
    
                if (inet_ntop(AF_INET, &sin->sin_addr, str,
                    sizeof(str)) == NULL) {
                    return(NULL);
                }
                if (ntohs(sin->sin_port) != 0) {
                    snprintf(portstr, sizeof(portstr), ":%d",
                    ntohs(sin->sin_port));
                    strcat(str, portstr);
                }
                return(str);
            }
            case AF_INET6: {
                struct sockaddr_in6    *sin6 = (struct sockaddr_in6 *) sa;
    
                str[0] = '[';
                if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + 1,
                    sizeof(str) - 1) == NULL) {
                    return(NULL);
                }
                if (ntohs(sin6->sin6_port) != 0) {
                    snprintf(portstr, sizeof(portstr), "]:%d",
                    ntohs(sin6->sin6_port));
                    strcat(str, portstr);
                    return(str);
                }
                return (str + 1);
            }
            case AF_UNIX: {
                struct sockaddr_un    *unp = (struct sockaddr_un *) sa;
    
                if (unp->sun_path[0] == 0) {
                    strcpy(str, "(no pathname bound)");
                } else {
                    snprintf(str, sizeof(str), "%s", unp->sun_path);
                }
                return(str);
            }
            default: {
                snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",
                     sa->sa_family, salen);
                return(str);
            }
        }
        return (NULL);
    }

    三、客户端程序

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <strings.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    
    #define SA struct sockaddr
    #define SERV_PORT1 9999
    #define SERV_PORT2 6666
    #define MAXLINE 4096
    
    void send_msg(int);
    void listen_msg(int, const struct sockaddr*);
    char *sock_ntop(const struct sockaddr*, socklen_t);
    
    int main(int argc, char *argv[]) {
        pid_t childpid;
        int sockfd1,sockfd2;
        int connstatus1, connstatus2;
        struct sockaddr_in servaddr1, servaddr2;
    
        if (argc != 2) {
            printf("usage: %s <IPaddress>
    ", argv[0]);
            exit(0);
        }
        
        sockfd1 = socket(AF_INET, SOCK_STREAM, 0);
        sockfd2 = socket(AF_INET, SOCK_STREAM, 0);
    
        bzero(&servaddr1, sizeof(servaddr1));
        servaddr1.sin_family = AF_INET;
        servaddr1.sin_port = htons(SERV_PORT1);
        inet_pton(AF_INET, argv[1], &servaddr1.sin_addr);
    
        bzero(&servaddr2, sizeof(servaddr2));
        servaddr2.sin_family = AF_INET;
        servaddr2.sin_port = htons(SERV_PORT2);
        inet_pton(AF_INET, argv[1], &servaddr2.sin_addr);
    
        connstatus1 = connect(sockfd1, (SA *)&servaddr1, sizeof(servaddr1));
        connstatus2 = connect(sockfd2, (SA *)&servaddr2, sizeof(servaddr2));
    
        if (connstatus1 == 0 && connstatus2 == 0) {
            if ( (childpid = fork()) == 0) {
              close(sockfd1);
              listen_msg(sockfd2, (SA *)&servaddr2);
              close(sockfd2);
              exit(0);
          }
          close(sockfd2);
          send_msg(sockfd1);
          close(sockfd1);
        } else {
            printf("connect failed!
    ");
        }
        exit(0);
    }
    
    void listen_msg(int sockfd, const struct sockaddr *addr) {
        ssize_t n;
        char buf[MAXLINE];
    
        while ( (n = read(sockfd, buf, MAXLINE)) > 0) {
           printf("[%s]: ", sock_ntop(addr, sizeof(addr)));
            fputs(buf, stdout);
            bzero(buf, sizeof(buf));
        }
    }
    
    void send_msg(int sockfd) {
        char buf[MAXLINE];
    
        while (fgets(buf, MAXLINE, stdin) != NULL) {
            write(sockfd, buf, sizeof(buf));
        }
    }
    
    char *sock_ntop(const struct sockaddr *sa, socklen_t salen) {
        
        char portstr[8];    
        static char str[128];
       
        switch (sa->sa_family) {
            case AF_INET: {
                struct sockaddr_in    *sin = (struct sockaddr_in *) sa;
    
                if (inet_ntop(AF_INET, &sin->sin_addr, str, 
                    sizeof(str)) == NULL) {
                    return(NULL);
                }
                if (ntohs(sin->sin_port) != 0) {
                    snprintf(portstr, sizeof(portstr), ":%d", 
                        ntohs(sin->sin_port));
                    strcat(str, portstr);
                }
                return(str);
            }
            case AF_INET6: {
                struct sockaddr_in6    *sin6 = (struct sockaddr_in6 *) sa;
    
                str[0] = '[';
                if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + 1, 
                    sizeof(str) - 1) == NULL) {
                    return(NULL);
                }
                if (ntohs(sin6->sin6_port) != 0) {
                    snprintf(portstr, sizeof(portstr), "]:%d",
                        ntohs(sin6->sin6_port));
                    strcat(str, portstr);
                    return(str);
                }
                return (str + 1);
            }
            case AF_UNIX: {
                struct sockaddr_un    *unp = (struct sockaddr_un *) sa;
    
                if (unp->sun_path[0] == 0) {
                    strcpy(str, "(no pathname bound)");
                } else {
                    snprintf(str, sizeof(str), "%s", unp->sun_path);
                }
                return(str);
            }
            default: {
                snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",
                     sa->sa_family, salen);
                return(str);
            }
        }
        return (NULL);
    }
  • 相关阅读:
    【jquery ,ajax,php】加载更多实例
    关于scrollTop
    jquery 底部导航透明度变化
    jquery 处理密码输入框(input type="password" ) 模仿placeholder
    物化视图基于rowID快速刷新
    ora-01653 无法通过1024扩展
    oracle临时表空间
    java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.Integer
    redis 简单使用
    BigDecimal 运算
  • 原文地址:https://www.cnblogs.com/soldierback/p/10685655.html
Copyright © 2011-2022 走看看