zoukankan      html  css  js  c++  java
  • Unix Domain Socket 域套接字实现

    主要注意流程:

    STREAM SOCKET: 

    Server :  socket() --->  bind() ---> listen()  ---> accept()

    Client:    scoket() ---> connect()

    参考文章一篇就够: http://troydhanson.github.io/misc/Unix_domain_sockets.html

    自己写的 一个 Server 和 一个Client:

    //Server
    //
    //  unix_domain_server.c
    //  UnixDomainServer
    //
    //  Created by gtliu on 7/11/13.
    //  Copyright (c) 2013 GT. All rights reserved.
    //
    
    #include "MITLogModule.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <stddef.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    
    #define FUNC_FAIL                           -1
    #define FUNC_SUCCESS                        0
    #define SOCKADDR_UN_SUN_PATH_MAX_LEN        103  // 104 - 1
    #define SER_ACCEPT_CON_NUM                  1
    
    /**
     * Create a server endpoint of a connection.
     *
     * @param  scok_path: the unix domain socket path
     * @return return the file descirption if all ok, <0 on err
     */
    int create_serv_listen(const char *sock_path)
    {
        size_t path_len = strlen(sock_path);
        if (path_len == 0) {
            MITLogWrite(MITLOG_LEVEL_ERROR, "socket path can't be empty");
            return FUNC_FAIL;
        } else if (path_len > SOCKADDR_UN_SUN_PATH_MAX_LEN) {
            MITLogWrite(MITLOG_LEVEL_ERROR, "socket path length must less than%d", SOCKADDR_UN_SUN_PATH_MAX_LEN);
            return FUNC_FAIL;
        }
        
        int fd = 0, size = 0;
        struct sockaddr_un server_un;
        memset(&server_un, 0, sizeof(server_un));
        server_un.sun_family = AF_UNIX;
        strncpy(server_un.sun_path, sock_path, sizeof(server_un.sun_path) - 1);
        
        if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
            MITLogWrite(MITLOG_LEVEL_ERROR, "socket() faild:%s", strerror(errno));
            return FUNC_FAIL;
        }
        /* in case it already exists */
        unlink(sock_path);
        
        size = offsetof(struct sockaddr_un, sun_path) + strlen(server_un.sun_path);
        if (bind(fd, (struct sockaddr *)&server_un, size) < 0) {
            MITLogWrite(MITLOG_LEVEL_ERROR, "bind() failed:%s", strerror(errno));
            close(fd);
            return FUNC_FAIL;
        }
        
        if (listen(fd, 0) < 0) {
            MITLogWrite(MITLOG_LEVEL_ERROR, "listen() failed:%s", strerror(errno));
            close(fd);
            return FUNC_FAIL;
        }
        
        return fd;
    }
    
    /**
     * Accept a client's connection and return the relative file descriptor.
     *
     * @param  listen_fd: the server socket file descriptor
     * @return return the file descirption if all ok, <0 on err
     */
    int serv_accept(int listen_fd)
    {
        int child_fd = 0, len = 0;
        struct sockaddr_un income_un;
        len = sizeof(income_un);
    
        if ((child_fd = accept(listen_fd, (struct sockaddr *)&income_un, &len)) < 0) {
            MITLogWrite(MITLOG_LEVEL_ERROR, "accept() failed:%s", strerror(errno));
            /* often errno=EINTR, if signal caught */
            return FUNC_FAIL;
        }
        return child_fd;
    }
    
    
    int main(int argc, const char * argv[])
    {
    
        MITLogOpen("unix_domain_server");
        
        char *sock_path = "/tmp/domain_socket_one";
        if (argc > 1) {
            sock_path = (char *) argv[1];
        }
            
        MITLogWrite(MITLOG_LEVEL_COMMON, "Starting the server...");
        int listen_fd = create_serv_listen(sock_path);
        if (listen_fd == FUNC_FAIL) {
            return FUNC_FAIL;
        }
        
        MITLogWrite(MITLOG_LEVEL_COMMON, "Wait for the client... listen_fd:%d", listen_fd);
        int child_fd = serv_accept(listen_fd);
        if (child_fd == FUNC_FAIL) {
            close(listen_fd);
            return FUNC_FAIL;
        }
        
        char recv_buffer[1024] = {0};
        while (1) {
            MITLogWrite(MITLOG_LEVEL_COMMON, "Wait for the message...");
            if(read(child_fd, recv_buffer, sizeof(recv_buffer) - 1) > 0) {
                printf("Recieve message:%s
    ", recv_buffer);
            }
            sleep(2);
        } 
        
        MITLogClose();
        return 0;
    }
    
    
    //Client
    //
    //  main.c
    //  UnixDomainClient
    //
    //  Created by gtliu on 7/11/13.
    //  Copyright (c) 2013 GT. All rights reserved.
    //
    
    #include "MITLogModule.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <stddef.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/un.h>
    #include <sys/stat.h>
    
    #define FUNC_FAIL                           -1
    #define FUNC_SUCCESS                        0
    #define SOCKADDR_UN_SUN_PATH_MAX_LEN        103  // 104 - 1
    #define SER_ACCEPT_CON_NUM                  1
    
    /**
     * Create a server endpoint of a connection.
     *
     * @param  scok_path: the unix domain socket path
     * @return return the file descirption if all ok, <0 on err
     */
    int client_connection(const char *sock_path)
    {
        size_t path_len = strlen(sock_path);
        if (path_len == 0) {
            MITLogWrite(MITLOG_LEVEL_ERROR, "socket path can't be empty");
            return FUNC_FAIL;
        } else if (path_len > SOCKADDR_UN_SUN_PATH_MAX_LEN) {
            MITLogWrite(MITLOG_LEVEL_ERROR, "socket path length must less than%d", SOCKADDR_UN_SUN_PATH_MAX_LEN);
            return FUNC_FAIL;
        }
        
        int fd = 0, len = 0;
        if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
            MITLogWrite(MITLOG_LEVEL_ERROR, "socket() faild:%s", strerror(errno));
            return FUNC_FAIL;
        }
        
        struct sockaddr_un client_un;
        memset(&client_un, 0, sizeof(client_un));
        client_un.sun_family = AF_UNIX;
        strncpy(client_un.sun_path, sock_path, sizeof(client_un.sun_path) - 1);
        
        len = offsetof(struct sockaddr_un, sun_path) + strlen(client_un.sun_path);
        if ((connect(fd, (struct sockaddr *)&client_un, len)) < 0) {
            MITLogWrite(MITLOG_LEVEL_ERROR, "connect() failed:%s", strerror(errno));
            close(fd);
            return FUNC_FAIL;
        }
        
        return fd;
    }
    
    int main(int argc, const char * argv[])
    {
        
        MITLogOpen("unix_domain_client");
    
        char *sock_path = "/tmp/domain_socket_one";
        if (argc > 1) {
            sock_path = (char *) argv[1];
        }
        
        MITLogWrite(MITLOG_LEVEL_COMMON, "Starting the client...");
        int client_fd = client_connection(sock_path);
        if (client_fd == FUNC_FAIL) {
            return FUNC_FAIL;
        }
            
        for (int i=1; i < 100; ++i) {
            MITLogWrite(MITLOG_LEVEL_COMMON, "Send message to server...");
            char msg[256] = {0};
            sprintf(msg, "client message :%d", i);
            if(write(client_fd, msg, strlen(msg)) > 0) {
                MITLogWrite(MITLOG_LEVEL_COMMON, "Send message :%d success", i);
            }
            sleep(2);
        }
        
        MITLogClose();
        return 0;
    }
        
    



  • 相关阅读:
    MySQL sys Schema 简单介绍-2
    dubbo服务+Spring事务+AOP动态数据源切换 出错
    sql 查询优化
    spring事务-说说Propagation及其实现原理
    Redis 分布式锁
    三、操作符
    二、一切皆是对象
    一、对象导论
    SpringMVC工作原理
    数据库性能优化策略
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3187014.html
Copyright © 2011-2022 走看看