***************************************************************************
***************************************************************************
tcp重点:接收发送文件一定要用accept返回的套接字!!!!
对端的地址同时被accept存放在定义好的结构体
收发使用: recv()和 send()
***************************************************************************
udp重点:网络传输不必双向绑定,本地(AF_UNIX)传输要双向绑定
收发使用:
recvfrom():后面两个参数是接受并保存对端的地址
sendto():后面两个参数是发到到的对端的地址
***************************************************************************
********************************OSI模型*******************************
物理层 --->物理层负责最后将信息编码成电流脉冲信号(0和1)用于网上传输
数据链路层 --->数据链路层通过物理网络链路提供数据传输。不同的数据链路层定义了不同的网络和协议特征,
其中包括物理编址、网络拓扑结构、错误校验、数据帧序列以及流控;
可以简单的理解为:规定了0和1的分包形式,确定了网络数据包的形式 打包数据整理 mac地址
网络层 --->网络层负责在源和终点之间建立连接。可以理解为,此处需要确定计算机的位置。怎么确定?IPv4,IPv6!
传输层 --->传输层向高层提供可靠的端到端的网络数据流服务。可以理解为:每一个应用程序都会在网卡注册一个端口号,
该层就是端口与端口的通信,常用的(TCP/IP)协议。
应用层 --->OSI的应用层协议包括文件的传输、访问及管理协议(FTAM),
以及文件虚拟终端协议(VIP)和公用管理系统信息(CMIP)等;规定数据的传输协议。
*********************************IP地址*********************************
IP地址分为二进制表示法和点分十进制表示法,IP地址长度是4字节,4个8位域组成
端口:用来区分不同应用程序
小于1024的端口号被系统标准服务程序占用,用户应用程序可以使用1024以上的端口号
Web服务器的端口号是80,电子邮件SMTP的端口号是25,文件传输FTP的端口号为20和21等
***************************API接口 字节转换函数**************************************
htons() --->表示对于 short 类型的变量,从host主机字节序转换为网络字节序
htonl() --->表示对于 long 类型的变量,从network主机字节序转换为网络字节序
ntohs() --->表示对于 short 类型的变量,从网络字节序转换为主机字节序
ntohl() --->表示对于 long 类型的变量,从网络字节序转换为主机字节序
#include <arpa/inet.h>
int inet_pton(int family, const char *strptr, void *addrptr);
参数
family --->协议族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET
strptr --->点分十进制数串
addrptr --->32 位无符号整数的地址
返回值
成功 --->1
失败 --->-1
功能
将点分十进制数串转换成 32 位无符号整数
const char *inet_ntop( int family, const void *addrptr, char *strptr, size_t len );
参数
family --->协议族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET
addrptr --->32 位无符号整数
strptr --->点分十进制数串
len --->strptr 缓存区长度
len 的宏定义
#define INET_ADDRSTRLEN 16 // for ipv4
#define INET6_ADDRSTRLEN 46 // for ipv6
返回值
成功 --->则返回字符串的首地址
失败 --->返回 NULL
功能
将 32 位无符号整数转换成点分十进制数串
******************************TCP通信************************************
客户端步骤:
1、建立套接字 --->socket()
2、连接服务器 --->connect()
3、接收和发送数据 --->send()/recv()
4、关闭套接字 --->close()
服务端步骤:
1、建立套接字 --->socket()
2、套接字与端口的绑定 --->bind()
3、设置服务器的监听连接 --->listen()
4、接收客户端连接 --->accept()
5、接收和发送数据 --->send()/recv()
6、关闭套接字 --->close()
************ ****** ****** ******* ***** *******************
int socket(int domain,int type,int protocol);
domain 创建套接字所使用的协议族,在通信中必须采用对应的地址
AF_INET(IPV4 协议)
AF_INET6(IPV6协议)
AF_UNIX 只在本机内通信的套接字
type:指定socket类型
SOCK_STREAM:创建TCP流套接字。提供面向连接的稳定数据传输
SOCK_DGRAM:创建UDP数据报套接字。使用不连续不可靠的数据包连接。
SOCK_RAW:创建原始套接字。提供原始网络协议存取。
SOCK_PACKET:与网络驱动程序直接通信。
SOCK_SEQPACKET:提供连续可靠的数据包连接。
SOCK_RDM: 提供可靠的数据包连接
protocol:指定协议,通常设为0
返回值:成功:套接字 失败:-1
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd --->socket()返回的描述字
addr --->所要连接的服务器地址结构
addrlen --->服务器地址结构体的长度
返回值:成功:0 失败:-1
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
sockfd --->socket()返回的描述字
addr --->指向要绑定给sockfd的协议地址(服务器的地址结构体)
addrlen --->服务器的地址结构体的长度
返回值:成功:0 失败:-1
int listen(int sockfd,int backlog);
socket默认是一个主动类型的,listen函数将socket变为被动类型
sockfd --->socket监听套接字
backlog --->监听的客户端的数量,默认是20个
返回值:成功:0 失败:-1
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd --->socket监听套接字
addr --->用于存放接收到的客户端套接字地址结构,不需要可设为NULL
addrlen --->客户端套接字地址结构体的长度,不需要可设为NULL
accept默认会阻塞进程,直到有一个客户连接建立后返回连接套接字。
注意:
一个服务器通常通常仅仅只创建一个监听socket描述字,它在该服务器的生命周期内一直存在。
内核为每个由服务器进程接受的客户连接创建了一个已连接socket描述字,
当服务器完成了对某个客户的服务,相应的已连接socket描述字就被关闭。
返回值:成功:0 失败:-1
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t recv(int sockfd, const void *buf, size_t len, int flags);
sockfd --->已经建立连接的套接字
buf --->发送/接收数据缓冲区地址
len --->发送/接收长度
flags --->为控制选项,一般设为0或取以下值:
send()
MSG_OOB:在指定套接字上发送外带数据,该类型的套接字必须支持外带数据。
MSG_DONTROUTE:通过最直接的路径发送数据,而忽略下层协议的路由设置。
最后一个参数为0时,可以使用write代替不,能使用TCP协议发送0长度的数据包。
!!!!如果数据没有发送成功,内核会自动重发
recv()
MSG_OOB:请求接受外带数据
MSG_PEEK:只查看数据而不读出
MSG_WAITALL:只在接受缓冲区满时才返回
!!!!!如果没有收到数据则会阻塞等待,直到有数据到来
返回值:成功:成功接收的字节数 失败:-1
*****************************UDP通信**********************************
通常音频、视频和普通数据在传送时使用 UDP 较多,
因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
比如我们聊天用的 ICQ 和 QQ 就是使用的 UDP 协议
客户端步骤:
1、建立套接字 --->socket()
2、接收和发送数据 --->sendto()/recvfrom()
3、关闭套接字 --->close()
服务端步骤:
1、建立套接字 --->socket()
2、套接字与端口的绑定 --->bind()
3、接收和发送数据 --->sendto()/recvfrom()
4、关闭套接字 --->close()
************ ****** ****** ******* ***** *******************
ssize_t sendto(int sockfd,const void *buf,size_t len,int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
sockfd --->套接字
buf: --->发送数据缓冲区
len --->发送数据缓冲区的大小
flags --->一般为 0
dest_addr --->指向目的主机地址结构体的指针
addrlen --->dest_addr所指向内容的长度
返回值: 成功:发送数据的长度 失败: -1
功能: 向dest_addr结构体指针中指定的ip发送UDP数据
ssize_t recvfrom(int sockfd,void *buf,size_t len,int flags,struct sockaddr *src_addr,socklen_t *addrlen);
sockfd --->套接字
buf: --->接收数据缓冲区
len --->接收数据缓冲区的大小
flags --->套接字标志,一般为 0
src_addr --->源地址结构体的指针
addrlen --->src_addr所指向内容的长度
返回值: 成功:接收数据的长度 失败: -1
功能:接收UDP数据,并将源地址信息保存在from指向的结构中,
默认的情况下,如果没有接收到数据,这个函数会阻塞,直到有数据到来。
***********************************状态总结**********************************
状 态 描 述
CLOSED 关闭状态,没有连接活动或正在进行
LISTEN 监听状态,服务器正在等待连接进入
SYN_RCVD 收到一个连接请求,尚未确认
SYN_SENT 已经发出连接请求,等待确认
ESTABLISHED 连接建立,正常数据传输状态
FIN_WAIT_1 (主动关闭)已经发送关闭请求,等待确认
FIN_WAIT_2 (主动关闭)收到对方关闭确认,等待对方关闭请求
TIMED_WAIT 完成双向关闭,等待所有分组死掉
CLOSING 双方同时尝试关闭,等待对方确认
CLOSE_WAIT (被动关闭)收到对方关闭请求,已经确认
LAST_ACK (被动关闭)等待最后一个关闭确认,并等待所有分组死掉
*****************************UDP本地通信AF_UNIX**********************************
客户端步骤:
建立套接字 --->socket()
配置接收(自己)地址->绑定套接字 bind()
配置发送(对方)地址
接收和发送数据 --->sendto()/recvfrom()
关闭套接字 --->close()
服务端步骤:
建立套接字 --->socket()
配置接收(自己)地址->绑定套接字 bind()
配置发送(对方)地址
接收和发送数据 --->sendto()/recvfrom()
关闭套接字 --->close()
******* **********结构体******* *********
struct sockaddr_un
*****************************************************************************************
套接字函数使用
最新推荐文章于 2024-08-09 17:50:34 发布