加入收藏 | 设为首页 | 会员中心 | 我要投稿 南京站长网 (https://www.025zz.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Unix > 正文

UNIX域套接字(UDS) 原理及应用

发布时间:2022-11-06 15:00:49 所属栏目:Unix 来源:未知
导读: UNIX域套接字(UDS):UNIX Domain Socket
UNIX域socket实现本地进程间通信,需要一个进程作为服务器端,一个进程作为客户端,使用方法有点像socket网络,但又不经过网络底层的那些东西。与网

UNIX域套接字(UDS):UNIX Domain Socket

UNIX域socket实现本地进程间通信,需要一个进程作为服务器端,一个进程作为客户端,使用方法有点像socket网络,但又不经过网络底层的那些东西。与网络编程最不一样的地方是服务器端bind的时候用的是sockaddr_un结构,客户端connect的时候用的也是sockaddr_un结构,而不是sockaddr_in或sockaddr。而对于sockaddr_un结构,重点是给它提供一个bind()函数生成的socket类型文件的路径,即sockaddr_un.sun_path的值。并且客户端与服务器端的这个sockaddr_un结构的sun_path是一致的,通常这个路径是众所众知的,就像百度的域名那样。

经过bind,listen,accept,和connect后,两进程就通过读写socket文件描述符来通信,具体是服务器端读写accept返回的socket文件描述符,客户端读写经过connect处理后的文件描述符。

使用流程分析:

一、服务器端通信过程分析

服务器端基本遵循面向连接的socket数据流通信过程。

1、调用socket()函数,建立socket对象,指定通信协议为AF_UNIX。

2、调用bind()函数,将创建的socket对象与bind()函数产生的那个socket类型的文件server_socket P绑定。

UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,其地址用结构体sockaddr_un表示, 网络编程的socket地址是IP地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存在unix进程通信,且已被link,则bind()错误返回。一个套接字只能绑定到一个路径上,同样的,一个路径也只能被一个套接字绑定。

sockaddr_un结构的sun_path成员包含一路径名,当我们将一地址绑定至UNIX域套接字时,系统用该路径名创建一类型为S_IFSOCK的文件。该文件仅用于向客户端进程告知套接字名字,该文件不能打开,也不能由应用程序用于通信,当关闭套接字时,并不自动删除该文件,所以我们必须确保在应用程序终止前,对该文件执行解除链接操作(unlink(path)),或删除该文件。

struct sockaddr_un结构有两个参数:sun_family、sun_path。sun_family只能是AF_LOCAL或AF_UNIX;而sun_path就是本地文件的路径。

3、调用listen()函数,使socket对象处于监听状态,并设置监听队列大小。

4、服务器端监听到该请求,在客户端发出请求后,accept()函数接收请求,返回新文件描述符,从而建立连接。

5、服务器端调用read()函数接收数据(开始处于阻塞状态,等待客户端发送数据,因此,客户端在编程是需要首先发送数据,接收到数据后,输出接收到的数据)。

6、调用write()函数发送数据到客户端。

7、通信完成后,调用close()函数关闭socket对象;unlink(sockaddr_un.sun_path)。

二、客户端通信过程分析

客户端基本遵循面向连接的socket数据流通信过程。

1、调用socket()函数,建立socket对象,指定相同通信协议。

2、客户端调用connect()函数,向服务器端发起连接请求。

3、在得到服务器端允许后,首先调用write()函数向服务器端发送消息(因服务器端循环体中首先是接收数据)。

4、调用read()函数接收数据。

5、通信完成后,调用close()函数关闭socket对象。

具体使用例子:

这一例子实现一端发送字符,一端发送字符串。

服务器端源码:

socket_local_server.c:

#include

#include

#include

#include

#include

#include

int main(int argc,char *argv[])

{

int server_sockfd, client_sockfd;

int server_len, client_len;

struct sockaddr_un server_address;

struct sockaddr_un client_address;

int i,byte;

char ch_send,recv_buf[128];

unlink("server_socket");//解除原有server_socket对象链接

server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);//创建socket,指定通信协议为AF_UNIX,数据方式SOCK_STREAM

//配置server_address

server_address.sun_family = AF_UNIX;

strcpy(server_address.sun_path, "server_socket");

server_len = sizeof(server_address);

bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

listen(server_sockfd, 5);

printf("server waiting for client connect\n");

client_len = sizeof(client_address);

//accept函数接收客户端求情,存储客户端地址信息、客户端地址大小

client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_address, (socklen_t *)&client_len);

printf("the server wait form client data\n");

for(i=0,ch_send='1';i

{

//从client_sockfd读取客户端发来的消息

if((byte=read(client_sockfd, recv_buf, sizeof(recv_buf)))==-1)

{

perror("read");

exit(EXIT_FAILURE);

}

printf("the massage receiver from client is: %s\n",recv_buf);

sleep(1);

//向客户端发送消息

if((byte=write(client_sockfd,&ch_send,1))==-1)

{

perror("write");

exit(EXIT_FAILURE);

}

}

close(client_sockfd);

unlink("server socket");

}

客户端源码:

socket_local_client.c:

#include

#include

#include

#include

#include

#include

int main(int argc,char *argv[])

{

int sockfd;

int len;

struct sockaddr_un address;

int result;

int i,byte;

char send_buf[128],ch_recv;

if((sockfd = socket(AF_UNIX, SOCK_STREAM, 0))==-1)//创建socket,指定通信协议为AF_UNIX,数据方式SOCK_STREAM

{

perror("socket");

exit(EXIT_FAILURE);

}

//配置server_address

address.sun_family = AF_UNIX;

strcpy(address.sun_path, "server_socket");

len = sizeof(address);

result = connect(sockfd, (struct sockaddr *)&address, len);

if(result == -1)

{

printf("ensure the server is up\n");

perror("connect");

exit(EXIT_FAILURE);

}

for(i=0;i

{

sprintf(send_buf,"client massage %d",i);//用sprintf事先把消息写到send_buf

if((byte=write(sockfd, send_buf, sizeof(send_buf)))==-1)

{

perror("write");

exit(EXIT_FAILURE);

}

if((byte=read(sockfd,&ch_recv,1))==-1)

{

perror("read");

exit(EXIT_FAILURE);

}

printf("receive from server data is: %c\n",ch_recv);

}

close(sockfd);

return 0;

}

运行结果:

服务器端:

book@book-desktop:~/workspace/zongde/chapter17$ ./socket_local_server

server waiting for client connect

the server wait form client data

the massage receiver from client is: client massage 0

the massage receiver from client is: client massage 1

the massage receiver from client is: client massage 2

the massage receiver from client is: client massage 3

the massage receiver from client is: client massage 4

book@book-desktop:~/workspace/zongde/chapter17$

客户端:

book@book-desktop:~/workspace/zongde/chapter17$ ./socket_local_client

receive from server data is: 1

receive from server data is: 2

receive from server data is: 3

receive from server data is: 4

receive from server data is: 5

book@book-desktop:~/workspace/zongde/chapter17$

(编辑:南京站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章