基于socket网络编程技术 实现TCP、UDP协议流程详解

详细讲解一下TCP、UDP,以及使用到的参数讲解

目录

详细讲解一下TCP、UDP,以及使用到的参数讲解

1、TCP、UDP介绍

TCP协议

UDP协议

2、 socket接口简介

3、接口参数详解

2.1   创建套接字  socket()

2.2  绑定套接字与网络地址  bind()

 ①   IPv4 地址结构体

 ②   IPv6 地址结构体

③   UNIX 域地址结构体

2.3. 将待连接套接字设置为监听套接字,并设置最大同时接收连接请求个数  listen()

2.4  等待对端连接请求   accept()

2.5   连接对端监听套接字  connect()

2.6  断开本端连接套接字  

①  同时断开读端和写端  close(int fd)

 ② int shutdown(int sockfd, int how)

2.7  向 TCP 套接字发送数据  send()

2.8   向 UDP 套接字发送数据接口声明  sentdo()  

2.9   从 TCP 套接字接收数据

2.10    从 UDP 套接字接收数据   recvfrom()

2.11    多路复用   

 ①    select()

 ②    poll()

2.12   将文本地址转化为二进制地址  inet_pton()

2.13  将二进制地址转化为文本地址

2.14   字节序转换


1、TCP、UDP介绍

网络编辑是指对网络通信中的数据进行编辑、分析和调试的工作。TCP(Transmission Control Protocol)和UDP(User Datagram Protocol)是两种常见的网络传输协议,用于在计算机之间传输数据。

TCP协议

面向连接的协议、安全可靠(三次握手、四次挥手)、采用字节流(流式套接字)、传输文件、一对一、星型结构

 它使用三次握手建立连接,并且在传输过程中保证数据的完整性和顺序。TCP通过序列号和确认机制来确保数据的正确接收,同时还具备流量控制和拥塞控制的功能。

UDP协议

无连接协议、不可靠(数据包丢失)、采用数据报套接字,但是传输速度快、通讯成本低,并且不区分客户端与服务端、树型结构或者网状结构

UDP没有确认机制,因此无法保证数据的可靠性和顺序,但是由于没有建立连接的开销,传输效率较高,适用于实时性要求较高的应用场景,如音频和视频传输。应用:QQ客户端

2、 socket接口简介

socket(int domain, int type, int protocol)

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

listen(int sockfd, int backlog)

accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)  

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

close(int fd)

shutdown(int sockfd, int how)

send(int sockfd, const void *buf, size_t len, int flags)

recv(int sockfd, void *buf, size_t len, int flags) 

sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen)

  recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen)

3、接口参数详解

2.1   创建套接字  socket()

接口声明:int socket(int domain, int type, int protocol);

参数:

domain:域。

AF_INET/PF_INET: 网际协议

AF_UNIX/PF_UNIX:本地协议,可写成 AF_LOCAL/PF_LOCAL

type:类型。

SOCK_STREAM:流式套接字     TCP

SOCK_DGRAM:数据包套接字    UDP

protocol:协议。一般为 0

返回值:

成功:待连接套接字

失败:-1

备注:在网际协议中,选择流式套接字就代表 TCP 协议,选择数据包套接字就代表 UDP 协议,第三个参数protocol一般不用。

2.2  绑定套接字与网络地址  bind()

接口声明:int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

参数:

sockfd:待连接套接字

addr:包含本地地址(IP+PORT)的通用地址结构体的指针

addrlen:地址结构体大小

返回值:

成功:0

失败:-1

备注:

通用地址结构体的定义:

struct sockaddr

{

sa_family_t sa_family;

char sa_data[14];};

 ①   IPv4 地址结构体

特殊地址结构体 —— IPv4 地址结构体

struct sockaddr_in

{

u_short   sin_family; // 地址族

u_short   sin_port; // 端口,0-----1023, 1024-----5000,5000------65535

struct in_addr  sin_addr; // IPV4 地址

char sin_zero[8];

};

struct in_addr

{

in_addr_t s_addr; // 无符号 32 位网络地址sockaddr. sin_addr. s_addr = htons(192.168.124.195)

};

 ②   IPv6 地址结构体

特殊地址结构体 —— IPv6 地址结构体:

struct sockaddr_in6

{

u_short sin6_family; // 地址族

__be16 sin6_port; // 端口

__be32 sin6_flowinfo; // 流信息

struct in6_addr sin6_addr; // IPv6 地址

__u32 sin6_scope_id;

};

③   UNIX 域地址结构体

特殊地址结构体 ——UNIX 域地址结构体

struct sockaddr_un

{

u_short sun_family; // 地址族

char sun_path[108]; // 套接字文件路径

};

2.3. 将待连接套接字设置为监听套接字,并设置最大同时接收连接请求个数  listen()

接口声明:int listen(int sockfd, int backlog);

参数:

sockfd:待连接套接字

backlog最大同时接收连接请求个数

返回值:成功:0,并将 sockfd 设置为监听套接字

失败:-1

备注:

由于历史原因,各种系统对 backlog 的理解并不一致,以 LINUX 为例,监听端能同时接收的最大连接请求个数为 0+4

2.4  等待对端连接请求   accept()

接口声明:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

参数:

sockfd:监听套接字

addr:通用地址结构体,用以存储对端地址(IP+PORT)

addrlen:参数 addr 的存储区域大小

返回值

成功:已连接套接字(非负整数)

失败:-1

2.5   连接对端监听套接字  connect()

接口声明:int connect(int sockfd, const struct sockaddr *addr, socklen_t  addrlen);

参数:

sockfd:待连接套接字

addr:包含对端地址(IP+PORT)的通用地址结构体的指针

addrlen:地址结构体大小

返回值:

成功:0

失败:-1

2.6  断开本端连接套接字  

  同时断开读端和写端  close(int fd)

接口声明:int close(int fd);

参数:

fd:已连接套接字

返回值:成功:0

              失败:-1

备注:

同时断开读端和写端

  int shutdown(int sockfd, int how)

接口声明:int shutdown(int sockfd, int how);

参数:

sockfd:已连接套接字

how:断开方式。

SHUT_RD:关闭读端

SHUT_WR:关闭写端

SHUT_RDWR:同时关闭读写端

返回值:

成功:0

失败:-1

备注:

在只关闭一端的时候,另一端可以继续使用。

2.7  向 TCP 套接字发送数据  send()

接口声明:ssize_t send(int sockfd, const void *buf, size_t len, int flags);

参数:

sockfd已连接套接字

buf:即将被发送的数据

len:数据长度

flags:发送标志0

MSG_NOSIGNAL:当对端已关闭时,不产生 SIGPIPE 信号

MSG_OOB:发送紧急(带外)数据,只针对 TCP 连接

返回值:

成功:已发送字节数

失败:-1

备注:

flags 为 0 时,send 与 write 作用相同。

2.8   向 UDP 套接字发送数据接口声明  sentdo()  

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);

参数:

sockfd:UDP 套接字

buf:即将发送的数据

len数据长度

flags:发送标志,与函数 send 的 flags 完全一致

dest_addr对端网络地址

addr_len地址长度

返回值:

成功:已发送字节数

失败:-1

备注:

当 dest_addr 为 NULL,addrlen 为 0 时,sendto 与 send 作用一致

2.9   从 TCP 套接字接收数据

接口声明: ssize_t recv(int sockfd, void *buf, size_t len, int flags);

参数:

sockfd:已连接套接字

buf存储数据缓冲区

len缓冲区大小

flags:接收标志 0阻塞等待

MSG_OOB:接收紧急(带外)数据

返回值:

成功:已接收字节数

失败:-1

备注:

flags 为 0 时,recv 与 read 作用相同。阻塞等待

2.10    从 UDP 套接字接收数据   recvfrom()

接口声明:ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);

参数:

sockfd:UDP 套接字

buf:储存数据缓冲区

len:缓冲区大小

flags:接收标志,与函数 send 的 flags 完全一致

src_addr:对端网络地址

addrlen:地址长度

返回值:

成功:已接收字节数

失败:-1

2.11    多路复用   

     select()

接口声明:int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

参数:

nfds:所有正在监测的套接字的最大值加 1

readfds:读就绪文件描述符集合

writefds:写就绪文件描述符集合

exceptfds:异常就绪文件描述符集合

timeout:超时控制

返回值:

成功:就绪文件描述符总数(当超时返回时为 0

失败:-1

备注:

文件描述符集合操作函数:

void FD_CLR(int fd, fd_set *set);

int FD_ISSET(int fd, fd_set *set);

void FD_SET(int fd, fd_set *set);

void FD_ZERO(fd_set *set);

     poll()

接口声明:int poll(struct pollfd *fds, nfds_t nfds, int timeout);

参数:

fds:监测文件描述符结构体数组

nfds:数组元素个数

timeout:超时控制

备注:

struct pollfd

{

int fd; // 监测的文件描述符

short events; // 监测的状态

short revents; // 实际发生的状态

};

其中,监测的状态可以用以下宏来标记:

POLLIN:读就绪

POLLPRI:紧急数据读就绪

POLLOUT:写就绪

POLLRDHUP:对端已关闭或已关闭写端(仅对流式套接字有效)

POLLERR:发生错误

2.12   将文本地址转化为二进制地址  inet_pton()

Char *src=”192.168.124.115”

接口声明:int inet_pton(int af, const char *src, void *dst);

参数:

af:地址族

AF_INET:IPv4 地址

AF_INET6:IPv6 地址

src指向“点分式”IPv4 或 IPv6 地址的指针,例如“192.168.1.100”

dst:类型为 struct in_addr *或者 struct in6_addr *的指针返回值:

成功:1

失败:0 代表地址与地址族不匹配,-1 代表地址不合法

2.13  将二进制地址转化为文本地址

接口声明:const char *inet_ntop(int af, const void *src, char *dst, socklen_t

size);

参数:

af:地址族。

2.14   字节序转换

接口声明:

uint32_t htonl(uint32_t hostlong);

uint16_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t netlong);

uint16_t ntohs(uint16_t netshort);

参数:

hostlong: 主机字节序的长整型数据

hostshort: 主机字节序的短整型数据

netlong: 网络字节序的长整型数据

netshort: 网络字节序的短整型数据

返回值:

对应的字节序数据

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值