15-14.【HTTP】Socket 是什么?TCP Socket 与 UDP Socket 在 iOS 如何使用?

4 阅读3分钟

Socket(套接字) 是应用层与 TCP/IP 协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Socket 接口后面。

对开发者来说,Socket 就是 “IP 地址 + 协议 + 端口” 的结合体,通过它,你的 App 才能在互联网上精准地找到另一台设备并交换数据。


1. TCP Socket vs UDP Socket

在 iOS 中,选择哪种 Socket 取决于你的业务需求:

特性TCP Socket (流式)UDP Socket (数据报)
连接性面向连接(三次握手)无连接
可靠性保证交付、顺序一致、无差错不保证交付,可能丢包或乱序
数据边界字节流(存在“粘包”问题)保留数据边界(发多大收多大)
适用场景即时通讯(IM)、文件传输、远程登录实时音视频、在线游戏、局域网发现

2. 在 iOS 中如何使用 (现代方式)

虽然 iOS 依然支持传统的 C 语言 BSD Sockets,但 Apple 强烈建议使用 Network.framework (iOS 12+)。它不仅支持 Swift,还能自动处理 Wi-Fi/蜂窝网切换、低功耗优化等。

A. 使用 TCP Socket

TCP 需要先建立连接,然后才能进行双向数据流传输。

Swift

import Network

// 1. 创建连接 (指定 Host 和 Port)
let connection = NWConnection(host: "192.168.1.100", port: 8080, using: .tcp)

// 2. 监听连接状态
connection.stateUpdateHandler = { state in
    switch state {
    case .ready:
        print("TCP 连接已就绪")
        // 连接成功后可以发送数据
    case .failed(let error):
        print("连接失败: (error)")
    default: break
    }
}

// 3. 启动连接
connection.start(queue: .main)

// 4. 发送数据
let content = "Hello Server".data(using: .utf8)
connection.send(content: content, completion: .contentProcessed({ error in
    if let error = error { print("发送失败: (error)") }
}))

// 5. 接收数据
connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { data, _, isComplete, _ in
    if let data = data, !data.isEmpty {
        print("收到回复: (String(data: data, encoding: .utf8) ?? "")")
    }
}

B. 使用 UDP Socket

UDP 不需要握手,直接通过 NWConnection 发送数据包。

Swift

// 1. 使用 .udp 协议
let udpConnection = NWConnection(host: "255.255.255.255", port: 9000, using: .udp)

// 2. 配置允许广播 (如果是局域网发现)
let params = NWParameters.udp
params.allowLocalEndpointReuse = true
// 注意:UDP 通常用于快速发送小数据包

// 3. 发送数据 (无需等待连接确认,直接尝试发送)
udpConnection.start(queue: .main)
let packet = "Discovery_Signal".data(using: .utf8)
udpConnection.send(content: packet, completion: .idempotent)

3. iOS 开发中的关键点

  1. 后台存活:标准的 Socket 连接在 App 进入后台后会被系统挂起或切断。如果需要长连接(如 IM),通常建议使用 Apple 推送 (APNs) 唤醒,或申请特定的后台运行权限。
  2. 粘包问题 (TCP) :TCP 是基于流的,如果你连发两条消息 "Hello""World",接收方可能一次性收到 "HelloWorld"。你需要自己定义数据包协议(例如在包头加 4 字节的长度字段)。
  3. Local Network 权限:在 iOS 14+ 中,如果你的 Socket 是连接局域网设备,必须在 Info.plist 中配置 NSLocalNetworkUsageDescription,否则连接会静默失败。
  4. 性能优化:尽量复用 NWConnection 对象,频繁创建/销毁 Socket 会非常耗电。

总结

  • TCP 用于需要“稳”的场景,它是 iOS 中长连接(IM、控制协议)的首选。
  • UDP 用于需要“快”或“广播”的场景。
  • Network.framework 是目前 iOS 开发 Socket 的最佳实践。