前言:行动是治愈拖延的良药,现代人所谓的拖延症都是对自己懒惰的借口。
一直说要看看libevent源码,却又一直拖着忙着,不知道在忙些什么。我说在公司看着那一堆乱七八糟的源码都看下去了,为什么不能花点时间来研读下别人的优秀的源码呢?同学说那是因为在公司那是被动的,而这个是主动的,想想也挺有道理。。

这篇文章是看libevent的第一篇记录,libevent是基于信号来分发消息,对于信号的描述结构

typedef void (*ev_sighandler_t)(int);/* Data structure for the default signal-handling implementation in signal.c*/
struct evsig_info {/* Event watching ev_signal_pair[1] */struct event ev_signal;/* Socketpair used to send notifications from the signal handler */evutil_socket_t ev_signal_pair[2];/* True iff we've added the ev_signal event yet. */int ev_signal_added;/* Count of the number of signals we're currently watching. */int ev_n_signals_added;/* Array of previous signal handler objects before Libevent started* messing with them.  Used to restore old signal handlers. */
#ifdef _EVENT_HAVE_SIGACTIONstruct sigaction **sh_old;
#elseev_sighandler_t **sh_old;
#endif/* Size of sh_old. */int sh_old_max;
};

其中里面有个成员变量 ev_signal_pair[2]; 在初始化时将它设为了一组连接着的socket。在linux下使用的是socketpair函数,

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

而windows下没有这个函数,是手动实现的。这个socketpair的用途为

1. 这对套接字可以用于全双工通信,每一个套接字既可以读也可以写。例如,可以往sv[0]中写,从sv[1]中读;或者从sv[1]中写,从sv[0]中读; 
2. 如果往一个套接字(如sv[0])中写入后,再从该套接字读时会阻塞,只能在另一个套接字中(sv[1])上读成功; 
3. 读、写操作可以位于同一个进程,也可以分别位于不同的进程,如父子进程。如果是父子进程时,一般会功能分离,一个进程用来读,一个用来写。因为文件描述副sv[0]和sv[1]是进程共享的,所以读的进程要关闭写描述符, 反之,写的进程关闭读描述符。
借此博客的一张图https://www.cnblogs.com/big-xuyue/p/4098578.html

实现原理我还没有看到,此文主要说windows下socketpair的实现。

#include<WinSock2.h>
#include<Windows.h>
#pragma comment(lib,"ws2_32.lib")
#include<iostream>
using namespace std;void EVUTIL_SET_SOCKET_ERROR(int code)
{cout<<"error code"<<code<<endl;
}
int evutil_ersatz_socketpair(int family, int type, int protocol, SOCKET fd[2])
{/* This code is originally from Tor.  Used with permission. *//* This socketpair does not work when localhost is down. So* it's really not the same thing at all. But it's close enough* for now, and really, when localhost is down sometimes, we* have other problems too.*/
#ifdef WIN32
#define ERR(e) WSA##e
#else
#define ERR(e) e
#endifSOCKET listener = -1;SOCKET connector = -1;SOCKET acceptor = -1;struct sockaddr_in listen_addr;struct sockaddr_in connect_addr;int size;int saved_errno = -1;if (protocol|| (family != AF_INET
#ifdef AF_UNIX&& family != AF_UNIX
#endif)) {EVUTIL_SET_SOCKET_ERROR(ERR(EAFNOSUPPORT));return -1;}if (!fd) {EVUTIL_SET_SOCKET_ERROR(ERR(EINVAL));return -1;}listener = socket(AF_INET, type, 0);if (listener < 0)return -1;memset(&listen_addr, 0, sizeof(listen_addr));listen_addr.sin_family = AF_INET;listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);listen_addr.sin_port = 0;    /* kernel chooses port.  */if (bind(listener, (struct sockaddr *) &listen_addr, sizeof(listen_addr))== -1)goto tidy_up_and_fail;if (listen(listener, 1) == -1)goto tidy_up_and_fail;connector = socket(AF_INET, type, 0);if (connector < 0)goto tidy_up_and_fail;/* We want to find out the port number to connect to.  */size = sizeof(connect_addr);//获取监听地址if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)goto tidy_up_and_fail;if (size != sizeof(connect_addr))goto abort_tidy_up_and_fail;//connector连接到listener上if (connect(connector, (struct sockaddr *) &connect_addr,sizeof(connect_addr)) == -1)goto tidy_up_and_fail;size = sizeof(listen_addr);//listener接受连接,此时connector与acceptor是一对已连接的socket pairacceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);if (acceptor < 0)goto tidy_up_and_fail;if (size != sizeof(listen_addr))goto abort_tidy_up_and_fail;/* 判断两个socket之间的地址,端口,协议是否相同   */if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)goto tidy_up_and_fail;if (size != sizeof(connect_addr)|| listen_addr.sin_family != connect_addr.sin_family|| listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr|| listen_addr.sin_port != connect_addr.sin_port)goto abort_tidy_up_and_fail;closesocket(listener);//不需要再监听了fd[0] = connector;fd[1] = acceptor;/*** 此时就已经创建了两个连接起来的socket,即可以实现进程间的通信*/return 0;abort_tidy_up_and_fail:saved_errno = ERR(ECONNABORTED);
tidy_up_and_fail:if (saved_errno < 0);//saved_errno = EVUTIL_SOCKET_ERROR();if (listener != -1)closesocket(listener);if (connector != -1)closesocket(connector);if (acceptor != -1)closesocket(acceptor);EVUTIL_SET_SOCKET_ERROR( saved_errno);return -1;
#undef ERR
}int main() {WSADATA wsa;WSAStartup(MAKEWORD(2, 2), &wsa);SOCKET fd[2];if (evutil_ersatz_socketpair(AF_INET, SOCK_STREAM, 0, fd))goto end;char buf[1024] = { 0 };send(fd[0], "hello", 6, 0);int len = recv(fd[1], buf, 1024, 0);if (len){buf[len] = '\0';cout << "收到" << buf << endl;strcat(buf, " word");int r=send(fd[0], buf, strlen(buf), 0);}char buf2[1024] = { 0 };len = recv(fd[1], buf2, 1024, 0);if (len){buf2[len] = '\0';cout << "2收到" << buf2 << endl;}end:system("pause");return 1;
}

代码中首先定义了一个listener来监听连接,然后有一个connecter去主动连接,然后调用accept后返回一个accepter,如果没有发生异常问题,那此时connecter与accepter是一组可以相互通信的socket。最后通过参数fd返回函数调用处实参。

Windows下实现socketpair进行进程通信相关推荐

  1. Windows下使用Python实现串口通信

    Windows下使用Python实现串口通信 基本信息 配置过程 配置思路 详细配置过程 安装USB装TTL驱动 配置serial库 获取设备端口号 配置串口通信 配置说明 测试过程 其他学习记录 参 ...

  2. Windows下的Powerlink主从站通信-(现场总线作业——NJIT)

    Windows下的Powerlink主从站通信-(现场总线作业--NJIT) 一.设计任务(要求) 二.Powerlink工作原理 1.Powerlink简介: 2.Powerlink设备类型及设备模 ...

  3. windows下实现socketpair函数

    前言 socketpair是Linux下的函数,其主要作用是创建一对套节字来进行进程间通信,其与匿名管道(PIPE)的作用相似,这两个套节字均可读可写. 具体介绍见本博客另一篇文章: https:// ...

  4. Windows下用C语言获取进程cpu使用率,内存使用,IO情况

    /** @file * @brief 进程统计信息函数的声明 * @author 张亚霏 * @date 2009/05/03 * @version 0.1 * */ #ifndef PROCESS_ ...

  5. windows下 , py运用了 进程池, 将py打包成exe,出现错误的 解决思路之一

    在windows上,用pycharm开发了一个小项目, 用到了from concurrent.futures import ProcessPoolExecutor 本来在pycharm里面,运行的好好 ...

  6. c语言占用cpu的程序,Windows下用C语言获取进程cpu使用率,内存使用,IO情况

    转自: http://zhangyafeikimi.iteye.com/blog/378658 process_stat.h /** @file * @brief 进程统计信息函数的声明 * @aut ...

  7. Qt笔记-获取Windows下目前运行的进程信息

    目录 基本概念 代码与实例 源码下载 基本概念 知识点如下: CreateToolhelp32Snapshot    获取当前系统进程快照 void Thread::getSnapshot() {HA ...

  8. Windows下80端口被进程SystemPID=4占用的解决方法

    突然发现 80 端口被莫名占用,咋一看还是 System 这个进程 又无法结束这货,于是开始慢慢查看到底是什么东西占用了 首先,打开 cmd 跑这一句,80 端口被System 占用,肯定是 HTTP ...

  9. Windows 下80端口被进程 System PID=4 占用的解决方法

    80 端口被莫名占用,还是 System 这个进程,又无法结束这货.慢慢排查看到底是什么东东占用了. 打开 cmd 执行 netsh http show servicestate ,80 端口被Sys ...

最新文章

  1. 寄语2013应届实习生
  2. l360废墨收集垫清零_知识分享003:EPSON L360打印机出现故障-废墨计数清零
  3. SDP(12): MongoDB-Engine - Streaming
  4. 二叉树中最大的二叉搜索子树
  5. LSTM和GRU的解析从未如此通俗易懂(动图)
  6. 9.Shell 编程从入门到精通 --- 进程
  7. php报修小程序,微信小程序报修管理系统
  8. SublimeText3安装中文插件
  9. 正确安装Senta的姿势
  10. 计算机术语pc是什么意思,pc是什么意思
  11. 怎么把python变成中文_又一个奇葩要求,Python是如何将“中文”转“拼音”的?...
  12. PTA最短工期 详细解释 为什么最短反而是最长?
  13. 计算机考研什么时候开始备考,2022考研什么时候开始准备最好 为什么
  14. Oneday01 | ~scanf、冒泡排序、sort排序
  15. SAP-ABAP-一般FUNCTION ALV代码示例
  16. 适用于 Linux 桌面的 7 大白板应用程序
  17. 爬虫-获取指定城市所有企业信息
  18. 使用springboot访问本地电脑资源,并解决中文路径无法访问的问题
  19. 5.20下周黄金行情走势分析及开盘独家交易策略
  20. CCSP2021 分赛区

热门文章

  1. element-ui在表格里插入图片或者链接等
  2. scrapy的注意点的问题
  3. 2021年安徽省安全员C证考试试卷及安徽省安全员C证试题及解析
  4. 软件设计师备考笔记(十六)UML建模及习题
  5. windows上使用QQ截取网页长图,支持下拉方法截图任意长的图
  6. 【SMS】SMS协议介绍之IP-SM-GW
  7. 诚哥的逆袭2 sdoj
  8. 朋友圈刷屏了!互联网人回乡求生指南
  9. 追查坏牛奶(最大流)
  10. Spring Cloud -Eureka 注册中心配置