进程笔记2:进程之间的通信(UNIX域套接字socket)

2024-04-09 12:18

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

socket的地址数据结构根据不同的系统以及网络环境有不同形式。为了使不同格式地址能够被传入套接字函数,必须强制将地址结构转换为:

struct sockaddr{sa_family_t sa_family; /* address family*/char        sa_data[]; /* variable-length address*/...
};

套接字实现可以自由地添加额外的成员并且定义sa_data成员的大小。例如在linux中,该结构定义如下

struct sockaddr{sa_family_t sa_family;   /* address family*/char        sa_data[14]; /* variable-length address*/
};

其中sa_family_t表示套接字的通信域。主要有以下四个值


描述
AF_INETIPv4因特网域
AF_INET6IPv6因特网域
AF_UNIXUNIX域
AF_UNSPEC未指定


创建套接字的函数如下

#include <sys/socket.h>
int socket(int domain, int type, int protocol);/*成功返回文件(套接字)描述符,出错返回-1

其中domain指代通信域,type指代套接字类型,主要有以下四种

类型描述
SOCK_DGRAM长度固定的、无连接的不可靠报文传递
SOCK_RAMIP协议的数据报接口
SOCK_SEQPACKET长度固定、有序、可靠的面向连接报文传递
SOCK_STREAM有序、可靠、双向的面向连接字节流

参数protocol通常是零,表示按给定的域和套接字类型选择默认协议。当对同一域和套接字类型支持多个协议时,可以使用protocol参数选择一个特定协议。

一个多进程间利用UNIX域套接字(只用在本地)进行通信的例子( 代码分两部分不方便观察,后面socket_unix.c将其合为了一部分

 /*
domain_socket.h
@Author: duanjigang @2006-4-11
@Desp: declaratin of methods used for unix-domain-socket communication 
*/
#ifndef _H_
#define _H_
#include <stdio.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/socket.h>
#define MSG_SIZE 1024
int init_send_socket(struct sockaddr_un * addr,char * path)
{int sockfd,len;sockfd=socket(AF_UNIX,SOCK_DGRAM,0);if(sockfd<0){exit(1);}bzero(addr,sizeof(struct sockaddr_un));addr->sun_family=AF_UNIX;strcpy(addr->sun_path,path);return sockfd;
}
int init_recv_socket(char * path)
{int sockfd,len; struct sockaddr_un addr; sockfd=socket(AF_UNIX,SOCK_DGRAM,0); if(sockfd<0) { return -1;} bzero(&addr,sizeof(struct sockaddr_un)); addr.sun_family = AF_UNIX; strcpy(addr.sun_path, path);unlink(path);len = strlen(addr.sun_path) + sizeof(addr.sun_family);if(bind(sockfd,(struct sockaddr *)&addr,len)<0) { return -1;} return sockfd;}
int receive_from_socket(int sockfd, char msg[])
{int n; memset(msg, 0, MSG_SIZE);n=recvfrom(sockfd, msg, MSG_SIZE, 0, NULL, NULL); if(n<=0){return -1;}msg[n]=0;return n;
}
int send_to_socket(int sockfd, char msg[], const struct sockaddr_un * addr)
{int len; len = strlen(addr->sun_path)+sizeof(addr->sun_family);sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)addr,len); return 1;
}
#endif

/*
main.c
@Author: duanjigang @ 2006-4-11
@Desp: Two processes communicate with unix domain socket
*/
#include "domain_socket.h"
#define PATH "/home/useless"
/*
进程间通过域进行通讯-举例:父子进程,一个发送,一个接收
*/
int main(void)
{int pid;/*子进程用于发送消息*/if((pid = fork()) == 0){int fd, counter = 0;char send_buffer[MSG_SIZE];struct sockaddr_un addr;if( (fd = init_send_socket(&addr, PATH)) > 0)while(1){memset(send_buffer, 0 , MSG_SIZE);/*防止计数器越界,所以做一个复位判断*/sprintf(send_buffer,"message for %d times",counter++ >= 10000 ? 1 : counter);send_to_socket(fd, send_buffer, &addr);printf("Sender: %s\n", send_buffer);sleep(1);}}/*父进程用于接收消息*/else{int fd;char recv_buffer[MSG_SIZE];if( (fd = init_recv_socket(PATH))> 0)while(1){memset(recv_buffer, 0, MSG_SIZE);if(receive_from_socket(fd, recv_buffer)){printf("Receiver: %s\n", recv_buffer);}}}
}

运行结果示例:

Sender: message for 1 timesSender: message for 2 timesReceiver: message for 2 timesSender: message for 3 timesReceiver: message for 3 timesSender: message for 4 timesReceiver: message for 4 timesSender: message for 5 timesReceiver: message for 5 times


socket_unix.c

//利用UNIX域套接字通信#include <stdio.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/socket.h>#define MSG_MAX_SIZE 1024
#define PATH "a.socket"//套接字文件int main()
{int len;int socket_fd;struct sockaddr_un addr;bzero(&addr, sizeof(struct sockaddr_un));addr.sun_family = AF_UNIX;strcpy(addr.sun_path, PATH); len = strlen(addr.sun_path)+sizeof(addr.sun_family);if(!fork())//子进程内部代码{int counter = 0;char send_buffer[MSG_MAX_SIZE];//init send socketsocket_fd = socket(AF_UNIX, SOCK_DGRAM, 0); if(socket_fd<0){printf("client socket error!");return 0;}while(1) //循环发送数据消息{memset(send_buffer, 0, MSG_MAX_SIZE);sprintf(send_buffer, "message for %d times", counter++);//将数据信息发送到addr指定的套接字文件之中,所以这样进程之间就可以进行通信sendto(socket_fd, send_buffer, strlen(send_buffer), 0, (struct sockaddr*)&addr, len);printf("sender:%s\n", send_buffer);sleep(1);}}else{char recv_buffer[MSG_MAX_SIZE];//init recv socketsocket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);if(socket_fd<0){printf("server socket error!");return 0;}unlink(PATH);//防止要创建的socket文件已存在if(bind(socket_fd, (struct sockaddr *)&addr, len)<0)//只有bind以后才会在硬盘创建套接字PATH{printf("bind error");return 0;}while(1)//循环接收数据{memset(recv_buffer, 0, MSG_MAX_SIZE);//receive from socket从指定socket中读取数据,这里socket已经绑定了指定的PATH的文件recvfrom(socket_fd, recv_buffer, MSG_MAX_SIZE, 0, NULL, NULL);printf("receive Message: %s\n", recv_buffer);}}return 0;
}


这篇关于进程笔记2:进程之间的通信(UNIX域套接字socket)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.

Java中数组与栈和堆之间的关系说明

《Java中数组与栈和堆之间的关系说明》文章讲解了Java数组的初始化方式、内存存储机制、引用传递特性及遍历、排序、拷贝技巧,强调引用数据类型方法调用时形参可能修改实参,但需注意引用指向单一对象的特性... 目录Java中数组与栈和堆的关系遍历数组接下来是一些编程小技巧总结Java中数组与栈和堆的关系关于

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL

一文解密Python进行监控进程的黑科技

《一文解密Python进行监控进程的黑科技》在计算机系统管理和应用性能优化中,监控进程的CPU、内存和IO使用率是非常重要的任务,下面我们就来讲讲如何Python写一个简单使用的监控进程的工具吧... 目录准备工作监控CPU使用率监控内存使用率监控IO使用率小工具代码整合在计算机系统管理和应用性能优化中,监

Python实现MQTT通信的示例代码

《Python实现MQTT通信的示例代码》本文主要介绍了Python实现MQTT通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 安装paho-mqtt库‌2. 搭建MQTT代理服务器(Broker)‌‌3. pytho

Linux进程CPU绑定优化与实践过程

《Linux进程CPU绑定优化与实践过程》Linux支持进程绑定至特定CPU核心,通过sched_setaffinity系统调用和taskset工具实现,优化缓存效率与上下文切换,提升多核计算性能,适... 目录1. 多核处理器及并行计算概念1.1 多核处理器架构概述1.2 并行计算的含义及重要性1.3 并

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin