设为首页 收藏本站
查看: 640|回复: 0

[经验分享] linux进程间通信--本地socket(tcp部分)

[复制链接]
累计签到:2 天
连续签到:1 天
发表于 2014-11-18 09:21:07 | 显示全部楼层 |阅读模式
[内核版本]

linux-2.6.31

[尚存缺憾]
1、getsockopt和setsockopt的某些特定参数的调用(net/unix/af_unix.c中定义的*sockop函数均保留接口,返回EOPNOTSUPP错误);
2、ss命令查看到的本地socket状态需要进一步确认;

[注意事项]
1、使用本地socket进行通信时,其通信过程并不通过报文交互进行状态机切换:
    a)server端在执行listen函数之后,该socket即处于监听状态;

    b)client端在执行connect函数时,正常情况下,内核将sock状态设置为SS_CONNECTED,将sk状态设置为TCP_ESTABLISHED,然后通知server端有client请求(向server的socket发送SIGIO信号);
    c)一旦出现某一情况导致server端的最大链接请求(应该是由sk_max_ack_backlog成员定义,在listen函数中指定)使用完毕,如果不设置连接超时时间,client端应该在2147483647秒的时间超时
// include/linux/kernel.h
#define LONG_MAX((long)(~0UL>>1))
// include/linux/sched.h
#defineMAX_SCHEDULE_TIMEOUTLONG_MAX
// net/core/sock.c
void sock_init_data(struct socket *sock, struct sock *sk)
{
        ...

sk->sk_sndtimeo=MAX_SCHEDULE_TIMEOUT;
        ...

}
2、本地socket和网络socket的通信机制有些不同(比如,tcp状态机不通过报文交互实现,getsockopt不能取到tcp的连接状态,内核在处理本地socket时,可能不会有一些协议栈的过程,即可能忽略了报文的完整性检查),很多网络socket上使用的函数在迁移至本地socket时需要酌情考虑。

[server端代码]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
int ct_ipc_sock_create(struct ct_fd * sockfd, int server_flag)
{
    log_debug("server_flag: %d", server_flag);
    int ret = CT_RET_SUCCESS;
    int result = 0;
    struct sockaddr_un srv_addr;

    memset(&srv_addr, 0, sizeof(struct sockaddr_un));

    if (SERVER_SOCKET == server_flag)
    {
        sockfd->fd = socket(PF_UNIX, SOCK_DGRAM, 0);
        if (0 > sockfd->fd)
        {
            log_err("create Unix Socket error");
            ret = CT_RET_SYS_SOCK_CREATE_ERR;
            goto ct_ipc_sock_create_err;
        }

        srv_addr.sun_family=AF_UNIX;
        strncpy(srv_addr.sun_path, UNIX_DOMAIN, sizeof(srv_addr.sun_path)-1);   
        unlink(UNIX_DOMAIN);
         
        ret=bind(sockfd->fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));   
        if(ret==-1)
        {
            log_err("cannot bind server socket (%d)", sockfd->fd);        
            ret = CT_RET_SYS_SOCK_BIND_ERR;
            goto ct_ipc_sock_bind_listen_err;
        }
         
    }
    else if (CLIENT_SOCKET == server_flag)
    {
        sockfd->fd = socket(PF_UNIX, SOCK_STREAM, 0);
        if (0 > sockfd->fd)
        {
            log_err("create Unix Socket error");
            ret = CT_RET_SYS_SOCK_CREATE_ERR;
            goto ct_ipc_sock_create_err;
        }
        log_debug("sockfd: %d", sockfd->fd);
     
        setsockopt(sockfd->fd, SOL_SOCKET, TCP_NODELAY, &result, sizeof(int));

        srv_addr.sun_family=AF_UNIX;
        strncpy(srv_addr.sun_path, UNIX_DOMAIN_CLOUD, sizeof(srv_addr.sun_path)-1);   
        unlink(UNIX_DOMAIN_CLOUD);
        ret=bind(sockfd->fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
         
        if(ret==-1)
        {
            log_err("cannot bind server socket (%d)", sockfd->fd);        
            ret = CT_RET_SYS_SOCK_BIND_ERR;
            goto ct_ipc_sock_bind_listen_err;
        }
        log_debug("%s", strerror(errno));

        ret=listen(sockfd->fd, MAX_LISTEN_BACKLOG);   
        if(ret==-1)
        {      
            log_err("cannot listen the client connect request (%d)", sockfd);
            ret = CT_RET_SYS_SOCK_LISTEN_ERR;
            goto ct_ipc_sock_bind_listen_err;
        }
    }
    else
    {
    }
     
    log_debug("%s", strerror(errno));
     
    return ret;
     
ct_ipc_sock_bind_listen_err:
    close(sockfd->fd);
ct_ipc_sock_create_err:
    sockfd->fd = -1;
    return ret;
}
int ct_select_run()
{
    int ret = CT_RET_SUCCESS;
    fd_set  rset, allset;

    int nfds = 0;
    int maxfd = 0;
    int cloudfd = 0;
    int read_num = 0;
    int write_num = 0;
    socklen_t addrLen;
    struct sockaddr_in addr;
    char rsp[] = "ACK";
    char data_buf[MAX_BUF] = {0};

    log_debug("sockfd: %d, nlfd.fd: %d, cloud_sockfd.fd: %d", ipc_sockfd.fd, nlfd.fd, cloud_sockfd.fd);

    group_filter_init();
     
    maxfd = ipc_sockfd.fd ;
     
    FD_ZERO(&allset);
    FD_SET(cloud_sockfd.fd, &allset);
    log_debug("sockfd: %d, maxfd: %d, cloud_sockfd.fd: %d", ipc_sockfd.fd, maxfd, cloud_sockfd.fd);

    while (1/*nfds == 0*/)
    {
        rset = allset;
        log_debug("sockfd: %d", ipc_sockfd.fd);
        nfds = select(maxfd + 1, &rset, NULL, NULL, NULL);
        if (0 > nfds)
        {
            log_err("select error: %s", strerror(errno));
            ret = CT_RET_SYS_SOCK_SELECT_ERR;
            return ret;
        }

        if (FD_ISSET(cloud_sockfd.fd, &rset)) {
            log_debug("cloud_sockfd: %d", cloud_sockfd.fd);
            cloudfd = accept(cloud_sockfd.fd, (struct sockaddr *)&addr, &addrLen);

            if (cloudfd < 0) {
                 
                log_err("accept (%d) client error: %d", cloud_sockfd.fd, ret);
                continue;
            }
            
            read_num = read(cloudfd, data_buf, MAX_BUF);
            log_debug("client socket is: %d, read_num: %d", cloudfd, read_num);
            
            if (read_num > 0) {
                write_num = write(cloudfd, sta_info, (sizeof(sta_list_attr)*num + sizeof(int)));
                log_debug("client socket is: %d, write_num: %d", cloudfd, write_num);;
                }
            }

            close(cloudfd);
        }
    }

    return ret;
}




[client端代码]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
int do_filter_notify(cloud_cmd_attr * attr, char * buf, int buf_len)
{
    int ret = 0;
    int client_fd = -1;
    char recv_buf[128] = {0};
    struct sockaddr_un srv_addr;
    int maxfd = 0;
    int nfds = 0;
    fd_set  rset, allset;
    struct timeval tv;
    struct timeval t;
    /* Wait up to five seconds. */
    tv.tv_sec = CLI_TIME_OUT;
    tv.tv_usec = 0;
     
    memset(&srv_addr, 0, sizeof(struct sockaddr_un));

    client_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    log_debug("client_fd: %d\n", client_fd);
    printf("client_fd: %d\n", client_fd);
    if (-1 != client_fd)
    {
        t.tv_sec = UNIX_SOCK_CONNECT_TIMEO;
        t.tv_usec = 0;
        ret = setsockopt(client_fd, SOL_SOCKET, SO_SNDTIMEO, &t, sizeof(t));
        srv_addr.sun_family = AF_UNIX;
        memcpy(srv_addr.sun_path, UNIX_DOMAIN_CLOUD, strlen(UNIX_DOMAIN_CLOUD));
        log_debug("srv_addr.sun_path: %s\n", srv_addr.sun_path);
        printf("srv_addr.sun_path: %s\n", srv_addr.sun_path);
        ret = connect(client_fd, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
        if (-1 == ret)
        {
            log_err("error: %d, %s\n", errno, strerror(errno));
            ret = CT_RET_SYS_SOCK_CONNECT_ERR;
            goto close_fd;
        }
        else
        {
            int write_num = 0;
            write_num = write(client_fd, attr, sizeof(cloud_cmd_attr));
            if (sizeof(cloud_cmd_attr) == write_num)
            {
                FD_ZERO(&allset);   
                FD_SET(client_fd, &allset);
                maxfd = client_fd;
                rset = allset;
                nfds = select(maxfd + 1, &rset, NULL, NULL, &tv);
                log_debug("nfds: %d\n", nfds);
                printf("nfds: %d\n", nfds);
                if (FD_ISSET(client_fd, &rset))
                {
                    int num = 0;
                    if (NULL == buf)
                    {
                        num = read(client_fd, recv_buf, sizeof(recv_buf));
                    }
                    else
                    {
                        num = read(client_fd, buf, buf_len);
                    }
                    if (num <= 0)
                    {
                        log_err("read %d error", client_fd);
                        ret = CT_RET_FD_READ_ERR;
                    }
                    else
                    {
                        log_debug("client_fd: %d, read length: %d", client_fd, num);
                        printf("client_fd: %d, read length: %d", client_fd, num);
                        if (NULL == buf)
                        {
                            log_debug("recv_buf: %s\n", recv_buf);
                            if (!strcasecmp(recv_buf, "ack"))
                            {
                                ret = CT_RET_SUCCESS;
                            }
                        }
                        else
                        {
                            // do nothing
                        }
                    }
                    goto close_fd;
                }
                else
                {
                    log_err("no response from: %d", client_fd);
                    printf("no response from: %d", client_fd);
                    ret = CT_RET_SOCK_SELECT_TIMEOUT;
                    goto close_fd;
                }
            }
            else
            {
                log_err("(%d) write to peer %s error (num: %d)", client_fd, UNIX_DOMAIN_CLOUD, ret);
                printf("(%d) write to peer %s error (num: %d)", client_fd, UNIX_DOMAIN_CLOUD, ret);
                ret = CT_RET_FD_WRITE_ERR;
                goto close_fd;
            }   
        }
    }
    else
    {
        log_err("create Unix socket error");
        printf("create Unix socket error");
        ret = CT_RET_SYS_SOCK_CREATE_ERR;
    }

    return ret;
close_fd:
    close(client_fd);
    client_fd = -1;
    return ret;
}



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-30901-1-1.html 上篇帖子: cobbler安装配置 下篇帖子: 解决Linux下中文乱码问题 linux 通信
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表