目录
相同点:
同属于传输层协议
不同点:
TCP:流式套接字,面向连接的,可靠的通信
UDP:数据报套接字,无连接的,不可靠的通信
1. TCP
全双工通信、面向连接、可靠
TCP(即传输控制协议):是一种面向连接的传输层协议,它能提供高可靠性通信(即数据无误、数据无丢失、数据无失序、数据无重复到达的通信)。
高可靠原因: 1. 三次握手、四次挥手
2. 序列号和应答机制
3. 超时,错误重传机制
4. 拥塞控制、流量控制(滑动窗口)
适用场景
适合于对传输质量要求较高的通信
在需要可靠数据传输的场合,通常使用TCP协议
MSN/QQ等即时通讯软件的用户登录账户管理相关的功能通常采用TCP协议
2. UDP
全双工通信、面向无连接、不可靠
UDP(User Datagram Protocol)用户数据报协议,是不可靠的无连接的协议。在数据发送前,因为不需要进行连接,所以可以进行高效率的数据传输。
适用场景
发送小尺寸数据(如对DNS服务器进行IP地址查询时)
适合于广播/组播式通信中。
MSN/QQ/Skype等即时通讯软件的点对点文本通讯以及音视频通讯通常采用UDP协议
3. TCP连接流程
服务器:
1.创建流式套接字(socket())------------------------> 有手机
2.指定本地的网络信息(struct sockaddr_in)----------> 有号码
3.绑定套接字(bind())------------------------------>绑定电话
4.监听套接字(listen())---------------------------->待机
5.链接客户端的请求(accept())---------------------->接电话
6.接收/发送数据(recv()/send())-------------------->通话
7.关闭套接字(close())----------------------------->挂机
客户端:
1.创建流式套接字(socket())----------------------->有手机
2.指定服务器的网络信息(struct sockaddr_in)------->有对方号码
3.请求链接服务器(connect())---------------------->打电话
4.发送/接收数据(send()/recv())------------------->通话
5.关闭套接字(close())--------------------------- >挂机
4. UDP连接流程
服务器:
1. 创建数据报套接字 socket
2. 填充网络信息
3. 绑定 bind
4. 发送接收消息 sendto/recvfrom
5. 关闭套接字 close
客户端:
1. 创建数据报套接字 socket
2. 指定网络(服务器)信息
3. 发送接收消息 sendto/recvfrom
4. 关闭套接字 close
5.函数接口
5.1 socket
头文件:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
int socket(int domain, int type, int protocol);
功能:创建套接字
参数:
domain:协议族
AF_UNIX, AF_LOCAL 本地通信
AF_INET ipv4
AF_INET6 ipv6
type:套接字类型
SOCK_STREAM:流式套接字
SOCK_DGRAM:数据报套接字
SOCK_RAW:原始套接字
protocol:协议 - 填0 自动匹配底层 ,根据type系统默认自动帮助匹配对应协议
传输层:IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP
网络层:htons(ETH_P_IP|ETH_P_ARP|ETH_P_ALL)
返回值:
成功 文件描述符
失败 -1,更新errno
5.2 bind
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:绑定服务器地址(只允许绑定本机器的网卡地址)
参数:
socket:套接字描述符
addr:代表的是本机的IP地址和端口,用于通信结构体 (提供的是通用结构体,需要根据选择通信方式,填充对应结构体-通信当时socket第一个参数确定)
addrlen:地址的长度,结构体大小
返回值:成功 0 失败-1,更新errno
通用结构体:
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
ipv4通信结构体:
struct sockaddr_in {
sa_family_t sin_family;
in_port_t sin_port;
struct in_addr sin_addr;
};
struct in_addr {
uint32_t s_addr;
};
本地通信结构体:
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[108]; /* pathname */
};
5.3 listen
int listen(int sockfd, int backlog);
功能:监听socket连接,将主动套接字变为被动套接字
参数:
sockfd:套接字
backlog:同时响应客户端请求链接的最大个数,不能写0.
不同平台可同时链接的数不同,一般写6-8个
(队列1:保存正在连接)
(队列2,连接上的客户端)
返回值:成功 0 失败-1,更新errno
5.4 accept
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
accept(sockfd,NULL,NULL);
功能:接收一个客户端的连接,它是一个阻塞接口,直到有客户端连入的时候,会退出阻塞.如果有客户端连接,则accept()函数返回,返回一个用于通信的套接字文件;
参数:
Sockfd :套接字
addr: 链接客户端的ip和端口号
如果不需要关心具体是哪一个客户端,那么可以填NULL;
addrlen:结构体的大小
如果不需要关心具体是哪一个客户端,那么可以填NULL;
返回值:
成功:文件描述符; //用于通信
失败:-1,更新errno
5.5 connect
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
作用:客户端的socket连接服务器
参数:
sockfd: socket接口返回的文件描述符
addr: 服务器的地址,帮助文档的接收在bind里,
addrlen: 地址的长度,结构体大小
返回值:0 -1
第二个参数struct sockaddr *addr的解释
struct sockaddr {
sa_family_t sa_family; //同socket接口的domain参数
char sa_data[14];
}
上面的接口类型只是socket接口族为了兼容多种协议,定义的一个通用的结构体,实际编程的时候,
需要你根据具体的协议类型,使用具体协议的结构体,对于ipv4来讲,需要看ip的第7个手册(man 7 ip)
就能得到下面这个地址
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET */
in_port_t sin_port; /* 端口:网络字节序 */
struct in_addr sin_addr; /* IP地址:网络字节序 */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* ip地址:网络字节序 */
};
5.6 recv/send
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
作用:接收网络的数据
参数:
sockfd:文件描述符
buf:数据的存放缓冲区
len:buf缓冲区的最大长度
flags:默认填0 阻塞接收
返回值:
成功会返回实际接收到的字节个数
失败返回-1
如果返回0的话,代表对端退出
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
作用:发送网络的数据
参数:
sockfd:文件描述符
buf:数据的发送缓冲区
len:发的缓冲区大小
flags:默认填0
返回值:
成功会返回实际发送成功的字节个数
失败返回-1
5.7 recvfrom/sendto
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:发送端的网络信息结构体的大小的指针
返回值:
成功接收的字节个数
失败:-1
0:客户端退出
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
src_addr:接收端的网络信息结构体的指针
addrlen:接收端的网络信息结构体的大小
返回值:
成功发送的字节个数
失败:-1