命名UNIX域套接字通信

2024-06-02 00:58
文章标签 通信 命名 unix 接字 域套

本文主要是介绍命名UNIX域套接字通信,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《UNIX环境高级编程》中开发的三个函数 

#include "apue.h"
#include <sys/socket.h>
#include <sys/un.h>
#include <time.h>
#include <errno.h>#define	STALE	30	/* client's name can't be older than this (sec) */#define QLEN	10#define	CLI_PATH	"./"
#define	CLI_PERM	S_IRWXU			/* rwx for user only */
/** Wait for a client connection to arrive, and accept it.* We also obtain the client's user ID from the pathname* that it must bind before calling us.* Returns new fd if all OK, <0 on error*/
int
serv_accept(int listenfd, uid_t *uidptr)
{int					clifd, err, rval;socklen_t			len;time_t				staletime;struct sockaddr_un	un;struct stat			statbuf;char				*name;/* allocate enough space for longest name plus terminating null */if ((name = malloc(sizeof(un.sun_path + 1))) == NULL)return(-1);len = sizeof(un);if ((clifd = accept(listenfd, (struct sockaddr *)&un, &len)) < 0) {free(name);return(-2);		/* often errno=EINTR, if signal caught */}/* obtain the client's uid from its calling address */len -= offsetof(struct sockaddr_un, sun_path); /* len of pathname */memcpy(name, un.sun_path, len);name[len] = 0;			/* null terminate */if (stat(name, &statbuf) < 0) {rval = -3;goto errout;}#ifdef	S_ISSOCK	/* not defined for SVR4 */if (S_ISSOCK(statbuf.st_mode) == 0) {rval = -4;		/* not a socket */goto errout;}
#endifif ((statbuf.st_mode & (S_IRWXG | S_IRWXO)) ||(statbuf.st_mode & S_IRWXU) != S_IRWXU) {rval = -5;	/* is not rwx------ */goto errout;}staletime = time(NULL) - STALE;if (statbuf.st_atime < staletime ||statbuf.st_ctime < staletime ||statbuf.st_mtime < staletime) {rval = -6;	/* i-node is too old */goto errout;}if (uidptr != NULL)*uidptr = statbuf.st_uid;	/* return uid of caller */unlink(name);		/* we're done with pathname now */free(name);return(clifd);errout:err = errno;close(clifd);free(name);errno = err;return(rval);
}/** Create a server endpoint of a connection.* Returns fd if all OK, <0 on error.*/
int
serv_listen(const char *name)
{int					fd, len, err, rval;struct sockaddr_un	un;if (strlen(name) >= sizeof(un.sun_path)) {errno = ENAMETOOLONG;return(-1);}/* create a UNIX domain stream socket */if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)return(-2);unlink(name);	/* in case it already exists *//* fill in socket address structure */memset(&un, 0, sizeof(un));un.sun_family = AF_UNIX;strcpy(un.sun_path, name);len = offsetof(struct sockaddr_un, sun_path) + strlen(name);/* bind the name to the descriptor */if (bind(fd, (struct sockaddr *)&un, len) < 0) {rval = -3;goto errout;}if (listen(fd, QLEN) < 0) {	/* tell kernel we're a server */rval = -4;goto errout;}return(fd);errout:err = errno;close(fd);errno = err;return(rval);
}/** Create a client endpoint and connect to a server.* Returns fd if all OK, <0 on error.*/
int
cli_conn(const char *name)
{int					fd, len, err, rval;struct sockaddr_un	un, sun;int					do_unlink = 0;if (strlen(name) >= sizeof(un.sun_path)) {errno = ENAMETOOLONG;return(-1);}/* create a UNIX domain stream socket */if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)return(-1);/* fill socket address structure with our address */memset(&un, 0, sizeof(un));un.sun_family = AF_UNIX;sprintf(un.sun_path, "%s%05ld", CLI_PATH, (long)getpid());
printf("file is %s\n", un.sun_path);len = offsetof(struct sockaddr_un, sun_path) + strlen(un.sun_path);unlink(un.sun_path);		/* in case it already exists */if (bind(fd, (struct sockaddr *)&un, len) < 0) {rval = -2;goto errout;}if (chmod(un.sun_path, CLI_PERM) < 0) {rval = -3;do_unlink = 1;goto errout;}/* fill socket address structure with server's address */memset(&sun, 0, sizeof(sun));sun.sun_family = AF_UNIX;strcpy(sun.sun_path, name);len = offsetof(struct sockaddr_un, sun_path) + strlen(name);if (connect(fd, (struct sockaddr *)&sun, len) < 0) {rval = -4;do_unlink = 1;goto errout;}return(fd);errout:err = errno;close(fd);if (do_unlink)unlink(un.sun_path);errno = err;return(rval);
}

客户端:

#include "apue.h"
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/un.h>
//#include<netinet/in.h>
#define UNIXSOCKETNAME "test_socket"
#define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \} while(0)
void echo_cli(int sock)
{char buf1[1024] = {0};char buf2[1024] = {0};int ret = 0;while(fgets(buf1, sizeof(buf1), stdin) != NULL){write(sock, buf1, strlen(buf1));ret = read(sock, buf2, sizeof(buf2));if(ret == 0){printf("server %d close\n", sock);break;}printf("%s", buf2);memset(buf1, 0, sizeof(buf1));memset(buf2, 0, sizeof(buf2));}close(sock);
}
int main()
{int sock = cli_conn(UNIXSOCKETNAME);if(sock < 0)ERR_EXIT("socket");echo_cli(sock);return 0;
}

服务器端:

#include "apue.h"
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/un.h>
#define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \} while(0)
#define UNIXSOCKETNAME "./test_socket"
void echo_cli(int sock)
{char buf[1024] = {0};int ret = 0;while(1){ret = read(sock, buf, sizeof(buf));if(ret == 0){printf("client %d close\n", sock);break;}printf("server receive %s \n", buf);write(sock, buf, strlen(buf));memset(buf, 0, sizeof(buf));}close(sock);
}
int main()
{int listenfd = serv_listen(UNIXSOCKETNAME);if(listenfd < 0)ERR_EXIT("socket");//unlink(UNIXSOCKETNAME);uid_t uidclient; int conn;pid_t pid;while(1){printf("server waiting ...\n");conn = serv_accept(listenfd, &uidclient);	if(conn == -1){if(errno == EINTR)continue;ERR_EXIT("accept");}printf("Has new client connected, conn = %d\n", conn);pid = fork();if(pid < 0)ERR_EXIT("fork");else if(pid == 0){            echo_cli(conn);exit(1);}elseclose(conn);}return 0;
}

 

这篇关于命名UNIX域套接字通信的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1022596

相关文章

RabbitMQ工作模式中的RPC通信模式详解

《RabbitMQ工作模式中的RPC通信模式详解》在RabbitMQ中,RPC模式通过消息队列实现远程调用功能,这篇文章给大家介绍RabbitMQ工作模式之RPC通信模式,感兴趣的朋友一起看看吧... 目录RPC通信模式概述工作流程代码案例引入依赖常量类编写客户端代码编写服务端代码RPC通信模式概述在R

在Spring Boot中实现HTTPS加密通信及常见问题排查

《在SpringBoot中实现HTTPS加密通信及常见问题排查》HTTPS是HTTP的安全版本,通过SSL/TLS协议为通讯提供加密、身份验证和数据完整性保护,下面通过本文给大家介绍在SpringB... 目录一、HTTPS核心原理1.加密流程概述2.加密技术组合二、证书体系详解1、证书类型对比2. 证书获

Python模拟串口通信的示例详解

《Python模拟串口通信的示例详解》pySerial是Python中用于操作串口的第三方模块,它支持Windows、Linux、OSX、BSD等多个平台,下面我们就来看看Python如何使用pySe... 目录1.win 下载虚www.chinasem.cn拟串口2、确定串口号3、配置串口4、串口通信示例5

基于C#实现MQTT通信实战

《基于C#实现MQTT通信实战》MQTT消息队列遥测传输,在物联网领域应用的很广泛,它是基于Publish/Subscribe模式,具有简单易用,支持QoS,传输效率高的特点,下面我们就来看看C#实现... 目录1、连接主机2、订阅消息3、发布消息MQTT(Message Queueing Telemetr

浅谈Redis Key 命名规范文档

《浅谈RedisKey命名规范文档》本文介绍了Redis键名命名规范,包括命名格式、具体规范、数据类型扩展命名、时间敏感型键名、规范总结以及实际应用示例,感兴趣的可以了解一下... 目录1. 命名格式格式模板:示例:2. 具体规范2.1 小写命名2.2 使用冒号分隔层级2.3 标识符命名3. 数据类型扩展命

Java中的工具类命名方法

《Java中的工具类命名方法》:本文主要介绍Java中的工具类究竟如何命名,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java中的工具类究竟如何命名?先来几个例子几种命名方式的比较到底如何命名 ?总结Java中的工具类究竟如何命名?先来几个例子JD

Pytorch微调BERT实现命名实体识别

《Pytorch微调BERT实现命名实体识别》命名实体识别(NER)是自然语言处理(NLP)中的一项关键任务,它涉及识别和分类文本中的关键实体,BERT是一种强大的语言表示模型,在各种NLP任务中显著... 目录环境准备加载预训练BERT模型准备数据集标记与对齐微调 BERT最后总结环境准备在继续之前,确

Linux命名管道方式

《Linux命名管道方式》:本文主要介绍Linux命名管道方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、命名管道1、与匿名管道的关系2、工作原理3、系统调用接口4、实现两个进程间通信二、可变参数列表总结一、命名管道1、与匿名管道的关系命名管道由mkf

通过Python脚本批量复制并规范命名视频文件

《通过Python脚本批量复制并规范命名视频文件》本文介绍了如何通过Python脚本批量复制并规范命名视频文件,实现自动补齐数字编号、保留原始文件、智能识别有效文件等功能,听过代码示例介绍的非常详细,... 目录一、问题场景:杂乱的视频文件名二、完整解决方案三、关键技术解析1. 智能路径处理2. 精准文件名

linux如何复制文件夹并重命名

《linux如何复制文件夹并重命名》在Linux系统中,复制文件夹并重命名可以通过使用“cp”和“mv”命令来实现,使用“cp-r”命令可以递归复制整个文件夹及其子文件夹和文件,而使用“mv”命令可以... 目录linux复制文件夹并重命名我们需要使用“cp”命令来复制文件夹我们还可以结合使用“mv”命令总