计算机⽹络及TCP⽹络应⽤程序开发

一、 网络基础概念

1.网络的定义与目的

  • 定义 :将具有独立功能的多台计算机通过通信设备与线路连接起来,在网络软件和协议的管理协调下,实现资源共享信息传递的系统。

  • 目的 :进行网络编程,开发基于网络通信的应用程序。

2. IP地址 (Internet Protocol Address)

作用:网络设备的唯一逻辑标识,用于定位和寻址。

分类

IPv4 :32位地址,点分十进制表示(如 192.168.1.1),地址池近乎枯竭。

IPv6 :128位地址,十六进制表示(如 2001:0db8::1),解决IPv4地址不足问题。

查看命令 :Linux/macOS: ifconfig,Windows: ipconfig

连通性测试ping <IP或域名>

3. 端口 (Port) 与端口号 (Port Number)

端口:设备与外界通信交流的出口,是数据传输的通道。

端口号:用于标识端口的整数(0-65535)。

为什么需要端口 :IP地址只能定位到设备,端口号才能指定设备上具体的应用程序(进程)。

分类

知名端口 (Well-known Ports):0-1023,分配给系统核心服务(如HTTP:80, HTTPS:443, SSH:22, FTP:21)。

动态端口 (Dynamic Ports):1024-65535,供普通应用程序使用。

4. URL (统一资源定位符)

作用:完整描述互联网上资源地址的字符串。

标准格式<协议>://<主机名>:<端口号>/<路径>?<查询参数>#<片段锚点>

示例解析https://www.example.com:8080/api/users?id=1001#profile

协议(Scheme): https

主机名(Host): www.example.com

端口(Port): 8080 (HTTPS默认443,可省略)

路径(Path): /api/users

查询字符串(Query): ?id=1001

片段(Fragment): #profile (客户端使用,不发送到服务器)

概念 说明
IP地址 网 络中设备的唯一逻辑地址,用于标识和定位设备。
IPv4 32位地址,点分十进制表示(如 192.168.1.1),约42亿个地址。
IPv6 128位地址,十六进制表示(如 2001:0db8::1),解决IPv4地址耗尽问题。
URL (统一资源定位符) 用于定位互联网上资源的地址。完整格式:协议://域名:端口/路径?查询参数#锚点

二、同源与跨域 (Same-Origin vs. Cross-Origin)

特性 同源 (Same-Origin) 跨域 (Cross-Origin)
定义 协议、域名、端口完全相同 协议、域名、端口有任一不同
示例 https://example.com/apphttps://example.com/api https://example.comhttp://example.com (协议不同)
访问权限 完全访问 DOM、Cookie、AJAX 请求 默认禁止 访问,受同源策略限制
解决方案 无需特殊处理 CORS (跨域资源共享)、JSONP、代理服务器、WebSocket

同源策略 (SOP):浏览器的核心安全机制,防止恶意网站窃取另一个网站的数据。

三、Socket 套接字及使用场景

方面 说明
是什么 网络通信的端点(Endpoint),是应用程序通过网络协议进行数据交互的接口
比喻 IP地址是地址,端口是门牌号,Socket就是连接两扇门的电话线
使用场景 任何网络通信!包括Web服务(HTTP/HTTPS)、邮件(SMTP/POP3)、文件传输(FTP)、数据库连接、实时通信(游戏、聊天)等。
本质 封装了底层网络协议(如TCP/IP)的复杂操作,为程序员提供简单的API(如 send(), recv(), connect())。

四、TCP 与 UDP 的特点与区别

特性 TCP (传输控制协议) UDP (用户数据报协议)
连接性 面向连接 (需三次握手) 无连接 (直接发送)
可靠性 可靠传输 (确认、重传、校验) 不可靠传输 (可能丢失、乱序)
数据顺序 保证数据顺序 不保证数据顺序
速度/开销 速度慢,开销大(有控制机制) 速度快,开销小 (无控制机制)
流量控制 有 (滑动窗口)
应用场景 网页浏览(HTTP/S)、邮件(SMTP)、文件传输(FTP)、远程登录(SSH) 视频流、语音通话(VoIP)、在线游戏、DNS查询、直播
比喻 打电话:需要接通,确认对方听到,有条理地对话。 对讲机/发传单:直接说,不管对方是否收到,可能听不清。

五、TCP的可靠传输机制与连接管理

1 可靠传输机制

确认应答 (ACK):接收方收到数据后必须回复确认消息。

超时重传 (Retransmission):发送方在一定时间内未收到ACK,会重发数据。

序列号与确认号:为每个字节编号,解决乱序和重复问题。

流量控制 (Flow Control):通过滑动窗口机制,防止发送过快导致接收方缓冲区溢出。

拥塞控制 (Congestion Control):通过慢启动、拥塞避免等算法,避免网络过载。

2 TCP 三次握手与四次挥手

三次握手 (建立连接 - 我要和你打电话)

  1. SYN :客户端 -> 服务器。"你好,我能和你连接吗?" (SYN_SENT)

  2. SYN-ACK :服务器 -> 客户端。"收到,我可以连接,你准备好了吗?" (SYN_RCVD)

  3. ACK :客户端 -> 服务器。"好的,我准备好了,开始通信吧!" (ESTABLISHED)

" TCP三次握⼿" 是指在计算机⽹络中,TCP协议(传输控制协议)建⽴连接时所进⾏的⼀种过程。具 体来说,它包含以下三个步骤:

  1. 第⼀次握⼿:客户端发送⼀个带有SYN(同步序列编号)标志的TCP报⽂到服务器,表示请求建 ⽴连接。此时客户端进⼊SYN-SENT(同步已发送)状态。

  2. 第⼆次握⼿:服务器收到客户端的SYN报⽂后,会回复⼀个带有SYN和ACK(确认)标志的TCP 报⽂给客户端,其中ACK是对客户端SYN报⽂的确认,同时服务器⾃⼰也发送⼀个SYN报⽂,表 示⾃⼰也想建⽴连接。此时服务器进⼊SYN-RCVD(同步已接收)状态。

  3. 第三次握⼿:客户端收到服务器的SYN+ACK报⽂后,再发送⼀个带有ACK标志的TCP报⽂给服 务器,对服务器的SYN报⽂进⾏确认。此时客户端进⼊ESTABLISHED(已建⽴连接)状态,服 务器收到客户端的ACK报⽂后,也进⼊ESTABLISHED状态,⾄此TCP连接建⽴完成。

这种三次握⼿的过程可以有效防⽌出现错误的连接建⽴,确保双⽅都准备好进⾏数据传输。

四次挥手 (断开连接 - 我要挂电话了)

  1. FIN :客户端 -> 服务器。"我说完了,要挂电话了。" (FIN_WAIT_1)

  2. ACK :服务器 -> 客户端。"等等,我还没说完..." (CLOSE_WAIT / FIN_WAIT_2)

  3. FIN :服务器 -> 客户端。"好了,我也说完了,可以挂了。" (LAST_ACK)

  4. ACK :客户端 -> 服务器。"好的,再见!" (TIME_WAIT -> 等待后 CLOSED)

" TCP四次挥⼿" 是指TCP协议在断开连接时所进⾏的四次交互过程。具体如下:

  1. 第⼀次挥⼿:主机A(客户端)向主机B(服务器)发送⼀个FIN(Finish)报⽂,表示A想要关闭 连接,进⼊" FIN_WAIT_1" 状态。这个FIN报⽂的序号是seq = u,u是⼀个随机的序号值。

  2. 第⼆次挥⼿:主机B收到A的FIN报⽂后,会发送⼀个ACK(Acknowledgment)报⽂给A,表示B 已经收到A的关闭连接请求。这个ACK报⽂的序号是seq = v,确认号是ack = u + 1,表示B确认 了A的FIN报⽂。此时,B进⼊" CLOSE_WAIT" 状态,⽽A进⼊" FIN_WAIT_2" 状态。

  3. 第三次挥⼿:主机B在处理完⾃⼰的事务后,也会向主机A发送⼀个FIN报⽂,表示B也想要关闭 连接。这个FIN报⽂的序号是seq = w,确认号是ack = u + 1。此时,B进⼊" LAST_ACK" 状态。

  4. 第四次挥⼿:主机A收到B的FIN报⽂后,会发送⼀个ACK报⽂给B,表示A已经收到B的关闭连接 请求。这个ACK报⽂的序号是seq = u + 1,确认号是ack = w + 1。此时,A进 ⼊" TIME_WAIT" 状态,等待2MSL(Maximum Segment Lifetime)时间后,如果没有收到B的 任何报⽂,A就正式关闭连接,进⼊" CLOSED" 状态。⽽B在收到A的ACK报⽂后,也进 ⼊" CLOSED" 状态,完成整个断开连接的过程。

TCP四次挥⼿的⽬的是确保双⽅在断开连接时能够安全、可靠地完成数据传输,并且双⽅都能明确知 道对⽅已经关闭了连接

为什么挥手多一次?

因为TCP连接是全双工的,每一方向必须单独关闭。

六、TCP 网络应用程序开发总结

1 TCP 发送数据基本流程 (客户端)

代码:

python 复制代码
graph TD
    A[创建Socket对象] --> B[建立连接 connect]
    B --> C[发送数据 send]
    C --> D[关闭连接 close]

2 TCP 接收数据基本流程 (服务端)

代码:

python 复制代码
graph TD
    A[创建Socket对象] --> B[绑定IP和端口 bind]
    B --> C[设置监听 listen]
    C --> D[等待连接 accept<br>阻塞直到客户端连接]
    D -- 连接成功, 返回新Socket --> E[接收数据 recv]
    E --> F[发送响应 send]
    F --> G[关闭客户端连接 close]
    G --> D

3 核心开发流程

步骤 客户端 (Client) 服务器端 (Server)
1. 创建Socket socket.socket() socket.socket()
2. 绑定地址 (通常系统自动分配) 必须 .bind((host, port))
3. 建立连接 主动 .connect((server_ip, server_port)) 被动 .listen(backlog)
4. 接受连接 - .accept() -> 返回新Socket
5. 数据传输 .send() / .recv() 使用accept返回的新Socket 进行 .send() / .recv()
6. 关闭连接 .close() 先关新Socket,再关监听Socket

4 关键注意事项

  1. 字节流编码 :网络传输的是字节(bytes)。发送前需.encode('utf-8'),接收后需.decode('utf-8')

  2. 监听Socket vs 通信Socket

    • 监听Socket :仅用于接受新连接 (accept()),不能收发数据。

    • 通信Socketaccept() 返回的新Socket,用于与特定客户端进行数据通信。

  3. 多客户端并发 :默认的accept() -> recv() -> send()是串行的。处理多客户端必须使用 多线程多进程I/O多路复用 (如 selectors 模块)。

  4. 连接状态判断 :如果 recv() 返回空数据(长度为0的bytes),则表示对方已关闭连接。

  5. 端口复用:服务器重启时避免"Address already in use"错误。

python 复制代码
# 在bind()之前设置
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)

示例:

编写一个TCP回声服务器和客户端程序:

· 服务器监听本地端口8888

· 客户端连接到服务器后,用户可以输入任意字符串

· 服务器将接收到的消息原样返回给客户端

· 客户端显示服务器返回的消息

· 当用户输入"quit"时,客户端和服务器都应正常关闭连接

要求:

· 服务器能够同时处理多个客户端连接(使用多线程或多进程)

· 客户端和服务器都需要有适当的错误处理

· 代码结构清晰,有必要的注释

服务端代码(server.py):

python 复制代码
import threading
import socket

# 关于对处理客户端的连接
def handle(new_socket, ip_port):
    print(f"新的连接:{ip_port}")

    try:
        while True:
            data = new_socket.recv(1024).decode('utf-8')
            # 判断是否收到空数据
            if not data:
                print(f"客户端 {ip_port} 断开连接")
                break
            # 打印收到的消息和客户端的信息
            print(f"收到来自 {ip_port} 的消息: {data}")
            #   检测是否有退出的请求
            if data == "quit":
                print(f"客户端 {ip_port} 请求退出连接")
                new_socket.send("服务器连接关闭".encode("utf-8"))
                break
            # 发送从客户端传过来的信息
            new_socket.send(data.encode('utf-8'))
    # 捕获异常
    except Exception as e:
        print(f"客户端 {ip_port}: 发生错误 {e}")
    finally:
        new_socket.close()
        print(f"与客户端 {ip_port} 的连接已断开")

#   启动tcp的服务端函数
def start_server(host='127.0.0.1', port=8080):
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
        server_socket.bind((host, port))
        # 开始接听连接
        server_socket.listen(5)
        print(f"服务器启动, 监听: {host}:{port}")
        print("等待客户端连接...")

        while True:
            new_socket, ip_port = server_socket.accept()
            client_thread = threading.Thread(target=handle, args=(new_socket, ip_port))
            client_thread.daemon = True
            client_thread.start()
            print(f"活跃线程数: {threading.active_count()-1}")
    #   捕获异常
    except Exception as e:
        print(f"服务器错误: {e}")
    finally:
        server_socket.close()
        print("服务器已关闭")


if __name__ == '__main__':
    start_server()

客户端代码(client.py):

python 复制代码
import socket

#   启动客户端的函数
def start_client(host='127.0.0.1', port=8080):
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
        client_socket.connect((host, port))
        print(f'已连接到服务器 {host}:{port}')
        print("输入消息发送到服务器, 发送quit退出")

        while True:
            message = input("请输入: ")
            client_socket.send(message.encode('utf-8'))

            if message == 'quit':
                break

            data = client_socket.recv(1024).decode('utf-8')
            print(f"服务器的回复: {data}")
    except Exception as e:
        print(f"客户端错误: {e}")
    finally:
        client_socket.close()
        print("连接已关闭")


if __name__ == '__main__':
    start_client()

六、 总结

网络基础 :理解 IP地址 (定位设备)、端口 (定位应用)、Socket (通信工具) 是网络编程的基石。

协议选择 :根据应用场景在可靠但慢的TCP快速但不可靠的UDP之间做出权衡。

TCP精髓 :其可靠性 源于复杂的机制(握手、挥手、确认、重传、控制),其开发流程围绕"建立连接->传输->关闭连接"展开。

开发关键 :严格遵循开发流程,深刻理解字节编码双Socket分工多客户端并发处理,是写出稳定高效TCP程序的关键。

相关推荐
Greedy Alg1 分钟前
Socket编程学习记录
网络·websocket·学习
刘逸潇20051 小时前
FastAPI(二)——请求与响应
网络·python·fastapi
软件技术员1 小时前
使用ACME自动签发SSL 证书
服务器·网络协议·ssl
我也要当昏君1 小时前
6.4 电子邮件 (答案见原书 P284)
网络协议
Mongnewer1 小时前
通过虚拟串口和网络UDP进行数据收发的Delphi7, Lazarus, VB6和VisualFreeBasic实践
网络
我也要当昏君2 小时前
6.5 万维网(答案见原书P294)
网络
嶔某2 小时前
网络:传输层协议UDP和TCP
网络·tcp/ip·udp
文火冰糖的硅基工坊3 小时前
[嵌入式系统-154]:各种工业现场总线比较
网络·自动驾驶·硬件架构
以己之3 小时前
详解TCP(详细版)
java·网络·tcp/ip
せいしゅん青春之我3 小时前
[JavaEE初阶]网络协议-状态码
java·网络协议·http