其他分享
首页 > 其他分享> > Pxxx-本地套接字通信

Pxxx-本地套接字通信

作者:互联网

进程间通信

PIPE FIFO     实现简单 

mmap            非血缘关系进程间

信号               开销小

domain          稳定性最好

本地套接字

1、文件格式:pipe 、fifo

2、本地套接字s-->伪文件

3、服务端流程

创建套接字:lfd = socket(AF_UNIX, SOCK_STREAM,0)

绑定:

struct sockaddr_un serv;

serv.sun_famliy = AF_UNIX;

strcpy(serv.sun_path, "server.socket");现在还未创建

bind(lfd, (struct sockaddr*)&serv, len);  绑定成功则创建server.socket文件

设置监听

listen()

等待接收连接请求

struct sockaddt_un client;

int cfd = accept(lfd, &client, &len);

通信

send()

recv()

断开连接

close()

4、客户端流程

①创建套接字:fd = socket(AF_UNIX, SOCK_STREAM,0)

②绑定:

struct sockaddr_un client;

serv.sun_famliy = AF_UNIX;

strcpy(serv.sun_path, "client.socket");现在还未创建

bind(lfd, (struct sockaddr*)&client, len);  绑定成功则创建client.socket文件

③连接服务器

struct sockaddr_un serv;

serv.sun_family=AF_UNIX;

strcpy(serv.sun_path, "server.socket");现在还未创建

connect(fd, &serv, sizeof(server));

④通信

recv

send

⑤关闭

close

 

本地套接字和网络套接字

头文件:sys/un.h

#define UNIX_PATH_MAX 128

struct sockaddr_un{

__kernel_sa_family_t sun_famliy;

char sun_pathname[UNIX_PATH_MAX]; 

};

服务编程流程:

①创建套接字 int lfd = sockfd(AF_UNIX, SOCK_STREAM, 0);

②绑定:

struct sockaddr_un server;

server.sun_family = AF_LOCAL;

strcpy(server.sun_path, "/tmp/server.socket");

bind(lfd, (struct sockaddr)&server, len);

③设置监听

listen()

④等待接收请求

int cfd=accetp(lfd, &client, &len);

UNIX Domain Socket的特点

1.UNIX Domain Socket为什么比TCP/IP在本地上通信更加快
因为UNIX Domain Socket不经过网络协议栈 / 不需要打包拆包 / 计算校验和 / 维护序号和应答,只是将应用层数据从一个进程拷贝到另一个进程
2.UNIX Domain Socket也提供面向流和面向数据包的两种API接口,类似于TCP和UDP,但是面向消息的 UNIX Domain Socket也是可靠的,消息既不会丢失也不会失序。
3.全双工
4.目前UNIX Domain Socket已经成为最广泛的IPC机制

4.常用API

1)用于创建类似于无名管道(pipe)的本地套接字

int socketpair(int domain, int type, int protocol, int sv[2]);

2)当不再需要这个 Unix 域套接字时,应删除路径名对应的文件

int unlink(const char *pathname);
int remove(const char *pathname);
注意,如果是抽象路径名,就不需要在使用完本地套接字后手动删除对应的套接字文件,因为当本地套接字被关闭之后,内核会自动删除这个抽象名。 

3)获取本地套接字的地址信息

int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

 

 

客户端3.c

客户端3.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <stddef.h>

int main(void)
{
	int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
	
	struct sockaddr_un client;
	client.sun_family = AF_LOCAL;	
	strcpy(client.sun_path, "client.sock");
	
	bind(fd, (struct sockaddr *)&client, sizeof(client));
	
	//初始化server信息
	struct sockaddr_un serv;
	serv.sun_family = AF_LOCAL;
	strcpy(serv.sun_path, "serv.sock");
	
	//连接服务器
	connect(fd, (struct sockaddr*)&serv, sizeof(serv));
	
	while(1)
	{
		char buf[1024]={0};
		fgets(buf, sizeof(buf), stdin);
		send(fd, buf, strlen(buf)+1, 0);
		
		recv(fd, buf, sizeof(buf), 0);
		printf("recv buff:%s\n", buf);
	}
	close(fd)
	
	return 0;
}

服务段3.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <stddef.h>

int main(void)
{
	//创建
	int lfd = socket(AF_UNIX, SOCK_STREAM, 0);
	
	//绑定
	struct sockaddr_un serv;
	serv.sun_family = AF_UNIX;
	strcpy(serv.sun_path, "socket.server");
	bind(lfd, (struct sockaddr*)&serv, sizeof(serv));
	
	//监听
	listen(lfd, 36);
	
	//等待连接请求
	struct sockaddr_un client;
	socklen_t len = sizeof(client);
	int cfd = accept(lfd, (struct sockaddr*)&client, &len);
	
	//通信
	while(1)
	{
		char buf[1024] = {0};
		int recvlen = recv(cfd, buf, sizeof(buf), 0);
		send(cfd, buf, recvlen, 0);
	}
	close(cfd);
	close(lfd);
	
	return 0;
}

 

TCP(字节流套接字)

【unixstr_cli.c】

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

#define UNIXSTR_PATH "/tmp/unix.str"
#define LISTENQ 5
#define BUFFER_SIZE 256

int main(void)
{
    int sockfd;
    struct sockaddr_un servaddr;

    sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sun_family = AF_LOCAL;
    strcpy(servaddr.sun_path, UNIXSTR_PATH);

    connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

    char buf[BUFFER_SIZE];

    while(1)
    {
        bzero(buf, sizeof(BUFFER_SIZE));
        printf(">> ");
        if(fgets(buf, BUFFER_SIZE, stdin) == NULL)
        {
            break;
        }
        write(sockfd, buf, strlen(buf));
    }

    close(sockfd);

    return 0;
}

【unixstr_serv.c】

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

#define UNIXSTR_PATH "/tmp/unix.str"
#define LISTENQ 5
#define BUFFER_SIZE 256

int main(void)
{
    int listenfd, connfd;
    socklen_t len;
    struct sockaddr_un servaddr, cliaddr;

    if(-1 == (listenfd = socket(AF_LOCAL, SOCK_STREAM, 0)))
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    unlink(UNIXSTR_PATH);

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sun_family = AF_LOCAL;
    strcpy(servaddr.sun_path, UNIXSTR_PATH);
    if(-1 == bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))
    {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    listen(listenfd, LISTENQ);

    len = sizeof(cliaddr);

    if(-1 == (connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &len)))
    {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    char buf[BUFFER_SIZE];

    while(1)
    {
        bzero(buf, sizeof(buf));
        if(read(connfd, buf, BUFFER_SIZE) == 0) break;
        printf("Receive: %s", buf);
    }

    close(listenfd);
    close(connfd);
    unlink(UNIXSTR_PATH);

    return 0;
}

服务器2.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <stddef.h>

#define SERV_ADDR "serv.socket"
#define offsetof(type, member) ((int)&((type *)0)->MEMBER)

int main(void)
{
	int lfd, cfd, len, size, i;
	struct sockaddr_un, servaddr, clieaddr;
	char buff[4096];
	
	lfd = socket(AF_UNIX, SOCK_STREAM, 0);
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sun_family = AF_UNIX;
	strcpy(servaddr.sun_path, SERV_ADDR);
	
	/*计算成员sun_path在结构体中sockaddr_un中的偏移量*/
	len=offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);
	
	unlink(SERV_ADDR);
	bind(lfd, (struct sockaddr *)&servaddr, len);
	
	listen(lfd, 20);
	
	printf("Accept ...\n");
	
	while(1)
	{
		len=sizeof(cliaddr);
		cfd=accept(lfd, (struct sockaddr*)&cliaddr, (socklen_t *)&len);
		len -=offsetof(struct sockaddr_un, sun_path);
		cliaddr.sun_path[len]='\0';
		
		printf("client bind filename %s\n", cliaddr.sun_path);
	
		while((size = read(cfd, buf, sizeof(buf))) > 0)
		{
			for(i =0; i<size; i++)
				buf[i]=toupper(buf[i]);
			write(cfd, buf, size);
		}
		close(cfd);
	}
	close(lfd);
		
	return 0;
}

客户端2.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/inet.h>
#include <stddef.h>


#define SERV_ADDR "serv.socket"
#define CLIE_ADDR "clie.socket"

int main(void)
{
	int cfd, len;
	struct sockaddr_un servaddr,cliaddr;
	char buf[4096];

	cfd=socket(AF_UNIX, SOCK_STREAM, 0);
	
	bzero(&cliaddr, sizeof(cliaddr));
	cliaddr.sun_family = AF_UNIX;
	strcpy(cliaddr.sun_path, CLIE_ADDR);

/*本地套接字为什么需要绑定??不需要吧*/
	len = offsetof(struct sockaddr_un, sun_path) + strlen(cliaddr.sun_path);
	
	unlink(CLIE_ADDR);
	bind(cfd, (struct sockaddr *)&cliaddr, len);
	
	
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sun_family=AF_UNIX;
	strcpy(servaddr.sun_path, SERV_ADDR);
	
	len=offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);
	
	connet(cfd, (struct sockaddr *)&servaddr, len);
	
	while(fgets(buf, sizeof(buf), stdin) != NULL)
	{
		write(cfd, buf, strlen(buf));
		len = read(cfd, buf, sizeof(buf));
		write(STDOUT_FILENO, buf, len);
	}
	
	close(cfd);
	return 0;
}

 

 

 

标签:sockaddr,struct,buf,sun,本地,接字,include,Pxxx,servaddr
来源: https://blog.csdn.net/LuckyDog0623/article/details/115279043