linux處理序間通訊--本地socket(tcp部分)

來源:互聯網
上載者:User

標籤:linux   tcp   處理序間通訊   本地socket   

[核心版本]

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端代碼]

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端代碼]

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;}


linux處理序間通訊--本地socket(tcp部分)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.