socket

网络编程套接字
  • IP地址:

    1. IPV4: uint32_t ~ 43亿左右 — 在网络上唯一标识一台主机
    2. IPV6: uchar ip[16] — 因为不向前兼容ipv4因此没有推广起来
    3. DHCP: 动态地址分配技术 — 谁上网给谁分配IP地址
    4. NAT: 地址替换 — 实现多人使用同一地址上网

    因为数字不好记忆,所以使用点分十进制形式展示ip地址
    每条数据中都会包含:src ip(源ip),dest ip(目的ip)

  • port端口: uint16_t – 0~65535 - 0~1025 不推荐使用 - 在主机上标识一个进程
    网络程序分了客户端和服务端,主动发起请求的一方是客户端,被动在指定位置接收请求的一方是服务端(服务端被动的接收地址必须是固定不变的)
    一个端口只能被一个进程占用,一个进程可以使用多个端口
    每条数据中都会包含:src port(源端口),dest port(目的端口)
    每条数据中都包含:sip sport dip dport proto (五元组 标识一条通信)

  • 网络字节序:

  1. 字节序: cpu在内存中对数据进行存取的顺序
  2. 大端字节序: 低地址存高位
  3. 小端字节序: 低地址存低位
  4. 主机字节序: 当前计算机的字节序 — 大小端取决于cpu架构
    X86_64 — 小端, MIPS — 大端
    如果通信两端主机字节序不同,就会造成数据二义(针对存储大于一个字节数据(short int long float double))
    解决方案: 订立标准 — 网络字节序(通信双方都是用网络字节序)— 大端字节序
传输层协议:TCP/UDP
  • TCP: 传输控制协议 — 面向连接,可靠传输,面向字节流
    面向连接:通信之前,先建立连接,确保双方在线
    可靠传输:在网络正常的情况下,数据不会丢失
    面向字节流:传输灵活,但是存在TCP粘包问题
    使用场景:对数据安全要求高,传输文件 — 保证数据安全
    TCP为了实现可靠传输牺牲了部分传输性能
  • UDP: 用户数据报协议 — 无连接,不可靠,面向数据报
    面向数据报:每条数据有长度标识,整条发,整条收;传输不够灵活,但是不会存在粘包问题
    使用场景:对数据实时要求高,传输视频 — 保证传输速度
UDP:(实时性)
客户端服务端
1.创建套接字1.创建套接字,通过套接字使进程与网卡建立联系,创建struct socket
2.为套接字绑定地址信息,通常客户端不推荐用户手动绑定地址信息2.为套接字绑定地址信息(ip+port)
3.发送数据(如果socket还没有绑定地址,操作系统会选择一个合适的地址端口进行绑定)3.接收数据
4.接收数据4.发送数据
5.关闭套接字5.关闭套接字
  1. 创建套接字
    int socket(int domain, int type, int protocol);
    domain: 地址域
    AF_INET: IPV4网络协议地址域
    type: 套接字类型
    SOCK_STREAM 流式套接字,默认协议TCP,不支持UDP
    SOCK_DGRAM 数据报套接字,默认协议UDP,不支持TCP
    protocol: 协议类型
    0: 使用套接字默认协议
    6/IPPROTO_TCP — tcp协议
    17/IPPROTO_UDP — udp协议
    返回值: 套接字操作句柄 — 文件描述符, 失败: -1
  2. 为套接字绑定地址 — bind()
    int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
    sockfd: 创建套接字返回的描述符
    addr: 地址信息
    addrlen: 地址信息长度
    返回值: 0, 失败: -1
  3. 接收数据 — recvfrom
    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr * saddr, socklen_t *addrlen);
    sockfd: 操作句柄,套接字描述符
    buf: 用buf存储接收的数据
    len: 想要接收的数据长度
    flags: 0 — 默认阻塞接收
    saddr: 发送端的地址信息
    addrlen: 地址信息长度(输入输出型参数)不但要指定想要接收多长还要保存实际接收了多长
    返回值: 实际接收的数据长度 , 失败:-1
  4. 发送数据 — sendto
    ssize_t sendto(int sockfd, void *buf, size_t len, int flags, struct sockaddr *daddr, socklen_t addrlen);
    sockfd: 套接字描述符
    buf: 要发送的数据
    len: 要发送的数据长度
    flags: 0 — 默认阻塞发送
    daddr: 目的段地址信息 — 标识数据要发送到哪里去
    addrlen: 地址信息长度
    返回值: 实际发送的数据长度 , 失败: -1
  5. 关闭套接字 — close
    int close(int fd);

TCP:(安全性)

客户端服务端
1.创建套接字1.创建套接字
2.不推荐手动绑定地址2.绑定地址信息
3.向服务端发起连接请求 connect(sockfd, srvaddr, len)3.开始监听:告诉系统可以接收客户端的连接请求
4.发送数据 send(sockfd, data, len, flag)4.获取已经连接成功的客户端新建socket
5.接收数据 recv(sockfd, buf, len, flag)__
6.关闭套接字 close(fd)__

在这里插入图片描述

  • 如何快速判断连接是否已经断开:
    原理:
    tcp的连接管理中,内建有保活机制;
    当长时间没有数据往来的时候,每隔一段时间都会向对方发送一个保活探测包,要求对方回复,当多次发送的保活探测包都没有响应,则认为连接断开;
    若连接断开,则recv会返回0;send会触发异常SIGPIPE(导致进程退出)
    recv返回0,不是没有数据的意思,而指的是连接断开
  • 因为TCP面向字节流,有可能接收到半条数据,因此一定要对返回值进行判断,判断是否数据已经完全接收或完全发送
  • 基本的tcp服务端程序只能与一个客户端通信一次,无法实现同时与多个客户端多次通信
  • 因为不知道客户端(连接请求+数据)什么时候来,因此写死的程序很容易造成阻塞
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值