一.套接字
socket是一种接口机制,可以让程序无论使用什么端口都可以从socket进出数据,
它负责了进程与协议之间的连接
1.编程模式
点对点(p2p):一对一通信
客户端/服务器(C/S):一对多
2.创建socket
int socket(int domain, int type, int protocol);
功能:创建socket描述符,可以把socket当作文件来看待,发送数据就是写文件,接收数据就是读文件
doaim:地址类型
AF_UNIX, AF_LOCAL,AF_FILE 本地通信(进程间通信)
AF_INET 基于32位IP地址通信,IPv4
AF_INET6 基于128位IP地址通信,IPv6
type:通信协议
SOCK_STREAM 数据流协议,TCP
SOCK_DGRAM 数据报协议,UDP
protocol:特别通信协议,给0即可
返回值:socket描述符
3.通信地址
注意:函数接口定义的是sockaddr,而实际提供的是sockaddr_un或sockaddr_in
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
};
struct sockaddr_un {
_SOCKADDR_COMMON (sun_);//地址类型,参看doaim
char sun_path[180];//socket文件的路径
}
struct sockaddr_in {
_SOCKADDR_COMMON (sun_);
in_port_t sin_port; //端口号 大端字节序
struct in_addr sin_addr;//ip地址,大端四字节整数
}
struct sockaddr {
in_addr_t s_addr;
};
4.绑定
socket描述符与物理通信载体(网卡/文件)绑定在一起
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
sockfd:socket描述符,socket函数的返回值
addr:通信地址结构体,实际给的是sockaddr_un或sockaddr_in,需要强制类型转换
addrlen:通信地址结构体类型的字节数,使用sizeof计算
5.连接
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
sockfd:socket描述符
addr:通信目标地址
addrlen:通信地址结构体类型的字节数,使用sizeof计算
返回值:在不同的编程模型下返回值意义不同,在本地通信返回加0,失败返回-1
6.数据接收与发送:read/write
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
recv/send与read/write功能一样,flags多了是否阻塞的功能,(0阻塞,1不阻塞)
7.关闭套接字:close
如果是网络通信,端口号并不会立即回收,大概会占用3分钟左右
8.字节序转换
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
功能:把32本机字节序转换成32位网络字节序
uint16_t htons(uint16_t hostshort);
功能:把16本机字节序转换成16位网络字节序
uint32_t ntohl(uint32_t netlong);
功能:把32网络字节序转换成32位本机字节序
uint16_t ntohs(uint16_t netshort);
功能:把16网络字节序转换成16位本机字节序
9.IP地址转换
int inet_aton(const char *cp, struct in_addr *inp);
功能:把点分十进制的ip地址(字符串)转换成32位无符号整数,使用结构指针获取
in_addr_t inet_addr(const char *cp);
功能:把点分十进制的ip地址(字符串)转换成32位无符号整数,使用返回值直接返回
char *inet_ntoa(struct in_addr in);
功能:把32位无符号整数转换成点分十进制的ip地址(字符串)
10.本地通信编程模型
进程A 进程B
创建套接字(AF_LOCAL) 创建套接字(AF_LOCAL)
准备地址(sockaddr_un) 准备地址(sockaddr_un)
绑定(自己的socket/地址) 连接(connect,连接进程A的地址)
接收数据 发送数据
关闭套接字 关闭套接字
二.基于TCP协议的C/S模型
int listen(int sockfd, int backlog);
功能:设置等待连接的最大数量
sockfd:被监听的socket的描述符
backlog:等待连接的最大数量(排队的数量)
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
功能:等待连接sockfd
addr:等待连接的地址
addrlen:设置连接地址结构体的长度
返回值:专门用于通信的描述符
编程模型:
Server Client
创建socket套接字 创建socket套接字
准备地址(sockaddr_in,本机地址) 准备地址(服务器地址)
绑定(bind) ......
监听(listen) ......
等待连接(accept,fork) 连接(connect)
接收请求read/recv 发送请求(write/send)
响应请求write/send 接收响应(read/recv)
关闭(close) 关闭(close)
三.基于UDP协议的C/S模型
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
功能:UDP协议专用的数据发送函数
sockfd:套接字描述符
buf:待发送的缓冲区首地址
len:待发送的数据字节数
flags:0阻塞,1不阻塞
dest_addr:目标计算机地址
addrlen:地址结构体的字节数
返回值:成功发送的字节数
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
功能:UDP协议专用的数据接收函数
sockfd:套接字描述符
buf:数据存储位置
len:最大接收字节数
flags:0阻塞,1不阻塞
src_addr:获取发送者的地址
addrlen:设置地址结构体的字节数
返回值:成功接收的字节数
编程模型:
Server Client
创建套接字(socket) 创建套接字(socket)
准备地址(本机地址sockaddr_in) 准备地址(目标机地址)
绑定(bind(sockfd+addr)) ......
接收请求(recvfrom) 发送请求(sendto)
响应请求(sendto) 接收响应(recvfrom)
关闭套接字(close) 关闭套接字(close)
注意:从服务器到客户端返回的路线是UDP协议自己设计的.