TCP/UDP协议操作流程及接口介绍

传输层的协议:TCP/UDP协议

TCP:传输控制协议,面向连接,可靠传输,面向字节流;

——应用于对安全性要求大于实时性的场景(文件传输等);

UDP:用户数据报协议,无连接,不可靠,面向数据报;

——应用于对实时性性要求大于安全性的场景(视频、音频等);

UDP操作流程:

服务端:

①创建套接字:

在内核中创建socket结构体,将进程与网卡关联起来;

②为套接字绑定地址信息:

给创建的socket结构体描述源端地址信息;

③接收数据:

从socket接收缓冲区中取出数据;

④向服务器发送数据:

将要发送的数据放入发送缓冲区;

⑤关闭套接字;

客户端:

①创建套接字;

②为套接字绑定地址信息:

客户端不推荐主动绑定地址,绑定好之后程序只能启动一个且客户端不需要使用固定地址;

③向服务器发送数据:

发送数据之前若socket没有绑定指定地址,则系统会自动选择合适的地址信息进行绑定;

④接收数据;

⑤关闭套接字;

TCP操作流程

监听套接字(只用于处理新的连接请求)& 通信套接字(只用来通信);

需要先连接再通信所以不存在广播的操作;

服务端

①创建套接字:

在内核中创建socket结构体,将进程与网卡关联起来;

②为套接字绑定地址信息:

给创建的socket结构体描述源端地址信息;

③开始监听:

告诉服务器,当前socket可以处理链接请求了(监听套接字转换为listen状态);

如果有客户端发送连接请求过来,服务的会为其创建一个新的socket专门用于与指定客户端通信(该套接字为通信套接字,状态为established—就绪状态);

④ 获取新建连接:

从已完成连接的队列中取出一个新建套接字的描述符,该描述符对应了指定的socket与指定的客户端通信;

⑤收发数据;

⑥关闭套接字;

客户端

①创建套接字;

②为套接字绑定地址信息(不推荐);

③向服务器发起连接:

连接过后客户端tcp也会保存完整的五元组;

④收发数据;

⑤关闭套接字;

接口介绍

#include<sys/socket.h>
#include<netinet/in.h>

创建套接字

int socket(int domain, int type, int protocol);
//domain:地址域类型——AF_INET & AF_INET6;
//type:套接字类型——SOCK_STREAM & SOCK_DGRAM;
//protocol:协议类型——IPPROTO_TCP & IPPROTO_UDP (可以默认给0);
//返回值:成功返回一个套接字描述符,失败返沪-1;

绑定地址信息

int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);

//sockfd:创建套接字返回的描述符;
//addr:要绑定的地址信息(这是一个通用描述,根据前两个字节的内容使用统一的接口绑定不同的地址结构,还有端口信息、IP地址,IPV4为struct sockaddr_in, IPV6为struct sockaddr_in6);
//addrlen:地址信息长度,防止访问越界;

eg:
struct sockaddr_in addr;
addr.sin_family = AF_INET;//前两个字节代表IPV4地址结构,IPV6为AF_INET6
addr.sin_port = htons(9000);//端口信息,需要转化为网络字节序
addr.sin_addr.s_addr = inet_addr("192.168.2.2");//本机有的IP地址,inet_addr可将点分十进制转化为长整型数字
bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in));

关闭套接字

int close(int sockfd);

//实际情况下在TCP通信中,监听套接字基本不关闭,一般只关闭通信套接字

UDP发送数据

ssize_t sendto(int sockfd,char* data,int data_len,int flag,struct socket* dest_addr,socket_t addr_len);

//sockfd:套接字描述符
//data:要发送的数据首地址
//data_len:要发送的数据长度
//flag:选项标志,默认为0----表示当前操作是阻塞操作
//dest_addr:对端地址信息
//addr_len:地址信息结构长度
//返回值:成功返回实际发送数据长度,失败返回-1

UDP接收数据

ssize_t recvfrom(int sockfd,void* buf,size_t len,int flag,struct socket* src_addr,socket_t *addrlen);

//sockfd:套接字描述符
//buf:一块空间首地址,用于存放从内核获取到的数据
//len:要获取的数据长度
//flag:选项标志,默认为0----表示当前操作是阻塞操作
//src_addr:源端地址信息
//*addrlen:这是输入输出型参数,指定想要多长地址,返回实际长度地址

TCP客户端向服务端发起连接

int connect(int socket, struct sockaddr* srvaddr, socklen_t addrlen);
//srvaddr:服务器地址信息
//返回值:成功返回0,失败返回-1;

TCP服务器监听客户端发出的连接(参数会被问)

int listen(int socket, int backlog);
//backlog:同一时间最大并发连接数,当socket连接队列被放满之后,如果有新的连接请求到来则丢弃,以此限制同一时间所处理的新建连接请求数量;

//该操作将服务器端状态置为listen;

TCP获取新建连接

从内核的已完成连接的socket队列中取出一个已完成连接的socket,并返回描述符;

int accept(int listen_socket, struct sockaddr* addr, socklen_t *addrlen);
//listen_socket:监听套接字,决定了获取的是哪个套接字的新建连接;
//addr:一个地址结构的空间首地址,用于接收新连接的客户端地址信息;
//*addr:用于指定想要获取的地址长度以及返回的实际长度;
//返回值:成功返回新建连接的描述符,失败返回-1;

TCP发送数据

ssize_t send(int sockfd, char *buf, int len, int flag);
//sockfd:新建套接字描述符;
//data:要发送的数据的空间首地址;
//len:要发送的数据长度;
//flag:0,默认阻塞接收;
//返回值:成功返回实际发送的数据长度,出错返回-1,

TCP接收数据

TCP的通信套接字保存了完整的五元组

ssize_t recv(int sockfd, char *buf, int len, int flag);
//sockfd:新建套接字描述符;
//buf:空间首地址用于存放接收的数据;
//len:要获取的数据长度;
//flag:0,默认阻塞接收;
//返回值:成功返回实际获取到的数据长度,出错返回-1,连接断开返回0;

猜你喜欢

转载自blog.csdn.net/SFDWU3QVG/article/details/126819085
今日推荐