ndk学习16:unixdomainsocket
⼀、UNIX Domain Socket
概念:
UNIX Domain Socket是在socket架构上发展起来的⽤于同⼀台主机的进程间通讯(IPC)
特点:
1. 它不需要经过⽹络协议栈,不需要打包拆包、计算校验和、维护序号和应答等
2. 只是将应⽤层数据从⼀个进程拷贝到另⼀个进程。
⼯作模式:
SOCK_DGRAM 类似于UDP
SOCK_STREAM 类似于TCP
⽤途:
UNIX Domain Socket可⽤于两个没有亲缘关系的进程,是全双⼯的,是⽬前使⽤最⼴泛的IPC机制
⽐如X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的
⼆、⼯作流程
与⽹络socket的不同点:
1. address family为AF_UNIX
2. unix domain socket不需要IP和端⼝,取⽽代之的是⽂件路径来表⽰“⽹络地址”
原理:
UNIXDomain socket⽤结构体sockaddr_un表⽰,是⼀个socket类型的⽂件在⽂件系统中的路径
这个socket⽂件由bind()调⽤创建,如果调⽤bind()时该⽂件已存在,则bind()错误返回
UNIX Domain Socket客户端⼀般要显式调⽤bind函数,⽽不象⽹络socket⼀样依赖系统⾃动分配的地址。
客户端bind的socket⽂件名可以包含客户端的pid,这样服务器就可以区分不同的客户端
⼯作流程:
服务器端:创建socket—绑定⽂件(端⼝)—监听—接受客户端连接—接收/发送数据—…—关闭
客户端:创建socket—绑定⽂件(端⼝)—连接—发送/接收数据—…—关闭
三、阻塞和⾮阻塞(SOCK_STREAM⽅式)
读写操作有两种操作⽅式:阻塞和⾮阻塞
1.阻塞模式下
阻塞模式下,发送数据⽅和接收数据⽅的表现情况如同命名管道
2.⾮阻塞模式
在send或recv函数的标志参数中设置MSG_DONTWAIT,则发送和接收都会返回。如果没有成功,则返回值为-1,errno为EAGAIN 或EWOULDBLOCK
四.实例
服务端代码:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#define UNIX_DOMAIN "/data/local/tmp/ndk_cmd"
int main(void) {
int listen_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (listen_fd < 0) {
perror("cannot create communication socket\n");
return 1;
}
//set server addr_param
struct sockaddr_un srv_addr;
srv_addr.sun_family = AF_UNIX;
strncpy(srv_addr.sun_path, UNIX_DOMAIN, sizeof(srv_addr.sun_path) - 1); unlink (UNIX_DOMAIN);
//bind sockfd & addr
int ret = bind(listen_fd, (struct sockaddr*) &srv_addr, sizeof(srv_addr));
if (ret == -1) {
perror("cannot bind server socket");
close(listen_fd);
unlink(UNIX_DOMAIN);
return 1;
}
//listen sockfd
ret = listen(listen_fd, 1);
if (ret == -1) {
perror("cannot listen the client connect request");
close(listen_fd);
unlink(UNIX_DOMAIN);
return 1;
}
unix文件系统//have connect request use accept
struct sockaddr_un clt_addr;
int len = sizeof(clt_addr);
int com_fd = accept(listen_fd, (struct sockaddr*) &clt_addr, &len);
if (com_fd < 0) {
perror("cannot accept client connect request");
close(listen_fd);
unlink(UNIX_DOMAIN);
return 1;
}
//read and printf sent client info
printf("/n=====info=====/n");
static char recv_buf[1024];
for (int i = 0; i < 4; i++) {
memset(recv_buf, 0, 1024);
int num = read(com_fd, recv_buf, sizeof(recv_buf));
printf("Message from client (%d)) :%s\n", num, recv_buf);
}
close(com_fd);
close(listen_fd);
unlink(UNIX_DOMAIN);
return 0;
}
客户端代码:
#include <stdio.h>
#include <stddef.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
int main(void) {
//creat unix socket
int connect_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (connect_fd < 0) {
perror("cannot create communication socket");
return 1;
}
static struct sockaddr_un srv_addr;
srv_addr.sun_family = AF_UNIX;
strcpy(srv_addr.sun_path, "/data/local/tmp/ndk_cmd");
//connect server
int ret = connect(connect_fd, (struct sockaddr*) &srv_addr, sizeof(srv_addr)); if (ret == -1) {
perror("cannot connect to the server");
close(connect_fd);
return 1;
}
char snd_buf[1024];
memset(snd_buf, 0, 1024);
strcpy(snd_buf, "message from client");
//send info server
for (int i = 0; i < 4; i++)
write(connect_fd, snd_buf, sizeof(snd_buf)); close(connect_fd);
return 0;
}
运⾏结果:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论