命名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

相关文章

变量与命名

引言         在前两个课时中,我们已经了解了 Python 程序的基本结构,学习了如何正确地使用缩进来组织代码,并且知道了注释的重要性。现在我们将进一步深入到 Python 编程的核心——变量与命名。变量是我们存储数据的主要方式,而合理的命名则有助于提高代码的可读性和可维护性。 变量的概念与使用         在 Python 中,变量是一种用来存储数据值的标识符。创建变量很简单,

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

vue2 组件通信

props + emits props:用于接收父组件传递给子组件的数据。可以定义期望从父组件接收的数据结构和类型。‘子组件不可更改该数据’emits:用于定义组件可以向父组件发出的事件。这允许父组件监听子组件的事件并作出响应。(比如数据更新) props检查属性 属性名类型描述默认值typeFunction指定 prop 应该是什么类型,如 String, Number, Boolean,

linux中使用rust语言在不同进程之间通信

第一种:使用mmap映射相同文件 fn main() {let pid = std::process::id();println!(

列举你能想到的UNIX信号,并说明信号用途

信号是一种软中断,是一种处理异步事件的方法。一般来说,操作系统都支持许多信号。尤其是UNIX,比较重要应用程序一般都会处理信号。 UNIX定义了许多信号,比如SIGINT表示中断字符信号,也就是Ctrl+C的信号,SIGBUS表示硬件故障的信号;SIGCHLD表示子进程状态改变信号;SIGKILL表示终止程序运行的信号,等等。信号量编程是UNIX下非常重要的一种技术。 Unix信号量也可以

C++编程:ZeroMQ进程间(订阅-发布)通信配置优化

文章目录 0. 概述1. 发布者同步发送(pub)与订阅者异步接收(sub)示例代码可能的副作用: 2. 适度增加缓存和队列示例代码副作用: 3. 动态的IPC通道管理示例代码副作用: 4. 接收消息的超时设置示例代码副作用: 5. 增加I/O线程数量示例代码副作用: 6. 异步消息发送(使用`dontwait`标志)示例代码副作用: 7. 其他可以考虑的优化项7.1 立即发送(ZMQ_IM

VB和51单片机串口通信讲解(只针对VB部分)

标记:该篇文章全部搬自如下网址:http://www.crystalradio.cn/thread-321839-1-1.html,谢谢啦            里面关于中文接收的部分,大家可以好好学习下,题主也在研究中................... Commport;设置或返回串口号。 SettingS:以字符串的形式设置或返回串口通信参数。 Portopen:设置或返回串口

BERN2(生物医学领域)命名实体识别与命名规范化工具

BERN2: an advanced neural biomedical named entity recognition and normalization tool 《Bioinformatics》2022 1 摘要 NER和NEN:在生物医学自然语言处理中,NER和NEN是关键任务,它们使得从生物医学文献中自动提取实体(如疾病和药物)成为可能。 BERN2:BERN2是一个工具,

深入理解TCP通信

这大概是自己博客上面第三次写TCP通信demo了,总是写同样的内容也不太好啊,不过每一次都比前一次进步一点。这次主要使用了VIM编辑工具、gdb调试、wireshirk、netstat查看网络状态。 参考《C++服务器视频教程》、《Unix网络编程》 一、VIM常用命令 vim server.cpp #打开一个文件:w 写入文件:wq 保存并退出:q! 不保存退出显示行号