【Linux学习笔记62】UNIX域套接字

引言

在之前的笔记写的socket笔记,是通信方式中的一种扩展,前面笔记的socket都使用地址IP实现通信。实际上,socket可以使用在不需要IP的场合,即本地通信。(与进程间的通信(一)(匿名管道与有名管道)一样)
UNIX域套接字相比于前面的管道等提供的信息更多,比如:UNIX域可以等待对端的连接(与TCP类似),又可以实现帧同步(UDP类似)

本地域套接字的使用

字节流本地域套接字(不提供帧同步)
  1. 创建本地域套接字
    在这里插入图片描述
  2. 定义本地域套接字结构体,并且绑定地址(有效路径)
    在这里插入图片描述
  3. 等待连接(后面与TCP类似)
代码实现:

server.c:

#include <stdio.h>
#include "head4sock.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

#define LISTENQ 5
#define SIZE 100

int main(int argc, char **argv)
{
	if(argc != 2)
	{
		fprintf(stderr,"Usage:%s <path>\n",argv[0]);
		exit(1);
	}

	// 创建一个字节流本地域套接字(不提供帧同步) UNIX域套接字
	int fd;
	fd = Socket(AF_UNIX, SOCK_STREAM, 0);

 //定义本地域套接字地址结构体
	struct sockaddr_un local_address;
	bzero(&local_address, sizeof local_address);

	local_address.sun_family = AF_LOCAL;
	memcpy(local_address.sun_path, argv[1], strlen(argv[1]));
	//传进有效路径,在该路径上创建本地域套接字文件

	// 绑定地址
	Bind(fd,(struct sockaddr *)&local_address, sizeof(local_address));

	Listen(fd, LISTENQ);

	int connfd;
	struct sockaddr_un peer_address;

	socklen_t len = sizeof(peer_address);
	bzero(&peer_address, len);
	connfd = Accept(fd,(struct sockaddr *)&peer_address,&len);

	printf("new connection %d from %s.\n", connfd, peer_address.sun_path);

	char buf[SIZE];
	while(1)
	{

		bzero(buf, SIZE);
		if(read(connfd, buf, SIZE) == 0)
			break;

		printf("from peer: %s", buf);
	}
	close(fd);
	close(connfd);

	exit(0);
}

client.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

#include "head4sock.h"

#define BUFFER_SIZE 1024

int main(int argc,char **argv)
{
	if(argc != 2)
	{
		fprintf(stderr,"Usage:%s <path>\n",argv[0]);
		exit(1);
	}

	int fd;
	fd = Socket(AF_LOCAL,SOCK_STREAM,0);

	struct sockaddr_un remote_address;
	bzero(&remote_address, sizeof remote_address);
	remote_address.sun_family = AF_LOCAL;
	memcpy(remote_address.sun_path,argv[1],strlen(argv[1]));
	
	Connect(fd,(struct sockaddr *)&remote_address,sizeof(remote_address));

	char buffer[BUFFER_SIZE];
	while(1)
	{
		bzero(buffer, BUFFER_SIZE);
		if(fgets(buffer, BUFFER_SIZE, stdin) == NULL)
			break;

		write(fd, buffer, strlen(buffer));
	}

	close(fd);
	exit(0);
}

代码运行结果:

在这里插入图片描述

数据报本地域套接字(提供帧同步)
  1. 创建一个数据报本地域套接字
    在这里插入图片描述
  2. 定义本地域套接字结构体,并且绑定地址(有效路径)
  3. 等待连接(与上类似)
代码实现:

server.c:

//:server.c
#include <stdio.h>
#include "head4sock.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

#define LISTENQ 5
#define SIZE 100

int main(int argc, char **argv)
{
	if(argc != 2)
	{
		fprintf(stderr,"Usage:%s <path>\n",argv[0]);
		exit(1);
	}

	// 创建一个数据报本地域套接字(提供了帧同步)
	int fd;
	fd = Socket(AF_LOCAL, SOCK_DGRAM, 0);

	struct sockaddr_un local_address;
	bzero(&local_address, sizeof local_address);

	local_address.sun_family = AF_LOCAL;
	memcpy(local_address.sun_path, argv[1], strlen(argv[1]));
	
	Bind(fd,(struct sockaddr *)&local_address,sizeof(local_address)); 

	struct sockaddr_un peer_address;
	socklen_t len = sizeof(peer_address);
	bzero(&peer_address, len);

	char buf[SIZE];
	while(1)
	{
		bzero(buf, SIZE);
		if(recvfrom(fd, buf, SIZE, 0, NULL, NULL) == 0)
			break;

		printf("from peer: %s", buf);
	}
	close(fd);

	exit(0);
}

client.c :

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

#include "head4sock.h"

#define BUFFER_SIZE 1024

int main(int argc,char **argv)
{
	if(argc != 2)
	{
		fprintf(stderr,"Usage:%s <path>\n",argv[0]);
		exit(1);
	}

	int fd;
	fd = Socket(AF_LOCAL,SOCK_DGRAM, 0);

	struct sockaddr_un remote_address;
	socklen_t len = sizeof(remote_address);
	bzero(&remote_address, len);
	remote_address.sun_family = AF_LOCAL;
	memcpy(remote_address.sun_path,argv[1],strlen(argv[1]));
	
	char buffer[BUFFER_SIZE];
	while(1)
	{
		bzero(buffer, BUFFER_SIZE);
		if(fgets(buffer, BUFFER_SIZE, stdin) == NULL)
			break;

		sendto(fd, buffer, strlen(buffer), 0,
					(struct sockaddr *)&remote_address, len);
	}

	close(fd);
	exit(0);
}

代码运行结果:

在这里插入图片描述

总结多种进程通信使用频率:

  1. 共享内存,信号量:效率高
  2. 本地域套接字:提供类似TCP的连接服务,可以控制缓冲区大小,灵活性大
  3. 管道:效率低
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值