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()返回,连接建立
  │                    │
  │     数据交换        │
  │<──────────────────>│
相关推荐
Bat U2 分钟前
JavaEE|网络原理TCP/IP
网络·网络协议·tcp/ip
智慧光迅AINOPOL4 分钟前
OLT有哪些形态:框式、盒式,模块型,分别应用哪些场景?
网络·智能路由器
不仙52020 分钟前
Rocky Linux 8.10 TigerVNC 安装配置指南
linux·服务器·网络
冰冰的米咖21 分钟前
20260521网络配置-NAT Server实现外网访问内网服务
网络·网络协议·智能路由器
HMS工业网络27 分钟前
Cosy通过USB连接PLC时如何排查USB over IP故障
网络·网络协议·tcp/ip
小船跨境30 分钟前
如何验证代理IP纯净度?2026年IP检测与优化指南
网络·网络协议·tcp/ip
minji...33 分钟前
Linux 网络基础之网络IP层(十)IP 协议,网段划分,IP地址相关问题
linux·运维·服务器·网络·tcp/ip·智能路由器·php
IT瑞先生40 分钟前
运维专题3——业务进程排查方法论
运维·网络
IT大白鼠1 小时前
网络发展简史:从ARPANET到Web3.0的技术演进与社会影响
网络·web3
cui_ruicheng1 小时前
Linux网络编程(六):UDP聊天室与线程池
linux·服务器·网络·udp