ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Pxxx-本地套接字通信

2021-04-01 23:33:20  阅读:217  来源: 互联网

标签:sockaddr struct buf sun 本地 接字 include Pxxx servaddr


进程间通信

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有