目录

 

前言

一、计算机网络核心基础概念

1. 什么是计算机网络

2. IP 地址

作用

两种 IP 版本

查看本机 IP 命令

网络连通测试:ping 命令

3. 端口号

核心问题

端口号分类(0~65535)

4. Socket 套接字

5. TCP 协议

TCP 协议是一种可靠面向连接传输协议

TCP 两大核心特性

对比 UDP(补充了解)

6.TCP 三次握手、四次挥手

二、编码转换

核心方法

示例代码

三、TCP 客户端开发

客户端开发五步走

完整客户端代码

四、TCP 服务端开发

服务端七步走

客户端 & 服务端完整时序流程图

版本 1:基础单客户端服务端

版本 2:面向对象封装服务端

版本 3:多线程并发服务端

五、TCP 网络编程必看注意事项

六、总结


 前言

不管是聊天软件、网站服务、文件传输工具,底层全部依赖网络通信。作为 Python 开发者,Socket TCP 编程是后端、爬虫、服务开发的必备基础。

本文从底层网络原理讲起,结合编码转换、客户端 / 服务端实战、多并发服务、面试核心知识点(三次握手 / 四次挥手)完整梳理,零基础也能看懂。                                                   

一、计算机网络核心基础概念

1. 什么是计算机网络

将多台独立设备通过网线、路由器等设备连接,依靠网络协议实现资源共享、数据互传的平台,手机、电脑、服务器都属于网络设备

2. IP 地址

作用

IP 地址作为定位网络里唯一设备,是设备的网络 “身份证”,相当于手机号,用来在海量网络设备中精准找到目标机器

两种 IP 版本

  1. IPv4(当前主流) 32 位二进制,点分十进制格式,例:192.168.199.161,四段数字范围0~255,第一段限制1~223

  2. IPv6(下一代) 128 位地址,解决 IPv4 地址枯竭问题,自带加密、路由优化优势

查看本机 IP 命令

  • Windows:ipconfig

  • Linux/Mac:ifconfig

网络连通测试:ping 命令

# 测试外网连通
ping www.baidu.com
# 直接ping IP地址
ping 119.75.217.26

无丢包、有返回时延代表网络正常

3. 端口号

端口号是定位设备上的软件程序

核心问题

一台电脑同时运行微信、QQ、浏览器,只有 IP 只能找到电脑,无法区分数据发给哪个软件,端口就是程序的专属通道

  • IP:找到哪台电脑
  • 端口号:找到电脑上哪个应用程序 举个例子:飞秋默认端口2425,数据通过IP+端口精准送达对应软件

端口号分类(0~65535)

  • 知名端口 0~1023:固定分配给标准服务
端口服务用途
21FTP文件传输
22SSH远程登录
80HTTP网页访问
443HTTPS加密网页
  • 动态端口 1024~65535:程序自定义使用,我们开发 TCP 服务一般选用该区间

4. Socket 套接字

Socket 套接字是网络通信的工具

IP + 端口确定了通信双方,但需要工具完成收发数据,这个工具就是Socket,类比生活中的电话:

  • 知道对方手机号(IP + 端口),必须有电话(Socket)才能通话。 所有网络软件底层都基于 Socket 实现,是程序之间网络交互的统一接口

5. TCP 协议

TCP 协议是一种可靠面向连接传输协议

TCP 两大核心特性

  1. 面向连接:通信前必须建立连接,通信结束断开连接,类似打电话,流程:建立连接→传输数据→关闭连接。
  2. 可靠传输,通过 4 种机制保证数据不丢、不乱序:
    • 发送应答机制:发一条等对方确认再发下一条
    • 超时重传:长时间无应答自动重发数据包
    • 错误校验:校验数据完整性,损坏则重传
    • 流量 / 拥塞控制:防止发送太快导致对方缓冲区溢出

对比 UDP(补充了解)

UDP 是无连接、不可靠协议,不用建立连接直接发数据,速度更快,但不保证数据送达,适合直播、游戏、语音等允许少量丢包场景

6.TCP 三次握手、四次挥手

三次握手(建立连接)

TCP 三次握手极简流程图

  1. 客户端发 SYN 报文:请求连接,进入SYN-SENT
  2. 服务端回 SYN+ACK:同意连接 + 确认客户端请求,进入SYN-RCVD
  3. 客户端回 ACK:确认服务端连接请求,双方进入ESTABLISHED,连接就绪 作用:确认双方收发能力正常,避免无效连接

四次挥手(断开连接)

TCP 四次挥手极简流程图

  1. 客户端发 FIN:我不再发数据,进入FIN_WAIT_1
  2. 服务端回 ACK:收到关闭请求,继续传输剩余数据,进入CLOSE_WAIT
  3. 服务端发 FIN:数据发完,请求关闭连接,进入LAST_ACK
  4. 客户端回 ACK:确认关闭,等待 2MSL 后彻底断开,服务端收到 ACK 直接关闭 作用:双方都传输完数据再断开,避免数据丢失

二、编码转换

计算机网络只能传输二进制 bytes 字节流,我们写的字符串无法直接发送,必须经过编码 / 解码。

核心方法

  1. 字符串.encode("utf-8"):编码,文本 → 二进制(发送数据使用)
  2. bytes.decode("utf-8"):解码,二进制 → 文本(接收数据使用)

示例代码

# 编码
msg = "你好,TCP网络编程"
send_bytes = msg.encode("utf-8")
print("编码后二进制:", send_bytes)

# 解码
recv_str = send_bytes.decode("utf-8")
print("解码后文本:", recv_str)

注意:收发两端编码格式必须统一,否则会出现中文乱码(utf-8/GBK 二选一)

三、TCP 客户端开发

客户端开发五步走

  1. 创建 socket 套接字(socket)
  2. connect 连接服务端 IP + 端口
  3. send 编码后二进制数据
  4. recv 接收服务端响应并解码
  5. close 关闭套接字释放资源

完整客户端代码

import socket

if __name__ == '__main__':
    # 1. 创建TCP套接字 AF_INET=IPv4 SOCK_STREAM=TCP
    tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2. 连接服务端(元组参数:(IP,端口))
    tcp_client.connect(("127.0.0.1", 8080))
    
    # 3. 发送数据,必须编码
    send_msg = "服务端你好,我是客户端!"
    tcp_client.send(send_msg.encode("utf-8"))
    
    # 4. 接收响应,最大接收1024字节,解码
    recv_data = tcp_client.recv(1024).decode("utf-8")
    print(f"收到服务端消息:{recv_data}")
    
    # 5. 关闭连接
    tcp_client.close()

四、TCP 服务端开发

服务端七步走

客户端 & 服务端完整时序流程图

  1. 创建 socket 套接字
  2. bind 绑定本机 IP 和端口(必填,客户端靠端口找到服务)
  3. listen 开启监听,设置最大排队连接数
  4. accept 阻塞等待客户端连接,返回新通信套接字 + 客户端地址
  5. recv 接收客户端数据
  6. send 返回响应数据
  7. 关闭通信套接字、主监听套接字

版本 1:基础单客户端服务端

import socket

if __name__ == '__main__':
    # 1. 创建套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 端口复用:解决重启服务端口被占用报错
    tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    
    # 2. 绑定端口 ""代表本机所有网卡IP,127.0.0.1仅本地访问
    tcp_server.bind(("", 8080))
    
    # 3. 监听,最大排队128个连接
    tcp_server.listen(128)
    print("服务端启动成功,等待客户端连接...")
    
    # 4. 阻塞等待客户端接入
    conn_socket, client_addr = tcp_server.accept()
    print(f"新客户端接入:{client_addr}")
    
    # 5. 接收数据
    recv_bytes = conn_socket.recv(1024)
    recv_msg = recv_bytes.decode("utf-8")
    print(f"客户端发来:{recv_msg}")
    
    # 6. 回复数据
    resp = f"已收到你的消息:{recv_msg}"
    conn_socket.send(resp.encode("utf-8"))
    
    # 7. 关闭资源
    conn_socket.close()
    tcp_server.close()

版本 2:面向对象封装服务端

import socket

class TcpServer:
    def __init__(self, port=8080):
        # 初始化套接字
        self.server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        self.server_sock.bind(("", port))
        self.server_sock.listen(128)
        print(f"服务端启动,监听端口{port}")
    
    def handle_client(self, conn_sock, addr):
        """处理单个客户端消息"""
        recv_data = conn_sock.recv(1024).decode("utf-8")
        print(f"[{addr}] 客户端:{recv_data}")
        # 回复消息
        conn_sock.send(f"服务端已读取:{recv_data}".encode("utf-8"))
        conn_sock.close()
    
    def start(self):
        # 循环持续接收客户端
        while True:
            conn, addr = self.server_sock.accept()
            self.handle_client(conn, addr)

if __name__ == '__main__':
    server = TcpServer(8080)
    server.start()

版本 3:多线程并发服务端

基础服务一次只能处理一个客户端,使用多线程实现并发:

import socket
import threading

# 单个客户端处理函数
def handle_conn(conn_sock, client_addr):
    while True:
        try:
            recv_bytes = conn_sock.recv(1024)
            # recv返回空代表客户端断开
            if not recv_bytes:
                print(f"{client_addr} 客户端下线")
                break
            recv_msg = recv_bytes.decode("utf-8")
            print(f"[{client_addr}]:{recv_msg}")
            # 服务端主动发消息
            send_msg = input("服务端回复:").encode("utf-8")
            conn_sock.send(send_msg)
        except ConnectionResetError:
            print(f"{client_addr} 异常断开")
            break
    conn_sock.close()

if __name__ == '__main__':
    server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
    server_sock.bind(("", 8080))
    server_sock.listen(128)
    print("并发TCP服务启动,支持多客户端同时连接")
    
    while True:
        conn, addr = server_sock.accept()
        # 为每个客户端创建独立线程
        client_thread = threading.Thread(target=handle_conn, args=(conn, addr))
        client_thread.start()

五、TCP 网络编程必看注意事项

  1. 连接前提:客户端与服务端通信前必须建立 TCP 连接,无连接无法传输数据
  2. 端口绑定规则
    • 客户端:无需手动绑定端口,操作系统自动分配临时端口
    • 服务端:必须绑定固定端口,否则客户端找不到服务
  3. 两种套接字区分
    • listen()后的主套接字:只负责监听新连接,不能收发数据
    • accept()返回的 conn 套接字:专门和单个客户端收发消息
  4. 客户端下线判断:客户端调用close()后,服务端recv()会返回空字节,可通过判断长度 0 识别客户端断开
  5. 端口复用:添加setsockopt代码,避免服务重启时提示端口被占用
  6. 数据格式:所有收发数据必须是 bytes 二进制,字符串一定要 encode,接收后 decode

六、总结

  1. 网络通信三要素:IP(定位设备)+ 端口(定位程序)+Socket(通信工具)
  2. TCP 是面向连接、可靠传输协议,底层依靠三次握手建连、四次挥手断连
  3. 网络只传二进制,encode编码发数据,decode解码读数据
  4. 客户端五步、服务端七步是标准开发流程,多线程可实现并发多客户端
  5. 日常开发高频踩坑点:端口未绑定、编码不一致、忘记关闭套接字、端口占用

掌握这套基础后,HTTP 接口、文件传输、聊天室、爬虫底层通信逻辑都能轻松理解,是 Python 后端开发的核心基石

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐