socket网络编程
套接字函数
创建套接字
// 创建一个套接字
int socket(int domain, int type, int protocol);
参数:
- domain: 使用的地址族协议
AF_INET: 使用IPv4格式的ip地址
AF_INET6: 使用IPv6格式的ip地址 - type:
SOCK_STREAM: 使用流式的传输协议
SOCK_DGRAM: 使用报式(报文)的传输协议 - protocol: 一般写0即可, 使用默认的协议
SOCK_STREAM: 流式传输默认使用的是tcp
SOCK_DGRAM: 报式传输默认使用的udp
返回值:
- 成功: 可用于套接字通信的文件描述符
- 失败: -1
服务端函数
// 将文件描述符和本地的IP与端口进行绑定
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
- sockfd: 监听的文件描述符, 通过socket()调用得到的返回值
- addr: 传入参数, 要绑定的IP和端口信息需要初始化到这个结构体中,IP和端口要转换为网络字节序
- addrlen: 参数addr指向的内存大小, sizeof(struct sockaddr)
返回值:
- 成功返回0
- 失败返回-1
// 给监听的套接字设置监听
int listen(int sockfd, int backlog);
参数:
- sockfd: 文件描述符, 可以通过调用socket()得到,在监听之前必须要绑定 bind()
- backlog: 同时能处理的最大连接要求,最大值为128
返回值:
- 成功返回0
- 调用失败返回 -1
// 等待并接受客户端的连接请求, 建立新的连接, 会得到一个新的文件描述符(通信的)
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
参数:
- sockfd: 监听的文件描述符
- addr: 传出参数, 里边存储了建立连接的客户端的地址信息
- addrlen: 传入传出参数,用于存储addr指向的内存大小
返回值:
- 函数调用成功,得到一个文件描述符, 用于和建立连接的这个客户端通信
- 调用失败返回 -1
这个函数是一个阻塞函数,当没有新的客户端连接请求的时候,该函数阻塞;当检测到有新的客户端连接请求时,阻塞解除,新连接就建立了,得到的返回值也是一个文件描述符,基于这个文件描述符就可以和客户端通信了。
客户端函数
// 成功连接服务器之后, 客户端会自动随机绑定一个端口
// 服务器端调用accept()的函数, 第二个参数存储的就是客户端的IP和端口信息
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
参数:
- sockfd: 通信的文件描述符, 通过调用socket()函数就得到了
- addr: 存储了要连接的服务器端的地址信息: iP 和 端口,这个IP和端口也需要转换为大端然后再赋值
- addrlen: addr指针指向的内存的大小 sizeof(struct sockaddr)
返回值:
- 连接成功返回0
- 连接失败返回-1
通信函数
// 接收数据
ssize_t read(int sockfd, void *buf, size_t size);
ssize_t recv(int sockfd, void *buf, size_t size, int flags);
参数:
- sockfd: 用于通信的文件描述符, accept() 函数的返回值
- buf: 指向一块有效内存, 用于存储接收是数据
- size: 参数buf指向的内存的容量
- flags: 特殊的属性, 一般不使用, 指定为 0
返回值: - 大于0:实际接收的字节数
- 等于0:对方断开了连接
- -1:接收数据失败了
如果连接没有断开,接收端接收不到数据,接收数据的函数会阻塞等待数据到达,数据到达后函数解除阻塞,开始接收数据,当发送端断开连接,接收端无法接收到任何数据,但是这时候就不会阻塞了,函数直接返回0。
// 发送数据的函数
ssize_t write(int fd, const void *buf, size_t len);
ssize_t send(int fd, const void *buf, size_t len, int flags);
参数:
- fd: 通信的文件描述符, accept() 函数的返回值
- buf: 传入参数, 要发送的字符串
- len: 要发送的字符串的长度
- flags: 特殊的属性, 一般不使用, 指定为 0
返回值:
- 大于0:实际发送的字节数,和参数len是相等的
- -1:发送数据失败了
TCP通信流程

文件描述符的作用
- 服务器端有两个文件描述符,一个用于监听客户端请求,一个用于和客户端通信
- 客户端只有一个文件描述符,用于和服务端通信
- 每个fd对应两个缓冲区,socket就是从fd对应的缓冲区中读写数据的
![在这里插入图片描述]()
所以,send()函数实际上就是将数据从用户空间拷贝到内核空间中fd对应的缓冲区
字节序
为了保证数据传输的字节序,规定网络传输中都使用大端模式传输,这样主机不管是大端还是小端,从网络中获取的数据都是大端的,之后按照自己的模式做转换即可。
详细讲解:套接字-socket

浙公网安备 33010602011771号