socket可以用来网络中的进程间通信。比如浏览器与网页服务器之间的通信(访问baidu.com)或者QQ发送消息给对方。
本地进程间通信方式有哪些?
- 管道(有名管道、无名管道)
- 消息队列
- 共享内存(映射一段能被其他进程访问的内存,这个共享空间是被某个进程创建,别的进程也可以访问这个共享空间,需要和进程间同步一块使用)
- 信号量(控制多个进程对共享资源的访问,锁机制,防止当前进程正在访问共享资源时,别的进程也访问该资源)
- 信号(用于通知接收进程某个时间已经发生)
网络中进程之间如何通信?
首先网络层的IP地址能够确定是给哪个主机发送消息的,传输层的协议和端口能确定是给该主机中哪个进程发送消息的,通过(IP地址、协议、端口)可以标识网络的进程,网络中的进程通信就可以利用这个标识与其他进程进行交互。
什么是socket?
socket跟文件操作类似(打开、读写、关闭)
接口函数:
int socket(int domain, int type, int protocol);
对应文件操作中的打开文件,文件操作中会返回一个文件描述符,这个socket作用是创建一个socket描述符,用于标识一个socket
domain:协议族(AF_INET、AF_INET6、AF_LOCAL、AF_ROUTE)这个可以决定socket的地址类型。AF_INET:ipv4,AF_INET6:ipv6,AF_LOCAL:要用一个绝对路径名作为地址。
type:socket类型(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET)
protocol:指定协议(IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC)
需要根据type指定protocol。当protocol为0时,会自动选择type类型对应的默认协议。
如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()、listen()时系统会自动随机分配一个端口。
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
bind()函数把一个地址族中的特定地址赋给socket。例如对应AF_INET、AF_INET6就是把一个ipv4或ipv6地址和端口号组合赋给socket。
服务器端要用 bind() 函数将套接字与特定的 IP 地址和端口绑定起来,只有这样,流经该 IP 地址和端口的数据才能交给套接字处理
sockfd:socket描述符,bind()函数就是将给这个描述符绑定一个名字。
int listen(int sockfd, int backlog);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
listen函数的第一个参数即为要监听的socket描述字,第二个参数为相应socket可以排队的最大连接个数。socket()函数创建的socket默认是一个主动类型的,listen函数将socket变为被动类型的,等待客户的连接请求。
connect函数的第一个参数即为客户端的socket描述字,第二参数为服务器的socket地址,第三个参数为socket地址的长度。客户端通过调用connect函数来建立与TCP服务器的连接。
服务端调用完listen之后就会监听指定的socket地址了,客户端调用完connect之后就向服务端发送一个连接请求。服务端如果有连接请求之后就会调用accept去接收请求。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
这个函数也会返回一个描述符,这个描述符指的是已连接客户端A的描述符,用于区分接收哪个客户端的数据
read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0表示已经读到文件的结束
write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数
在服务器与客户端建立连接之后,会进行一些读写操作,完成了读写操作就要关闭相应的socket描述字,好比操作完打开的文件要调用fclose关闭打开的文件。
socket中TCP的三次握手建立连接
- 客户端向服务器发送一个SYN J
- 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
- 客户端再想服务器发一个确认ACK K+1
三次握手完毕,连接建立
socket中TCP的四次握手释放连接
- 某个应用进程首先调用close主动关闭连接,这时TCP发送一个FIN M;
- 另一端接收到FIN M之后,执行被动关闭,对这个FIN进行确认。它的接收也作为文件结束符传递给应用进程,因为FIN的接收意味着应用进程在相应的连接上再也接收不到额外数据;
- 一段时间之后,接收到文件结束符的应用进程调用close关闭它的socket。这导致它的TCP也发送一个FIN N;
- 接收到这个FIN的源发送端TCP对它进行确认。