在nginx中,master进程与worker进程之间使用了一种全双工通信方式--socketpair。socketpair 函数成功执行后会创建一对已经建立连接的socket对,两个相互通信的进程分别使用其中一个socket进行读写操作,就能够实现两进程间的通信。
查看nginx源码,可以看到,下面的函数创建了socketpair
ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn) { u_long on; ngx_pid_t pid; ngx_int_t s; /. ......省略...... ./ if (respawn != NGX_PROCESS_DETACHED) { /* Solaris 9 still has no AF_LOCAL */ //创建socketpair if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "socketpair() failed while spawning \"%s\"", name); return NGX_INVALID_PID; } //非阻塞 if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //非阻塞 if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //异步 on = 1; if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //设置将要在文件描述词fd上接收SIGIO 或 SIGURG事件信号的进程或进程组标识 。 if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //设置close_on_exec,当通过exec函数族创建了新进程后,原进程的该socket会被关闭 if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } //设置close_on_exec,当通过exec函数族创建了新进程后,原进程的该socket会被关闭 if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) { ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; } ngx_channel = ngx_processes[s].channel[1]; } else { ngx_processes[s].channel[0] = -1; ngx_processes[s].channel[1] = -1; } ngx_process_slot = s; pid = fork(); switch (pid) { case -1: ngx_close_channel(ngx_processes[s].channel, cycle->log); return NGX_INVALID_PID; case 0: //fork成功,子进程创建,同时相关socket描述符也会被复制一份 ngx_pid = ngx_getpid(); proc(cycle, data); break; default: break; } /. ......省略...... ./ return pid; }
fork成功后,原进程的descriptor也会被复制一份,如果在fork的进程中该描述符不再使用,需要我们及时关闭。
如果我们使用的是 fork->exec函数族 的形式创建新进程的话,我们可以采用更好的办法来确保原有的descriptor被正常关闭,避免资源的泄漏。也就是上边代码中对socket调用fcntl(FD_CLOEXEC)函数,设置该socket的属性:当exec函数族被调用后,该socket会被自动关闭。使用这种在socket创建后立即设置FD_CLOEXEC属性的办法,避免了我们在exec创建进程前手动关闭相关socket的操作,尤其是当有大量的descriptor被创建、管理的时候非常实用。
很多时候我们是使用下边的方法进行操作的:
#include <sys> #include <sys> #include <stdlib.h> #include <stdio.h> int main() { pid_t pid; int fds[2]; int valRead, valWrite; if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) { return 0; } pid = fork(); if (0 == pid) { pid = getpid(); printf("[%d]-child process start", pid); close(fds[0]); //read write on fds[1] write(fds[1], &valWrite, sizeof(valWrite)); read(fds[1], &valRead, sizeof(valRead)); } else if (0 <p> 可以看到,fork前,当前进程创建了一对socket,也就是socketpair。对于这对socket,可以看作一个是服务器端fds[0],另一个是客户端fds[1],通过fds[0]与fds[1]之间建立的链接,我们可以完成全双工通信。</p> <p> fork执行后,创建了子进程。在子进程中,之前父进程创建的socketpair自然也会被复制一份为fds',存在于子进程中。父进程继续执行。这个时候,在父进程和子进程中会存在相同socketpair。</p> <p> 试想,我们在主进程中向fds[0]中写入数据,在子进程中的fds'[1]上就会读取到该数据,这样就实现了父进程与子进程间的通信。当然,在主进程fds[1]上写数据,在子进程fds'[0]上也会读到写入的数据。我们实际使用中,只需要保留一对socket用来通信就可以了,另外两个socket就可以分别在父进程和子进程中关闭不用了。</p> <p> 当然了,如果我们能够把fds中的一个socket通过某种方式传递给另一个进程,那么也可以实现socketpair进程间通信了。</p> <br> <p> 以上就介绍了nginx 进程间通信-socketpair,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。</p> <p> </p> </stdio.h></stdlib.h></sys></sys>

本篇文章给大家带来了关于php+socket的相关知识,其中主要介绍了IO多路复用,以及php+socket如何实现web服务器?感兴趣的朋友下面一起来看一下,希望对大家有帮助。

一、基于TCP协议的socket套接字编程1、套接字工作流程先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束,使用以下Python代码实现:importso

SpringBoot端第一步,引入依赖首先我们需要引入WebSocket所需的依赖,以及处理输出格式的依赖com.alibabafastjson1.2.73org.springframework.bootspring-boot-starter-websocket第二步,创建WebSocket配置类importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Config

php socket无法连接的解决办法:1、检查php是否开启socket扩展;2、打开php.ini文件,检查“php_sockets.dll”是否被加载;3、取消“php_sockets.dll”的注释状态即可。

随着互联网的发展,文件传输成为人们日常工作和娱乐中不可或缺的一部分。然而,传统的文件传输方式如邮件附件或文件分享网站存在一定的限制,无法满足实时性和安全性的需求。因此,利用PHP和Socket技术实现实时文件传输成为了一种新的解决方案。本文将介绍利用PHP和Socket技术实现实时文件传输的技术原理、优点和应用场景,并通过具体案例来演示该技术的实现方法。技术

本篇文章给大家带来了关于php+socket的相关知识,其中主要介绍了什么是socket?php+socket如何实现客户端与服务端数据传输?感兴趣的朋友下面一起来看一下,希望对大家有帮助。

本篇文章给大家带来了关于php+socket的相关知识,其中主要介绍了怎么使用php原生socket实现一个简易的web聊天室?感兴趣的朋友下面一起来看一下,希望对大家有帮助。

nginx发布的1.9.1版本引入了一个新的特性:允许使用so_reuseport套接字选项,该选项在许多操作系统的新版本中是可用的,包括dragonflybsd和linux(内核版本3.9及以后)。该套接字选项允许多个套接字监听同一ip和端口的组合。内核能够在这些套接字中对传入的连接进行负载均衡。(对于nginxplus客户,此功能将在年底发布的版本7中出现)so_reuseport选项有许多潜在的实际应用。其他服务也可以使用它来简单实现执行中的滚动升级(nginx已经通过支持了滚动升级)。对


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3 Linux新版
SublimeText3 Linux最新版

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),