1 网络中进程间通信
本地进程通信(ipc)有很多方式:
(1)消息传递 (2)同步 (3)共享内存等等
首要解决的是如何唯一标识一个进程,本地可通过进程PID。
网络层的“ip地址”唯一标识网络中的主机,传输层的“协议+端口”唯一标识主机中的应用程序(进程)
(2)socket
socket是“open--write/read---close"模式的一种实现
(3)socket 基本操作
1. socket(int domain,int type,int protocol)---相当于普通文件的打开操作,返回一个socket descriptor,它唯一标识一个socket
domain:协议域,决定了socket的地址类型
type :指定socket类型
protocol:指定协议
当调用socket创建一个socket时,返回的socket描述字存在于它的协议域(AF_XXX)空间中,但没有一个具体的地址。得用bind()函数。否则当调用connect和listen()系统会随机分配一个端口。
2.bind 函数----将一个地址族中的特定地址赋给socket
例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket
通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个
(3)listen() connect()
通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个
(4)accept()
TCP服务器端依次调用socket()、bind()、listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()、connect()之后就想TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);如果accpet成功,那么其返回值是由内核自动生成的一个全新的描述字,代表与返回客户的TCP连接
一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭
(5)read() write()
至此服务器与客户已经建立好连接了。可以调用网络I/O进行读写操作了,即实现了网咯中不同进程之间的通信!网络I/O操作有下面几组:
- read()/write()
- recv()/send()
- readv()/writev()
- recvmsg()/sendmsg()
- recvfrom()/sendto()
注意:close操作只是使相应socket描述字的引用计数-1,只有当引用计数为0的时候,才会触发TCP客户端向服务器发送终止连接请求