当前位置: 首页 > news >正文

Python学习之网络编程

一,网络编程基本概念

网络编程是通过编写代码实现计算机之间的通信,它涵盖了许多重要的概念和技术,以下是一些关键概念的介绍:

1. Socket(套接字)

  • 定义:Socket是计算机网络中用于进行通信的端点,它提供了一个应用层与传输层之间的接口。通过Socket,程序可以与其他计算机进行数据交换。

  • 作用:通过Socket,程序能够进行以下操作:创建连接、发送和接收数据、关闭连接等。最常见的Socket编程模型是基于TCP/IP协议的。

  • 类型:

    • TCP Socket:面向连接的,使用TCP协议进行通信,确保数据的可靠性。
  • UDP Socket:无连接的,使用UDP协议进行通信,适用于实时性要求较高的应用,但不能保证数据的可靠性。

2. IP地址与端口

  • IP地址:每台连接到网络的设备都会分配一个唯一的IP地址(互联网协议地址),用于标识设备的网络位置。IP地址可以是IPv4(32位)或IPv6(128位)。
  • 端口号:端口号是区分同一台设备上不同服务的标识符。在一个IP地址下,可以有多个端口,通常端口号范围是0到65535,其中0到1023是“知名端口”,如HTTP(80)、HTTPS(443)、FTP(21)等。

3. TCP/IP协议栈

TCP/IP协议栈是现代计算机网络的基础。它分为多个层级,常见的有四层:

  • 应用层:处理具体的应用协议,如HTTP、FTP、SMTP等。
  • 传输层:提供端到端的通信功能,主要协议为TCP(传输控制协议)和UDP(用户数据报协议)。
  • 网络层:负责数据包的路由和传输,核心协议为IP(互联网协议)。
  • 数据链路层:在物理介质上传输数据包,确保数据的可靠传输。

4. TCP与UDP

  • TCP(传输控制协议):

    • 面向连接:在发送数据前,必须建立连接(如通过三次握手过程)。
    • 可靠性:TCP保证数据的可靠性,通过确认(ACK)、重传机制、顺序控制等手段来确保数据按顺序且无误到达。
    • 应用:适用于需要高可靠性的应用,如网页浏览(HTTP)、文件传输(FTP)等。
  • UDP(用户数据报协议):

    • 无连接:无需建立连接,直接发送数据。
    • 不保证可靠性:UDP不保证数据的可靠到达,也不保证数据的顺序,适用于对实时性要求高的应用(如视频会议、实时游戏等)。
    • 应用:常用于实时通信、流媒体传输等场景。

5. 三次握手与四次挥手

  • 三次握手(TCP连接建立过程):

    1. SYN:客户端向服务器发送连接请求(SYN标志位)。
    2. SYN-ACK:服务器响应客户端的请求,并确认收到连接请求。
    3. ACK:客户端向服务器确认连接建立完毕,连接正式建立。
  • 四次挥手(TCP连接关闭过程):

    1. 客户端发起连接关闭请求(FIN标志位)。
    2. 服务器响应并确认(ACK)。
    3. 服务器关闭连接并发送FIN请求。
    4. 客户端确认关闭连接。

6. DNS(域名系统)

  • 定义:DNS是一种将域名(如www.example.com)转换为IP地址(如192.168.1.1)的系统。因为人类更容易记住域名而不是数字形式的IP地址,所以DNS提供了一个可读性更强的映射。
  • 工作原理:当用户访问一个网站时,计算机会查询DNS服务器,获取域名对应的IP地址,之后通过这个IP地址与服务器建立连接。

7. HTTP与HTTPS

  • HTTP(超文本传输协议):HTTP是Web的基础协议,用于客户端与服务器之间的请求和响应。它是无状态的,每次请求都是独立的。
  • HTTPS(安全超文本传输协议):HTTPS是在HTTP上加入了SSL/TLS协议,提供了加密和身份验证功能,确保数据传输的安全性,防止中间人攻击。

8. WebSocket

  • 定义:WebSocket是一种基于TCP的协议,允许在客户端和服务器之间建立持久的双向通信。与传统的HTTP不同,WebSocket支持实时数据交换,适用于需要实时更新的应用场景,如在线聊天、实时股票交易等。

9. 代理服务器与负载均衡

  • 代理服务器:代理服务器位于客户端和目标服务器之间,转发客户端的请求到目标服务器。它可以隐藏客户端的真实IP地址,增强安全性,或者缓存数据以提高访问速度。
  • 负载均衡:负载均衡是一种技术,通过将请求分配到多个服务器来分散负载,保证应用的高可用性和高性能。

10. 网络安全

  • 加密与解密:在传输过程中,数据可能会被窃取。加密可以保证数据的保密性,常用的加密算法有对称加密(如AES)和非对称加密(如RSA)。
  • 身份验证与授权:确保通信双方身份的合法性,并根据授权控制对资源的访问,常见方法有使用证书、OAuth等。
  • 防火墙:防火墙可以监控和过滤网络流量,防止恶意访问或攻击。

二,网络协议概述

1. OSI模型与TCP/IP模型

网络协议通常是按照网络协议模型来设计的,最经典的模型是OSI七层模型TCP/IP协议栈。两者在结构上有所不同,但目的都是为了标准化网络通信。

  • OSI七层模型
    1. 物理层(Physical Layer):定义物理设备的传输媒介,如电缆、光纤等。
    2. 数据链路层(Data Link Layer):提供节点到节点的通信,常用协议如Ethernet、PPP。
    3. 网络层(Network Layer):负责数据包的路由与转发,核心协议是IP协议(Internet Protocol)。
    4. 传输层(Transport Layer):提供端到端的数据传输,常见协议有TCP、UDP。
    5. 会话层(Session Layer):管理应用间的会话和数据交换,典型协议有NetBIOS。
    6. 表示层(Presentation Layer):数据格式的转换,如加密、解密等。
    7. 应用层(Application Layer):实现具体的应用协议,如HTTP、FTP、SMTP等。
  • TCP/IP协议栈
    • 包括应用层传输层网络层数据链路层,实际网络协议栈中的层次较为简化。

2. 常见的网络协议

1. IP协议(Internet Protocol)
  • IP协议是网络层协议,负责在网络中传输数据包。它的主要作用是路由:根据目标IP地址,将数据从源计算机发送到目的计算机。IP协议有两个版本:
    • IPv4(32位地址,表示范围为0.0.0.0到255.255.255.255);
    • IPv6(128位地址,表示范围非常大,解决了IPv4地址耗尽的问题)。
2. TCP协议(Transmission Control Protocol)
  • TCP协议是传输层的面向连接的协议。它提供可靠的、无差错的数据传输。TCP保证数据包按顺序到达,并支持错误检测、重传和流量控制。TCP广泛用于需要高可靠性的应用,如网页浏览(HTTP)、电子邮件(SMTP)等。
  • 三次握手:建立连接时,客户端和服务器通过三次握手过程确认通信准备就绪。
  • 四次挥手:断开连接时,客户端和服务器通过四次挥手关闭连接。
3. UDP协议(User Datagram Protocol)
  • UDP协议是传输层的无连接协议。与TCP不同,UDP不保证数据的可靠到达和顺序,适用于实时应用,如视频流、语音通信等。UDP传输效率较高,但可能出现数据丢失和乱序的情况。
  • TCP与UDP的对比
特性TCPUDP
连接方式面向连接,需建立连接无连接,直接发送数据
可靠性保证数据可靠传输不保证数据可靠性
数据顺序保证数据顺序到达不保证数据顺序
流量控制支持流量控制不支持流量控制
拥塞控制支持拥塞控制不支持拥塞控制
传输效率较低,因需要建立连接和进行错误处理较高,适合低延迟要求的应用
数据重传自动重传丢失的数据包不进行重传
头部大小20字节(不含数据)8字节
适用场景文件传输、网页浏览、电子邮件等实时通信、视频会议、在线游戏等
4. HTTP协议(HyperText Transfer Protocol)
  • HTTP协议是应用层的协议,用于客户端与Web服务器之间的请求和响应。它基于请求/响应模型,不保证数据传输的可靠性,因此常与TCP/IP一起使用。HTTPS是其安全版本,使用TLS/SSL协议加密传输数据,确保通信的安全。
5. DNS协议(Domain Name System)
  • DNS协议是用于将域名(如www.example.com)解析为IP地址的协议。用户通过域名访问网站时,DNS会将域名转换为相应的IP地址,从而完成路由。
6. FTP协议(File Transfer Protocol)
  • FTP协议是用于在计算机之间传输文件的协议。它工作在客户端和服务器之间,支持上传、下载文件。FTP支持两种模式:主动模式和被动模式。
7. SMTP协议(Simple Mail Transfer Protocol)
  • SMTP协议是用于电子邮件传输的协议。它负责在邮件服务器之间传送邮件,通常与POP3或IMAP协议配合使用,POP3/IMAP用于邮件的接收和存储。
8. POP3/IMAP协议
  • POP3和IMAP都是用于电子邮件接收的协议:
    • POP3:将邮件从邮件服务器下载到本地设备,下载后邮件通常从服务器删除。
    • IMAP:将邮件存储在邮件服务器上,用户可以在不同设备上查看邮件,邮件在服务器上保持不变。
9. ARP协议(Address Resolution Protocol)
  • ARP协议用于在局域网内解析IP地址与MAC地址的映射关系。当一个设备知道目标IP地址时,ARP协议帮助它找到目标设备的MAC地址,从而完成数据链路层的通信。
10. DHCP协议(Dynamic Host Configuration Protocol)
  • DHCP协议用于动态分配IP地址给网络中的设备。设备在连接到网络时,DHCP服务器为其分配一个IP地址、子网掩码、网关等网络配置。

3. 网络协议的作用和特性

  • 数据格式化:协议规定了数据的格式、结构以及传输顺序。
  • 错误检测和修正:大多数协议会包含机制来检测和修复传输中的错误,特别是像TCP这样的可靠协议。
  • 数据加密与安全性:协议可以通过加密机制来保证数据在传输过程中的安全性,如HTTPS协议。
  • 路由和流量控制:某些协议,如IP协议,负责在网络中转发数据包,确保数据包能够到达目的地。传输层协议如TCP还会进行流量控制和拥塞管理。

4. 协议的分类

根据协议的作用和层级,网络协议大致可以分为:

  • 应用层协议:直接为应用程序提供服务,如HTTP、FTP、DNS、SMTP等。
  • 传输层协议:处理端到端的通信,确保数据的可靠传输,如TCP和UDP。
  • 网络层协议:负责数据包的路由和传输,如IP协议。
  • 数据链路层协议:确保在物理链路上正确传输数据,如Ethernet、PPP等。

三,Socket详解

Socket(套接字)是计算机网络中用于实现数据通信的基本组件,它为程序提供了一个接口,通过这个接口,应用程序可以向网络上的其他设备发送和接收数据。简而言之,Socket是通信的“端点”,它通过网络协议(如TCP或UDP)与其他计算机进行通信。

Socket编程通常是实现客户端与服务器之间通信的关键技术之一。以下是Socket的详细介绍,包括其基本概念、类型、工作原理以及如何在实际应用中使用。


1. Socket的基本概念

什么是Socket?

Socket是一个抽象的网络通信接口,通过它,应用程序可以通过操作系统提供的网络协议与其他主机进行通信。它是程序和协议之间的一个抽象层,提供了对网络通信的简单操作接口。通过Socket,程序可以完成:

  • 打开网络连接
  • 向网络发送和接收数据
  • 关闭连接

每个Socket都需要指定通信的协议(如TCP或UDP)和相应的端口号,系统将根据这些信息来正确地路由数据。

Socket的组成

Socket通常由以下几部分组成:

  1. IP地址:标识计算机在网络中的位置,通常是一个IPv4或IPv6地址。
  2. 端口号:用于区分同一台机器上不同的服务或应用程序,端口号通常在0到65535之间,0到1023是“知名端口”。
  3. 协议类型:TCP(面向连接,可靠)或UDP(无连接,不可靠)。

2. Socket的类型

根据协议的不同,Socket可以分为以下几种类型:

1. 流式Socket(Stream Socket)
  • 协议:TCP
  • 特点:流式Socket是面向连接的,数据传输保证顺序、可靠性和完整性。通信前必须先建立连接,通信过程中保证数据无误。
  • 应用场景:适用于需要高可靠性、顺序保证的应用,如HTTP、FTP、SMTP等。
2. 数据报Socket(Datagram Socket)
  • 协议:UDP
  • 特点:数据报Socket是无连接的,数据包可能丢失、乱序、重复,发送方不会等待接收方确认。其优势是传输速度快,但不可靠。
  • 应用场景:适用于实时性要求较高、容忍丢包的应用,如视频会议、在线游戏、DNS查询等。
3. 原始Socket(Raw Socket)
  • 协议:ICMP、IP等
  • 特点:原始Socket允许应用程序直接访问底层网络协议,如IP协议。它通常用于需要构造和发送自定义网络数据包的应用。
  • 应用场景:网络安全(如防火墙、嗅探器)、网络测试工具等。

3. Socket的工作原理

Socket的工作过程通常分为两个部分:客户端服务器。下面是Socket在客户端和服务器端的基本工作流程。

1. 服务器端Socket流程
  1. 创建Socket:服务器端创建一个Socket对象,指定协议(通常是TCP)。
  2. 绑定端口:服务器通过bind()方法将Socket与指定的IP地址和端口号绑定。
  3. 监听连接:服务器调用listen()方法,进入监听状态,等待客户端的连接请求。
  4. 接受连接:当客户端请求连接时,服务器通过accept()方法接受连接,并创建一个新的Socket对象与客户端进行通信。
  5. 接收和发送数据:服务器和客户端之间通过recv()send()方法交换数据。
  6. 关闭连接:通信结束后,服务器调用close()方法关闭Socket连接。
2. 客户端Socket流程
  1. 创建Socket:客户端首先创建一个Socket对象,指定协议(通常是TCP)。
  2. 连接服务器:客户端通过connect()方法与服务器建立连接,指定目标IP地址和端口号。
  3. 发送请求:客户端通过send()方法发送请求数据到服务器。
  4. 接收响应:客户端通过recv()方法接收服务器的响应数据。
  5. 关闭连接:通信完成后,客户端通过close()方法关闭Socket连接。

4. 常用Socket API

以下是常见的Socket操作及其使用方式。以Python为例,Java、C等语言也有类似的API:

1. Python中的Socket API
  • 创建Socket

    import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # AF_INET表示IPv4,SOCK_STREAM表示TCP
    
  • 绑定IP和端口

    s.bind(('localhost', 12345))  # 绑定到本地IP和端口
    
  • 监听连接

    s.listen(5)  # 最多允许5个连接排队
    
  • 接受连接

    client_socket, client_address = s.accept()  # 等待客户端连接
    
  • 连接到服务器(客户端)

    s.connect(('localhost', 12345))  # 连接到指定的服务器和端口
    
  • 发送数据

    s.send(b'Hello, World!')  # 发送数据,数据必须是字节串
    
  • 接收数据

    data = s.recv(1024)  # 接收最多1024字节的数据
    
  • 关闭连接

    s.close()  # 关闭Socket连接
    
2. 主要的Socket方法
  • socket():创建一个新的Socket对象。
  • bind(address):将Socket与指定的地址(IP地址和端口号)绑定。
  • listen(backlog):开始监听连接。backlog指定最大排队连接数。
  • accept():接受一个新的连接请求,返回一个新的Socket对象和客户端的地址。
  • connect(address):客户端连接到指定的服务器地址。
  • send(data):发送数据到远程计算机。
  • recv(buffer_size):接收从远程计算机发送的数据。
  • close():关闭Socket连接。

5. Socket的应用示例

1. 简单的TCP客户端和服务器
TCP服务器(Python示例)
import socket

# 创建Socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定地址和端口
server_socket.bind(('localhost', 12345))

# 开始监听连接
server_socket.listen(5)
print('Server is listening...')

while True:
    # 接受连接
    client_socket, client_address = server_socket.accept()
    print(f'Connection from {client_address} has been established.')
    
    # 接收客户端数据
    data = client_socket.recv(1024)
    print(f'Received from client: {data.decode()}')
    
    # 发送响应
    client_socket.send(b'Hello, Client!')
    
    # 关闭连接
    client_socket.close()
TCP客户端(Python示例)
import socket

# 创建Socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接到服务器
client_socket.connect(('localhost', 12345))

# 发送数据
client_socket.send(b'Hello, Server!')

# 接收响应
response = client_socket.recv(1024)
print(f'Received from server: {response.decode()}')

# 关闭连接
client_socket.close()

四,Socket模块

1. 基本概念

socket模块中,最重要的概念是Socket对象。它代表了一个网络通信的端点,通过该对象可以与其他计算机上的应用程序进行通信。Socket对象通常由以下参数组成:

  • 地址族(Address Family):表示Socket使用的地址类型。
    • socket.AF_INET:IPv4地址族。
    • socket.AF_INET6:IPv6地址族。
    • socket.AF_UNIX:Unix域套接字。
  • 套接字类型(Socket Type):定义Socket使用的通信协议。
    • socket.SOCK_STREAM:TCP协议,面向连接的流式通信。
    • socket.SOCK_DGRAM:UDP协议,无连接的报文传输。
  • 协议:一般情况下由操作系统根据地址族和套接字类型自动选择协议。

2. 常用的socket方法

2.1 创建Socket
import socket

# 创建一个IPv4、TCP的Socket对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  • socket.AF_INET:表示使用IPv4地址。
  • socket.SOCK_STREAM:表示使用TCP协议。
2.2 绑定地址和端口 (bind)

服务器需要通过bind()方法将Socket绑定到指定的IP地址和端口号上。

s.bind(('localhost', 12345))  # 绑定IP和端口
  • 第一个参数是一个元组,包含了服务器的IP地址和端口号。localhost表示本地计算机,12345是监听的端口。
2.3 开始监听连接 (listen)

服务器端调用listen()方法来开启监听状态,等待客户端连接。

s.listen(5)  # 允许最多5个客户端连接
  • 5表示服务器可以同时处理的最大排队连接数。
2.4 接受客户端连接 (accept)

服务器端通过accept()方法接受客户端的连接请求。

client_socket, client_address = s.accept()  # 接受连接
print(f"Connection from {client_address}")
  • accept()方法会阻塞,直到客户端发起连接。它返回一个新的Socket对象和客户端的地址。
2.5 客户端连接 (connect)

客户端通过connect()方法与服务器建立连接,指定服务器的IP和端口。

client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 12345))  # 连接服务器
2.6 发送数据 (sendsendall)

通过send()方法发送数据。数据必须是字节(bytes)格式。

client_socket.send(b'Hello, Server!')  # 发送字节数据
  • send()发送的数据可能没有完全发送完,如果需要确保数据完整发送,建议使用sendall()
client_socket.sendall(b'Hello, Server!')  # 确保发送完数据
2.7 接收数据 (recv)

recv()方法用于接收数据。它返回的是字节数据。

data = client_socket.recv(1024)  # 接收最多1024字节的数据
print(f"Received: {data.decode()}")  # 解码为字符串并打印
  • recv()方法的参数是缓冲区的大小,表示每次最多接收多少字节的数据。
2.8 关闭Socket连接 (close)

通信完成后,调用close()方法关闭Socket连接。

client_socket.close()

3. 示例:TCP服务器与客户端

3.1 TCP服务器端(Python示例)
import socket

def start_server():
    # 创建一个TCP Socket
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 绑定IP和端口
    server_socket.bind(('localhost', 12345))

    # 开始监听客户端连接
    server_socket.listen(5)
    print('Server is listening...')

    while True:
        # 接受客户端连接
        client_socket, client_address = server_socket.accept()
        print(f'Connection from {client_address}')

        # 接收数据
        data = client_socket.recv(1024)
        if data:
            print(f'Received: {data.decode()}')

        # 发送响应数据
        client_socket.sendall(b'Hello, Client!')

        # 关闭客户端连接
        client_socket.close()

if __name__ == '__main__':
    start_server()
3.2 TCP客户端(Python示例)
import socket

def start_client():
    # 创建一个TCP Socket
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 连接到服务器
    client_socket.connect(('localhost', 12345))

    # 发送数据
    client_socket.sendall(b'Hello, Server!')

    # 接收服务器响应
    response = client_socket.recv(1024)
    print(f'Received from server: {response.decode()}')

    # 关闭连接
    client_socket.close()

if __name__ == '__main__':
    start_client()

4. UDP通信

UDP通信不需要建立连接,发送数据和接收数据非常简单。下面是一个简单的UDP服务器和客户端示例。

4.1 UDP服务器端(Python示例)
import socket

def start_udp_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 创建UDP Socket

    # 绑定IP和端口
    server_socket.bind(('localhost', 12345))

    print('Server is waiting for messages...')

    while True:
        # 接收数据
        data, client_address = server_socket.recvfrom(1024)
        print(f'Received message: {data.decode()} from {client_address}')

        # 发送响应数据
        server_socket.sendto(b'Hello, Client!', client_address)

if __name__ == '__main__':
    start_udp_server()
4.2 UDP客户端(Python示例)
import socket

def start_udp_client():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # 创建UDP Socket

    # 发送数据
    client_socket.sendto(b'Hello, Server!', ('localhost', 12345))

    # 接收响应
    data, server_address = client_socket.recvfrom(1024)
    print(f'Received from server: {data.decode()}')

    # 关闭连接
    client_socket.close()

if __name__ == '__main__':
    start_udp_client()

5. 其他常用功能

5.1 设置Socket超时 (settimeout)

settimeout()方法可以设置Socket的超时时间,单位为秒。超时后,recv()accept()等方法将抛出socket.timeout异常。

s.settimeout(5)  # 设置超时时间为5秒
5.2 获取本地地址 (getsockname)

getsockname()方法可以获取当前Socket的本地地址。

address = s.getsockname()
print(f'Local address: {address}')
5.3 获取远程地址 (getpeername)

getpeername()方法可以获取当前Socket连接的远程地址。

address = s.getpeername()
print(f'Remote address: {address}')

6. 总结

  • Python的socket模块提供了丰富的功能,能够实现基于TCP和UDP协议的网络通信。
  • 使用socket模块,你可以轻松创建客户端和服务器应用程序,进行数据发送和接收。
  • 常见的Socket方法包括bind()listen()accept()connect()send()recv()等。
  • 对于UDP通信,sendto()recvfrom()代替了send()recv(),且不需要建立连接。

五,TCP编程

1. TCP服务器编程步骤

  1. 创建Socket对象:使用socket.socket()创建一个Socket对象,指定地址族为IPv4(AF_INET)和协议为TCP(SOCK_STREAM)。
  2. 绑定端口:使用bind()方法将Socket绑定到一个IP地址和端口上。
  3. 监听连接:使用listen()方法让服务器开始监听客户端的连接请求。
  4. 接受连接:通过accept()方法接受客户端的连接请求。
  5. 数据传输:通过recv()接收客户端数据,使用send()sendall()发送数据到客户端。
  6. 关闭连接:通信完成后,调用close()方法关闭Socket连接。

实例一,TCP服务端编程编写

from socket import socket,AF_INET,SOCK_STREAM
#AF_INET 用于Internet之间的进程通信
#SOCK_STREAM 表示为TCP协议编程

#1,创建socket对象
server_socket=socket(AF_INET,SOCK_STREAM)

#2,绑定IPA地址和端口
ip='127.0.0.1'
port=8888
server_socket.bind((ip,port))

#3,使用listen()开始监听
server_socket.listen(5)
print('服务器已经启动')

#4,等待客户端的连接
client_socket,client_addr=server_socket.accept() #系列解包赋值

#5,接受来自客户端的数据
date=client_socket.recv(1024)
print('客户端发送过来的数据为date',date.decode('utf-8')) #要求客户端发送过来的数据使用utf-8编码

#6,关闭socket
server_socket.close()

2.TCP客户端编程基本流程

  1. 创建Socket对象:客户端通过socket.socket()创建一个Socket对象,并指定使用的地址族(通常是IPv4)和协议(通常是TCP)。
  2. 连接服务器:客户端通过connect()方法与服务器建立连接,指定服务器的IP地址和端口号。
  3. 发送数据:客户端使用send()sendall()方法将数据发送到服务器。
  4. 接收数据:客户端通过recv()方法接收服务器返回的响应数据。
  5. 关闭连接:通信结束后,客户端使用close()方法关闭Socket连接。

实例二,TCP客户端编程编写

要求新创建一个项目编写python代码,以便作为区分。并且新开启一个窗口以打开这个新python文件

import socket
#1,创建socket对象
client_socket=socket.socket()
#2,写入服务端IP地址与主机端口
ip='127.0.0.1'
port=8888
client_socket.connect((ip,port))
print('与服务器连接建立成功')

#3,发送数据
client_socket.send('hello python'.encode('utf-8'))

#4,关闭
client_socket.close()
print('发送完毕')

TCP编程客户端启动运行有先后,先启动运行服务端再启动运行客户端,连接建立之后双方谁先发送数据均可

实例三,TCP多次通信服务器端代码编写

import socket
#1,创建socket对象
socket_obj=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

#2,绑定主机IP端口
socket_obj.bind(('127.0.0.1',8888))

#3,设置最大的连接数量
socket_obj.listen(5)

#4,等待客户端的TCP连接
client_socket,client_addr=socket_obj.accept()

#5,接受数据
info=socket_obj.recv(1024).decode('utf-8')
while info != 'bye':
    if info != '':
        print('接受到的数据是:',info)
    #准备发送数据
    date=input('请输入要发送的数据:')

    #服务器端回复客户端
    socket_obj.send(date.encode('utf-8'))
    if date == 'bye':
        break
    info=socket_obj.recv(1024).decode('utf-8')
    
#关闭socket对象
client_socket.close()
socket_obj.close()

实例四,TCP多次通信客户器端代码编写

import socket
#1,创建socket对象
client_socket=socket.socket()
#2,主机的IP与端口
client_socket.connect(('127.0.0.1',8888))
print('已经建立服务器连接')
#3,客户端先发送数据
info=''
while info !='bye':
    #准备发送的数据
    send_data=input('请输入要发送的数据:')
    client_socket.send(send_data.encode('utf-8'))
    #判断
    if send_data=='bye':
        break
    #接收一条数据
    info=client_socket.recv(1024).decode('utf-8')
    print('接受到服务器的响应数据:',info)

#关闭socket对象
client_socket.close()
常见TCP客户端的改进和扩展
1. 设置Socket超时(settimeout

客户端可以通过settimeout()方法设置Socket的超时时间。如果在指定时间内没有收到响应,recv()方法会抛出socket.timeout异常。

client_socket.settimeout(5)  # 设置5秒超时
  • 超过5秒没有数据接收,recv()方法会抛出timeout异常。
2. 发送和接收更大的数据

如果需要发送或接收比1024字节更大的数据,可以调整缓冲区大小,或者分多次发送和接收。

client_socket.sendall(b"Large Data" * 1000)  # 发送更大的数据
3. 异常处理

在实际应用中,TCP客户端应处理可能的异常,如连接失败、发送失败等。

try:
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_socket.connect(('localhost', 12345))
except socket.error as e:
    print(f"Error occurred: {e}")
finally:
    client_socket.close()
  • 通过try-except-finally语句捕获并处理Socket异常。

3 TCP服务端(线程池方式)

为了更有效地管理多个客户端连接,可以使用线程池来代替创建一个新的线程。

import socket
import threading
from concurrent.futures import ThreadPoolExecutor

# 处理客户端连接的函数
def handle_client(client_socket, client_address):
    print(f"New connection from {client_address}")

    # 接收客户端数据
    data = client_socket.recv(1024)  # 接收最多1024字节的数据
    print(f"Received from {client_address}: {data.decode()}")

    # 发送响应
    client_socket.sendall(b"Hello, Client!")

    # 关闭连接
    client_socket.close()
    print(f"Connection with {client_address} closed.")

def start_tcp_server():
    # 1. 创建Socket对象
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2. 绑定IP和端口
    server_socket.bind(('localhost', 12345))

    # 3. 开始监听连接,最多允许5个客户端排队
    server_socket.listen(5)
    print("Server is listening on port 12345...")

    # 4. 创建线程池来管理客户端连接
    with ThreadPoolExecutor(max_workers=5) as executor:
        # 5. 处理多个客户端连接
        while True:
            # 接受客户端连接
            client_socket, client_address = server_socket.accept()
            
            # 将每个连接任务提交给线程池
            executor.submit(handle_client, client_socket, client_address)

if __name__ == "__main__":
    start_tcp_server()

解释

  1. ThreadPoolExecutor:通过线程池来管理线程,避免每次都创建新的线程。
  2. executor.submit():将处理客户端连接的任务提交给线程池中的空闲线程执行。

4. TCP服务端异常处理

在实际编程中,TCP服务端程序需要处理一些可能出现的异常,例如:

  • 客户端断开连接
  • 网络异常
  • 连接超时

可以通过try/except语句来捕获异常并进行处理。例如:

try:
    client_socket, client_address = server_socket.accept()
except socket.timeout:
    print("Connection timeout!")
except Exception as e:
    print(f"Error: {e}")

六,UDP编程

UDP(用户数据报协议)是一个无连接的协议,与TCP不同,UDP不需要建立连接和确认数据是否成功到达,因此它的传输效率更高,但也不保证数据的可靠性和顺序性。在UDP中,数据被以“数据报”的形式发送,每个数据报都包含了目的地址和端口信息。

UDP编程相较于TCP编程简单,因为它不需要进行连接的建立与关闭。下面我们将介绍如何使用Python的socket模块进行UDP编程。

UDP客户端与服务器编程流程

  1. 创建UDP Socket对象:使用socket.socket()方法创建一个UDP的Socket对象。
  2. 绑定端口(仅服务器端需要):服务器端需要通过bind()方法将Socket与IP地址和端口绑定。
  3. 发送数据:客户端通过sendto()方法发送数据,数据将发送到目标IP地址和端口。
  4. 接收数据:使用recvfrom()方法接收来自远程主机的数据。
  5. 关闭连接:UDP没有连接的概念,但客户端和服务器使用close()来关闭Socket。

1. UDP服务器端编程

1.1 UDP服务器端代码

服务器端代码将创建一个UDP套接字,绑定本地IP和端口,接收客户端数据,并发送响应。

import socket

def start_udp_server():
    # 1. 创建UDP套接字
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 2. 绑定IP和端口
    server_socket.bind(('localhost', 12345))

    print("UDP server is waiting for messages...")

    while True:
        # 3. 接收客户端数据
        data, client_address = server_socket.recvfrom(1024)  # 最大接收1024字节
        print(f"Received message from {client_address}: {data.decode()}")

        # 4. 发送响应数据
        server_socket.sendto(b"Hello, Client!", client_address)

if __name__ == "__main__":
    start_udp_server()
代码解析:
  1. socket.AF_INET:使用IPv4地址族。
  2. socket.SOCK_DGRAM:使用UDP协议。
  3. bind(('localhost', 12345)):将Socket绑定到localhost12345端口。
  4. recvfrom(1024):接收客户端发送的数据,最多1024字节,返回的是数据和客户端的地址(client_address)。
  5. sendto(b"Hello, Client!", client_address):向客户端发送数据,client_address指定了客户端的地址和端口。

2. UDP客户端编程

2.1 UDP客户端代码

客户端创建一个UDP套接字,发送数据到服务器,并接收来自服务器的响应。

import socket

def start_udp_client():
    # 1. 创建UDP套接字
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    # 2. 发送数据到服务器
    message = "Hello, Server!"
    client_socket.sendto(message.encode(), ('localhost', 12345))  # 发送数据到服务器

    # 3. 接收服务器的响应
    response, server_address = client_socket.recvfrom(1024)  # 接收来自服务器的响应
    print(f"Received from server: {response.decode()}")

    # 4. 关闭连接
    client_socket.close()

if __name__ == "__main__":
    start_udp_client()
代码解析:
  1. socket.AF_INET:使用IPv4地址族。
  2. socket.SOCK_DGRAM:使用UDP协议。
  3. sendto(message.encode(), ('localhost', 12345)):通过sendto()方法将数据发送到指定的服务器IP和端口。发送的数据必须是字节类型,因此需要调用encode()
  4. recvfrom(1024):接收来自服务器的数据,最多接收1024字节,并返回数据和服务器的地址。
  5. close():关闭Socket连接。

3. UDP编程的特点与优势

  • 无连接性:UDP是无连接的协议,客户端和服务器不需要进行连接的建立和拆除。发送数据时无需确认接收方是否准备好接收。
  • 简单快速:由于没有连接的开销,UDP适合实时性要求高、数据量较小、丢包可以容忍的场景,例如视频流、语音通信、在线游戏等。
  • 不保证可靠性:UDP不会确保数据包的到达、顺序或完整性,数据包可能会丢失、重复或者顺序错乱。
  • 适用于广播和多播:UDP支持广播(将数据发送到网络中的所有主机)和多播(将数据发送到特定的一组主机)。

4. 异常处理

UDP虽然不需要建立连接,但客户端和服务器仍然可能遇到一些网络错误。可以使用try/except来捕获和处理异常。

import socket

def start_udp_server():
    try:
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        server_socket.bind(('localhost', 12345))

        print("UDP server is waiting for messages...")
        while True:
            data, client_address = server_socket.recvfrom(1024)
            print(f"Received message from {client_address}: {data.decode()}")
            server_socket.sendto(b"Hello, Client!", client_address)
    except socket.error as e:
        print(f"Socket error: {e}")
    finally:
        server_socket.close()
        print("Server socket closed.")

if __name__ == "__main__":
    start_udp_server()

在此代码中,try-except用于捕获任何Socket错误,例如绑定失败或网络不可用等。


5. UDP与TCP的比较

特性UDPTCP
连接类型无连接面向连接
可靠性不可靠(可能丢包、重复、乱序)可靠(保证数据顺序和完整性)
速度快速较慢(因有连接建立和确认机制)
数据完整性需要应用层保证自动保证数据完整性和顺序
适用场景实时通信(视频、音频、游戏等)文件传输、Web、电子邮件等应用

6. 总结

  • UDP编程通过Python的socket模块实现相对简单,适用于不需要高可靠性的场景。
  • UDP的优势在于快速传输,不需要建立连接,因此适合实时性要求高的应用场景,但其不保证数据传输的可靠性和顺序性。
  • UDP的缺点是它不提供数据包的完整性、顺序保证以及错误检测,所以开发者需要自己处理丢包、数据重发等问题。

实例一,UDP的发送方

from socket import socket,AF_INET, SOCK_DGRAM
#1,创建socket对象
send_socket=socket(AF_INET,SOCK_DGRAM)
#2,准备发送数据
date=input('输入需要发送的数据')
#3,指定接收的IP和端口
ip_port=('127.0.0.1',8888)
#4,发送数据
send_socket.sendto(date.encode('utf-8'),ip_port)

#接收来自接收方的回复数据
recv_data,addr=send_socket.recvfrom(1024)
print('接收到的数据为:',recv_data.decode('utf-8'))

#5,关闭socketd对象
send_socket.close()

实例二,UDP的接收方

from socket import socket,AF_INET,SOCK_DGRAM
#1,创建socket对象
recv_socket=socket(AF_INET,SOCK_DGRAM)
#2,绑定IP地址和端口
recv_socket.bind(('127.0.0.1',8888))
#3,接收来自发送方的数据
recv_date,addr=recv_socket.recvfrom(1024)
print('接收到的数据:',recv_date.decode('utf-8'))

#4,准备回复对方的数据
date=input('请输入需要回复的数据')
#5,回复
recv_socket.sendto(date.encode('utf-8'),addr)

#6,关闭
recv_socket.close()

UDP编程接收方与发送方启动运行无先后,但先启动运行发送方,数据会丢包

实例三,模拟客服咨询小程序

客服端代码

from socket import socket,AF_INET,SOCK_DGRAM
#1,创建socket对象
recv_socket=socket(AF_INET,SOCK_DGRAM)
#2,绑定IP地址和端口
recv_socket.bind(('127.0.0.1',8888))

while True:
    #3,接收发送过来的数据
    recv_data,addr=recv_socket.recvfrom(1024)
    print('客户说:',recv_data.decode('utf-8'))
    if recv_data.decode('utf-8') =='bye':
        break
    #4,准备回复对方的数据
    date=input('客服回:')

    #5,发送
    recv_socket.sendto(date.encode('utf-8'),addr)

#6,关闭socket对象
recv_socket.close()

咨询端代码

from socket import socket,AF_INET,SOCK_DGRAM
#1,创建socket对象
send_socket=socket(AF_INET,SOCK_DGRAM)

while True:
    #2,准备发送的数据
    date=input('客户说:')
    #3,发送
    send_socket.sendto(date.encode('utf-8'),('127.0.0.1',8888))
    if date == 'bye':
        break
    #4,接收来自客服端的回复
    recv_data,addr=send_socket.recvfrom(1024)
    print('客服回:',recv_data.decode('utf-8'))

#5,关闭socket对象
send_socket.close()

相关文章:

  • PostgreSQL:备库的延迟问题处理步骤
  • 基于LSTM的情感分析
  • 从入门到精通:Postman 实用指南
  • 【玩转全栈】----Django模板语法、请求与响应
  • OpenGL ES -> 投影变换矩阵完美解决绘制GLSurfaceView绘制图形拉伸问题
  • HBase简介
  • 2025年金三银四经典自动化测试面试题
  • [Unity角色控制专题] (借助ai)详细解析官方第三人称控制器
  • UNIX网络编程学习记录2-第一章
  • Centos 7安装docker
  • 网络安全-攻击流程-应用层
  • 五十天精通硬件设计第32天-S参数
  • DeepSeek在linux下的安装部署与应用测试
  • GPU(Graphics Processing Unit)详解
  • STM32的HAL库开发---ADC
  • Deepseek PHP API调用指南
  • 蓝桥杯篇---IAP15F2K61S2串口
  • STM32的启动流程
  • 基于STM32的智能路灯节能控制系统
  • 【设计模式】01- 一文理解常用设计模式-“创建型模式”篇
  • 人民日报读者点题:规范涉企执法,怎样防止问题反弹、提振企业信心?
  • 一季度煤价持续下探,多家煤炭巨头营收下滑、净利润降约两成
  • 印度加大应对力度,吊销所有巴基斯坦公民签证
  • 下周起上海浦东将投放5000万元消费券,预计分五周发放
  • 最高法典型案例:学生在校受伤,学校并非必然担责
  • 一季度提高两只医药基金股票仓位,中欧基金葛兰加仓科伦药业、百利天恒