Socket套接字与TCP实现框架

文章目录

Socket套接字

latex 复制代码
┌─────────────────┐
│   应用程序      │
├─────────────────┤
│  Socket API     │ ← 网络编程接口
├─────────────────┤
│   传输层(TCP/UDP) │
├─────────────────┤
│   网络层(IP)     │
├─────────────────┤
│   链路层/物理层  │
└─────────────────┘
  • 套接字属于一种特殊的文件描述符
  • UNIX域套接字用于进程间通信

Scoket概念

  • 定义:应用层与TCP/IP协议族通信的中间软件抽象层,是一组API
  • 作用:网络通信的端点,包含IP地址 + 端口号 + 协议三元组
    • IP地址:标识计算机
    • 端口号:标识计算机当中的进程
    • 协议:指定数据传输的方式
  • 本质:特殊的文件描述符,可以通过文件I/O函数(read/write)操作

常见的网络编程接口

  • Berkeley Socket:UNIX/Linux标准,POSIX规范
  • Windows Socket (Winsock):Windows平台的socket实现
  • TLI (Transport Layer Interface):AT&T UNIX的传输层接口

Socket地址结构

通用地址结构(用于类型转换)

c 复制代码
#include <sys/socket.h>

// 通用地址结构体(所有专用结构体都要转换为这个类型)
struct sockaddr {
    sa_family_t sa_family;    // 地址族:AF_XXX
    char        sa_data[14];  // 地址数据
};
  • AF_UNIX:使用本地域套接字的地址结构,用于本地通信
  • AF_INET: 使用IPv4的通信地址结构
  • AF_INET6:使用IPv6的通信地址结构

IPv4专用地址结构(最常用)

c 复制代码
#include <netinet/in.h>

// IPv4地址结构体
struct sockaddr_in {
    sa_family_t    sin_family;   // 地址族:AF_INET
    in_port_t      sin_port;     // 端口号(网络字节序)
    struct in_addr sin_addr;     // IPv4地址
};

// IPv4地址(32位)
struct in_addr {
    uint32_t       s_addr;       // IPv4地址(网络字节序)
};

IPv6专用地址结构

c 复制代码
#include <netinet/in.h>

// IPv6地址结构体
struct sockaddr_in6 {
    sa_family_t     sin6_family;   // 地址族:AF_INET6
    in_port_t       sin6_port;     // 端口号(网络字节序)
    uint32_t        sin6_flowinfo; // IPv6流信息
    struct in6_addr sin6_addr;     // IPv6地址
    uint32_t        sin6_scope_id; // 作用域ID
};

// IPv6地址(128位)
struct in6_addr {
    unsigned char   s6_addr[16];   // IPv6地址
};

套接字类型

三种主要类型

类型 常量 协议 特点 适用场景
流式套接字 SOCK_STREAM TCP 可靠、面向连接、字节流 文件传输、HTTP、SSH
数据报套接字 SOCK_DGRAM UDP 不可靠、无连接、数据报 DNS、音视频流、实时游戏
原始套接字 SOCK_RAW 直接IP层 直接操作底层协议 网络工具开发(ping/traceroute)

选择原则

c 复制代码
// TCP套接字(嵌入式服务器常用)
int tcp_sock = socket(AF_INET, SOCK_STREAM, 0);

// UDP套接字(嵌入式传感器数据上报)
int udp_sock = socket(AF_INET, SOCK_DGRAM, 0);

// 原始套接字(网络诊断工具)
int raw_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

TCP通信实现框架

  • 通信之前,客户端和服务器端先创建套接字
  • 服务器端调用 bind,把端口号和本地 IP 地址填写到已创建的套接字中
  • 服务器端调用 listen(收听),把套接字设置为被动方式,以便随时接受客户的服务请求。UDP 服务器不使用 listen 系统调用
  • 服务器端调用 accept(接受),以便把远地客户进程发来的连接请求提取出来。UDP 服务器不使用 accept 系统调用
  • 客户端进程调用 connect,以便和远地服务器建立连接
  • 客户端和服务器在 TCP 连接上使用 write传送数据,使用 read接收数据
  • 客户端或服务器通信结束,调用 close 释放连接和撤销套接字

三次握手在框架中的体现

latex 复制代码
客户端               服务器端
  │                    │
  │      SYN=1         │
  ├───────────────────>│ socket() + bind() + listen()
  │                    │
  │   SYN=1, ACK=1     │
  │<───────────────────┤ accept()阻塞等待连接
  │                    │
  │      ACK=1         │
  ├───────────────────>│ accept()返回,连接建立
  │                    │
  │     数据交换        │
  │<──────────────────>│
相关推荐
旺仔.2911 小时前
Linux 信号详解
linux·运维·网络
平生幻2 小时前
TCP协议与UDP协议的区别
网络协议·tcp/ip·udp
源远流长jerry4 小时前
在 Ubuntu 22.04 上配置 Soft-RoCE 并运行 RDMA 测试程序
linux·服务器·网络·tcp/ip·ubuntu·架构·ip
虾..5 小时前
UDP协议
网络·网络协议·udp
w-w0w-w5 小时前
Unix网络编程
服务器·网络·unix
未知鱼6 小时前
Python安全开发之子域名扫描器(含详细注释)
网络·python·安全·web安全·网络安全
寂柒6 小时前
序列化与反序列化
linux·网络
志栋智能6 小时前
超自动化巡检:应对复杂IT环境的必然选择
运维·网络·安全·web安全·自动化
mldlds7 小时前
windows手动配置IP地址与DNS服务器以及netsh端口转发
服务器·windows·tcp/ip
上海云盾-小余7 小时前
云主机安全加固:从系统、网络到应用的零信任配置
网络·安全·php