Open duyue6002 opened 5 years ago
本地进程通信方式有:
网络进程通信:网络层IP地址标识主机,传输层协议和端口标识进程
在Linux中,一切皆文件,可以用 open - > write/read -> close 来操作,Socket就是这种模式的实现,socket是一种特殊文件,socket函数是对其进行的操作。
int socket(int domain, int type, int protocol);
socket()对应于普通文件的打开,创建socket描述符(socket descriptor)唯一标识一个socket,用它作为参数,来进行一些读写操作。三个参数分别为:
domain:协议域,协议族,address family AF_INET: 决定用IPv4地址(32 bits)和端口号(16 bits)的组合 AF_INET6: 标识使用IPv6 AF_LOCAL(AF_UNIX): 决定用一个绝对路径名作为地址
type:socket类型 SOCK_STREAM: 流套接字,使用TCP协议 SOCK_DGRAM: 数据报套接字,使用UDP协议 SOCK_ROW: 原始套接字,使用其他协议,读写内核没有处理的IP数据包
protocol: 指定协议 IPPROTO_TCP, IPPROTO_UDP, IPPROTO_SCTP, IPPROTO_TIPC
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数说明:
struct sockaddr_in { // sin socket internet sa_family_t sin_family; // AF_INET in_port_t sin_port; // port in network byte order sturct in_addr sin_addr; // Internet address }; struct in_addr { uint32_t s_addr; };
IPv6:
struct sockaddr_in6 { sa_family_t sin6_family; in_port_t sin6_port; uint6_t sin6_flowinfo; struct in6_addr sin6_addr; uint32_t sin6_scope_id; }; struct in6_addr { unsigned char s6_addr[16]; };
服务器启动时绑定地址和端口,客户端不用制定,系统自动分配(connect())
网络字节序与主机字节序 主机字节序:大端、小端,不同CPU不同字节序类型。字节序指整数在内存中保存的顺序。 Little-Endian: 地位低地址,高位高地址 Big-Endian: 高位低地址,地位高地址 网络字节序:Big-Endian
网络字节序与主机字节序
主机字节序:大端、小端,不同CPU不同字节序类型。字节序指整数在内存中保存的顺序。 Little-Endian: 地位低地址,高位高地址 Big-Endian: 高位低地址,地位高地址 网络字节序:Big-Endian
将地址绑定到socket时,先将主机字节序转为网络字节序,不能假定都使用Big-Endian。
服务端:listen(),客户端:connect()
int listen(int sockfd, int backlog); int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
listen函数的参数:
服务器端依次调用socket(), bind(), listen()后,监听指定socket地址。客户端依次调用socket(), connect()后发给服务器一个连接请求。服务器监听到请求后,调用accept()函数接收请求,这样连接建立完成,可以开始I/O操作。
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
函数返回已连接到socket描述字,服务器只创建一个监听socket描述字,在服务器端生命周期内一直存在。
#include <unistd.h> ssize_t read(int fd, void *buf, size_count); ssize_t write(int fd, const void *buf, size_t count); #include <sys/types.h> #include <sys/socket.h> ssize_t send(int sockfd, const void *buf, size_t len, int flags); ssize_t recv(int sockfd, void *buf, size_t len, int flags); ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
read函数负责从fd中读,返回实际所读的字节数,返回值是0时表示已经读完,小于0表示出现了错误。 write函数将buf中n字节内容写入fd,返回写的字节数,失败时返回-1,设置errno变量。
#include <unistd.h> int close(int fd);
进程间通信
本地进程通信方式有:
网络进程通信:网络层IP地址标识主机,传输层协议和端口标识进程
Socket概念
在Linux中,一切皆文件,可以用 open - > write/read -> close 来操作,Socket就是这种模式的实现,socket是一种特殊文件,socket函数是对其进行的操作。
socket基本操作
socket()
socket()对应于普通文件的打开,创建socket描述符(socket descriptor)唯一标识一个socket,用它作为参数,来进行一些读写操作。三个参数分别为:
domain:协议域,协议族,address family AF_INET: 决定用IPv4地址(32 bits)和端口号(16 bits)的组合 AF_INET6: 标识使用IPv6 AF_LOCAL(AF_UNIX): 决定用一个绝对路径名作为地址
type:socket类型 SOCK_STREAM: 流套接字,使用TCP协议 SOCK_DGRAM: 数据报套接字,使用UDP协议 SOCK_ROW: 原始套接字,使用其他协议,读写内核没有处理的IP数据包
protocol: 指定协议 IPPROTO_TCP, IPPROTO_UDP, IPPROTO_SCTP, IPPROTO_TIPC
bind()
参数说明:
IPv6:
服务器启动时绑定地址和端口,客户端不用制定,系统自动分配(connect())
将地址绑定到socket时,先将主机字节序转为网络字节序,不能假定都使用Big-Endian。
listen(), connect()
服务端:listen(),客户端:connect()
listen函数的参数:
accept()
服务器端依次调用socket(), bind(), listen()后,监听指定socket地址。客户端依次调用socket(), connect()后发给服务器一个连接请求。服务器监听到请求后,调用accept()函数接收请求,这样连接建立完成,可以开始I/O操作。
函数返回已连接到socket描述字,服务器只创建一个监听socket描述字,在服务器端生命周期内一直存在。
read(), write()
read函数负责从fd中读,返回实际所读的字节数,返回值是0时表示已经读完,小于0表示出现了错误。 write函数将buf中n字节内容写入fd,返回写的字节数,失败时返回-1,设置errno变量。
close()
socket中TCP三次握手建立连接
socket中TCP四次握手释放连接