96SEO 2026-02-20 04:54 7
前面的管道、共享内存等等进程间通信都是仅限于用在本机进程之间通信。

网络间进程通信要解决的是不同主机进程间的相互通信问题可把同机进程通信看作是其中的特例。
为此首先要解决的是网络间进程标识问题。
同一主机上不同进程可用进程号process
ID唯一标识。
但在网络环境下各主机独立分配的进程号不能唯一标识该进程。
例如主机A赋于某进程号5在B机中也可以存在5号进程因此“5号进程”
其次操作系统支持的网络协议众多不同协议的工作方式不同地址格式也不同。
因此网间进程通信还要解决多重协议的识别问题。
TCP/IP协议族已经帮我们解决了这个问题网络层的“ip地址”可以唯一标识网络中的主机而传输层的“协议端口”可以唯一标识主机中的应用程序进程。
这样利用三元组ip地址协议端口就可以标识网络的进程了网络中的进程通信就可以利用这个标志与其它进程进行交互。
V的TLI已经被淘汰来实现网络进程之间的通信。
就目前而言几乎所有的应用程序都是采用socket而现在又是网络时代网络中进程通信是无处不在这就是为什么说“一切皆socket”。
socket起源于Unix而Unix/Linux基本哲学之一就是“一切皆文件”都可以用
即是一种特殊的文件一些socket函数就是对其进行的操作读/写IO、打开、关闭.
说白了Socket是应用层与TCP/IP协议族通信的中间软件抽象层它是一组接口。
在设计模式中Socket其实就是一个门面模式它把复杂的TCP/IP协议族隐藏在Socket接口后面对用户来说一组简单的接口就是全部让Socket去组织数据以符合指定的协议。
文件描述符其实就是一个整数我们最熟悉的句柄是0、1、2三个0是标准输入1是标准输出2是标准错误输出。
0、1、2是整数表示的对应的FILE
addrlen);在生活中A要电话给BA拨号B听到电话铃声后提起电话这时A和B就建立起了连接A和B就可以讲话了。
等交流结束挂断电话结束此次交谈。
打电话很简单解释了这工作原理“open—write/read—close”模式。
如上图服务器端先初始化Socket然后与端口绑定(bind)对端口进行监听(listen)这个过程可以理解为开机服务器已经做好了事前准备。
然后调用accept阻塞等待客户端连接。
在这时如果有个客户端初始化一个Socket然后连接服务器(connect)如果连接成功这时客户端与服务器端的连接就建立了。
客户端发送数据请求服务器端接收请求并处理请求然后把回应数据发送给客户端客户端读取数据最后关闭连接一次交互结束。
普通文件的打开操作。
普通文件的打开操作返回一个文件描述字而socket()
描述字跟文件描述字一样后续的操作都有用到它把它作为参数通过它来进行一些读写操作。
protofamily即协议域又称为协议族family。
常用的协议族有AF_INET(IPV4)、AF_INET6(IPV6)、AF_LOCAL或称AF_UNIXUnix域socket、AF_ROUTE等等。
协议族决定了socket的地址类型在通信中必须采用对应的地址如AF_INET决定了要用ipv4地址32位的与端口号16位的的组合、AF_UNIX决定了要用一个绝对路径名作为地址。
type指定socket类型。
常用的socket类型有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。
protocol故名思意就是指定协议。
常用的协议有IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。
注意并不是上面的type和protocol可以随意组合的如SOCK_STREAM不可以跟IPPROTO_UDP组合。
当protocol为0时会自动选择type类型对应的默认协议。
正如上面所说bind()函数把一个地址族中的特定地址赋给socket。
例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。
sockfd即socket描述字它是通过socket()函数创建了返回值唯一标识一个socket。
bind()函数就是将给这个描述字绑定一个名字。
addr一个const
的协议地址。
这个地址结构根据地址创建socket时的地址协议族的不同而不同如ipv4对应的是
通常服务器在启动的时候都会绑定一个众所周知的地址如ip地址端口号用于提供服务客户就可以通过它来接连服务器而客户端就不用指定有系统自动分配一个端口号和自身的ip地址组合。
这就是为什么通常服务器端在listen之前会调用bind()而客户端就不会调用而是在connect()时由系统随机生成一个。
API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、
由于每一个协议的结构体都不同那么为了适应这些协议就必须开发出多个
主机字节序就是我们平常说的大端和小端模式不同的CPU有不同的字节序类型这些字节序是指整数在内存中保存的顺序这个叫做主机序。
引用标准的Big-Endian和Little-Endian的定义如下
Little-Endian就是低位字节排放在内存的低地址端高位字节排放在内存的高地址端。
Big-Endian就是高位字节排放在内存的低地址端低位字节排放在内存的高地址端。
bit值以下面的次序传输首先是07bit其次815bit然后1623bit最后是24~31bit。
这种传输次序称作大端字节序。
由于TCP/IP首部中所有的二进制整数在网络中传输时都要求以这种次序因此它又称作网络字节序。
字节序顾名思义字节的顺序就是大于一个字节类型的数据在内存中的存放顺序一个字节的数据没有顺序的问题了。
所以在将一个地址绑定到socket的时候请先将主机字节序转换成为网络字节序而不要假定主机字节序跟网络字节序一样使用的是Big-Endian务必将其转化为网络字节序再赋给socket。
实际上我们并不需要过于关心主机序列、网络序列是怎么组织的因为有对应的接口帮我们实现这两种序列之间的转化下面是一些网络字节序转为主机字节序、主机字节序转为网络字节序的函数。
listen()函数只能在服务器进程中使用让服务器进程进入监听状态等待客户端的连接请求listen()函数在一般在
listen函数的第一个参数即为要监听的socket描述字第二个参数表示本服务器中全连接队列中数据的个数
1。
socket()函数创建的socket默认是一个主动类型的listen函数将socket变为被动类型的等待客户的连接请求。
的等待连接队列能够达到的最大值。
在服务器进程正处理客户端连接请求的时候可能还存在其它的客户端请求建立连接因为
连接是一个过程由于同时尝试连接的用户过多使得服务器进程无法快速地完成所有的连接请求那怎么办呢直接丢掉其他客户端的连接肯定不是一个很好的解决方法。
因此内核会在自己的进程空间里维护一个队列这些连接请求就会被放入一个队列中服务器进程会按照先来后到的顺序去处理这些连接请求这样的一个队列内核不可能让其任意大所以必须有一个大小的上限这个
参数告诉内核使用这个数值作为队列的上限。
而当一个客户端的连接请求到达并且该队列为满时客户端可能会收到一个表示连接失败的错误本次请求会被丢弃不作处理。
TCP服务器端依次调用socket()、bind()、listen()之后就会监听指定的socket地址了。
TCP客户端依次调用socket()、connect()之后就向TCP服务器发送了一个连接请求。
TCP服务器监听到这个请求之后就会调用accept()函数取接收请求这样连接就建立好了。
之后就可以开始网络I/O操作了即类同于普通文件的读写I/O操作。
sockfd参数sockfd就是上面解释中的监听套接字这个套接字用来监听一个端口当有一个客户与服务器连接时它使用这个一个端口号而此时这个端口号正与这个套接字关联。
当然客户不知道套接字这些细节它只知道一个地址和一个端口号。
addr这是一个输出型参数它用来接受一个返回值这返回值里面包含了客户端的地址当然这个地址是通过某个地址结构来描述的用户应该知道这一个什么样的地址结构。
如果对客户的地址不感兴趣那么可以把这个值设置为NULL。
它也是输出型参数用来接受上述addr
的结构的大小它指明addr结构所占有的字节个数。
同样的它也可以被设置为NULL。
如果accept成功返回则服务器与客户已经正确建立连接了此时服务器通过accept返回的套接字来完成与客户的通信。
服务器要给客户端发消息那么必须使用
所有的IP地址这是整形的风格那么也需要进行从字符串风格转换为整形因为
将一个网络字节序的IP地址也就是结构体in_addr类型变量转化为点分十进制的IP地址字符串。
inet_aton()
将一个字符串表示的点分十进制IP地址转换为网络字节序存储在addr中并且返回该网络字节序表示的无符号整数。
accept默认会阻塞进程直到有一个客户连接建立后返回它返回的是一个新可用的套接字这个套接字是连接套接字。
监听套接字正如accept的第一个参数sockfd它是监听套接字是服务器一开始调用socket()函数生成的称为监听socket描述字(监听套接字)。
连接套接字一个套接字会从主动连接的套接字变身为一个监听套接字而accept函数返回的是已连接socket描述字(一个连接套接字)它代表着一个网络已经存在的连接。
一个服务器通常通常仅仅只创建一个监听socket描述字它在该服务器的生命周期内一直存在。
此外内核为每个由服务器进程接受的客户连接创建了一个已连接socket
描述字当服务器完成了对某个客户的服务相应的已连接socket描述字就被关闭。
可以形象地比喻为一个饭店门口有一位负责招待客人进入店里的员工店内有多个给客人提供服务的员工门口的员工只负责揽客店内的员工只负责招待客人对应为监听套接字只负责建立连接连接套接字只负责进程之间的通信。
如果使用一个描述字的话那么它的功能太多使得使用很不直观同时在内核确实产生了一个这样的新的描述字。
连接套接字socketfd_new
并没有占用新的端口与客户端通信依然使用的是与监听套接字socketfd一样的端口号。
至此服务器与客户已经建立好连接了。
可以调用网络I/O进行读写操作了即实现了网咯中不同进程之间的通信网络I/O操作有下面几组
recvfrom()/sendto()read()/write()recv()/send()………………
read函数是负责从fd中读取内容。
当读成功时read返回实际所读的字节数如果返回的值是0表示已经读到文件的结束了小于0表示出现了错误。
如果错误为EINTR说明读是由中断引起的如果是ECONNREST表示网络连接出了问题。
write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数。
失败时返回-1并设置errno变量。
1)write的返回值大于0表示写了部分或者是全部的数据。
2)返回的值小于0此时出现了错误。
我们要根据错误类型来处理。
如果错误为EINTR表示在写的时候出现了中断错误。
如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接)。
的情况因为写程序的时候可以根据这个来区分不同的处理情况具体参见man文档或者baidu、Google。
在服务器与客户端建立连接之后会进行一些读写操作完成了读写操作就要关闭相应的socket描述字好比操作完打开的文件要调用fclose关闭打开的文件。
inet_addr(ip.c_str());addr.sin_port
将读到的缓冲区内容放到输出参数中buf-assign(tmp,
inet_addr(ip.c_str());addr.sin_port
public:UdpServer(){assert(sock_.Socket());}~UdpServer(){sock_.Close();}bool
resp.c_str());}sock_.Close();return
port_(port){assert(sock_.Socket());}~UdpClient(){sock_.Close();}bool
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback