python【网络编程】

Python 提供了两个级别访问的网络服务:

  • 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
  • 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。

Socket

Socket 又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

创建套接字

使用 socket() 函数:

socket.socket([family[, type[, proto]]])

  • family:套接字家族可以是 AF_UNIX 或者 AF_INET
  • type:套接字类型可以根据是面向连接的还是非连接分为 SOCK_STREAM 或 SOCK_DGRAM
  • proto:一般不填默认为0

Socket 对象(内建)方法

服务器端套接字

  • s.bind():绑定地址元组(host,port)到套接字。
  • s.listen():开始TCP监听。backlog指定在拒绝连接之前,操作系统可以挂起的最大连接数量。该值至少为1,大部分应用程序设为5就可以了。
  • s.accept():被动接受TCP客户端连接,(阻塞式)等待连接的到来客户端套接字
  • s.connect():主动初始化TCP服务器连接。一般address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。
  • s.connect_ex():connect()函数的扩展版本,出错时返回出错码,而不是抛出异常。

公共用途的套接字函数

  • s.recv():接收TCP数据,数据以字符串形式返回,bufsize指定要接收的最大数据量。flag提供有关消息的其他信息,通常可以忽略。
  • s.send():发送TCP数据,将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。
  • s.sendall():完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。
  • s.recvfrom():接收UDP数据,与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。
  • s.sendto():发送UDP数据,将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。
  • s.close():关闭套接字 s.getpeername() 返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。
  • s.getsockname():返回套接字自己的地址。通常是一个元组(ipaddr,port)。
  • s.setsockopt(level,optname,value):设置给定套接字选项的值。
  • s.getsockopt(level,optname[.buflen]):返回套接字选项的值。
  • s.settimeout(timeout):设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如connect())。
  • s.gettimeout():返回当前超时期的值,单位是秒,如果没有设置超时期,则返回None。
  • s.fileno():返回套接字的文件描述符。
  • s.setblocking(flag):如果 flag 为 False,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用 recv() 没有发现任何数据,或 send() 调用无法立即发送数据,那么将引起 socket.error 异常。
  • s.makefile():创建一个与该套接字相关连的文件。


TCP 编程

由于TCP连接具有安全可靠的特性,应用更为广泛。创建TCP连接时,起连接的叫客户端,被动响应连接的叫服务器。一个TCP连接就建立起来了,后面的通信就是发送网页内容了。

创建TCP服务器

完成一个 TCP 服务器功能需要的流程如下:

  1. 使用socket()创建一个套接字;
  2. 使用 bind()绑定 IP和port;
  3. 使用listen()使套接字变为可被动连接;
  4. 使用accept()等待客户端的连接;
  5. 使用recv/send()接收发送数据。

server.py

import socket

# 创建 socket 对象:TCP/IP套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 获取本地主机名
host = socket.gethostname()

# 设置端口号
port = 8080

# 绑定端口号
server_socket.bind((host, port))

# 设置最大连接数,超过后排队
server_socket.listen(5)

# 建立客户端连接
client_socket, addr = server_socket.accept()
print("TCP连接已建立")
print("连接地址: %s" % str(addr))

# 发送TCP数据
msg = '欢迎访问服务器!' + "\r\n"
client_socket.send(msg.encode('utf-8'))

# 接收来自客户端的数据
info = client_socket.recv(1024).decode()

while info != 'byebye':
    if info:
        print("服务器接收到的内容:" + info)

    send_data = input("回复客户端:")
    client_socket.send(send_data.encode())

    info = client_socket.recv(1024).decode()
    if info == 'byebye':
        client_socket.send('byebye'.encode())


# 关闭客户端套接字
client_socket.close()
# 关闭服务器套接字
server_socket.close()

print("已关闭端到端连接")

client.py

import socket

# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 获取本地主机名
host = socket.gethostname()

# 设置端口号
port = 8080

# 连接服务,指定主机和端口
s.connect((host, port))
print("已连接服务器")

# 接收小于 1024 字节的数据
msg = s.recv(1024)
print("收到服务器信息:" + msg.decode('utf-8'))

send_data = ''

while send_data != 'byebye':
    # 发送消息
    send_data = input("客户端发送消息:")
    s.send(send_data.encode())

    # 接收服务器的数据
    msg = s.recv(1024)
    print("收到服务器回复:" + msg.decode('utf-8'))


# 关闭套接字
s.close()

示例结果:

注意:先启动服务器,否则会直接拒绝客服端发起的连接请求。

UDP 编程

UDP 服务器不是面向连接的,除了等待传入连接之外,几乎不需要其他工作。

  • 服务器使用 recvfrom() 方法接收客户端的数据和地址信息,然后使用 sendto() 方法将转换后的温度数据发送回客户端。
  • 客户端使用 sendto() 方法发送摄氏温度数据到服务器,并使用 recvfrom() 方法接收服务器的回复。 

server.py

import socket

# 创建 UDP socket 对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 获取本地主机名
host = socket.gethostname()

# 设置端口号
port = 8080

# 绑定端口号
server_socket.bind((host, port))

print("UDP服务器已启动,等待客户端连接...")

while True:
    # 接收来自客户端的数据和地址信息
    data, addr = server_socket.recvfrom(1024)
    print("收到客户端数据:", data.decode('utf-8'), "来自", addr)

    if data.decode('utf-8').lower() == 'byebye':
        server_socket.sendto('byebye'.encode(), addr)
        print("客户端请求退出,服务器也将退出.")
        break

    try:
        # 将接收到的摄氏温度转换为华氏温度
        celsius = float(data.decode('utf-8'))
        fahrenheit = (celsius * 9/5) + 32
        response = f"{celsius}°C表示的是{fahrenheit}°F"
    except ValueError:
        response = "输入错误,请输入有效的摄氏温度值!"

    # 发送转换后的温度给客户端
    server_socket.sendto(response.encode('utf-8'), addr)

# 关闭服务器套接字
server_socket.close()
print("服务器已关闭")

client.py

import socket

# 创建 UDP socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 获取本地主机名
host = socket.gethostname()

# 设置端口号
port = 8080

while True:
    # 发送消息
    send_data = input("请输入摄氏温度(°C):")
    s.sendto(send_data.encode(), (host, port))

    # 接收服务器的数据
    msg, addr = s.recvfrom(1024)
    print("收到服务器回复:", msg.decode('utf-8'))

    if send_data.lower() == 'byebye':
        break

# 关闭套接字
s.close()

示例结果:


Python Internet 模块

协议功能用处端口号Python 模块
HTTP网页访问80httplib, urllib, xmlrpclib
NNTP阅读和张贴新闻文章,俗称为"帖子"119nntplib
FTP文件传输20ftplib, urllib
SMTP发送邮件25smtplib
POP3接收邮件110poplib
IMAP4获取邮件143imaplib
Telnet命令行23telnetlib
Gopher信息查找70gopherlib, urllib


 JSON 模块

JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。

  • JSON 使用 Javascript 语法来描述数据对象,但是仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。 目前非常多的动态编程语言都支持 JSON。
  • JSON 具有自我描述性,更易理解。

Python3 中可以使用 json 模块来对 JSON 数据进行编解码,它包含了两个函数:

  • json.dumps(): 对数据进行编码。
  • json.loads(): 对数据进行解码。

Python 编码为 JSON 类型转换对应表

PythonJSON
dictobject
list, tuplearray
strstring
int, float, int- & float-derived Enumsnumber
Truetrue
Falsefalse
Nonenull

JSON 解码为 Python 类型转换对应表

JSONPython
objectdict
arraylist
stringstr
number (int)int
number (real)float
trueTrue
falseFalse
nullNone


urllib 模块

Python urllib 库用于操作网页 URL,并对网页的内容进行抓取处理。urllib 包 包含以下几个模块:

  • urllib.request - 打开和读取 URL。
  • urllib.error - 包含 urllib.request 抛出的异常。
  • urllib.parse - 解析 URL。
  • urllib.robotparser - 解析 robots.txt 文件。

urllib.request

urllib.request 定义了一些打开 URL 的函数和类,包含授权验证、重定向、浏览器 cookies等。urllib.request 可以模拟浏览器的一个请求发起过程。

使用 urllib.request 的 urlopen 方法来打开一个 URL,语法格式:

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

  • url:url 地址。
  • data:发送到服务器的其他数据对象,默认为 None。
  • timeout:设置访问超时时间。
  • cafile 和 capath:cafile 为 CA 证书, capath 为 CA 证书的路径,使用 HTTPS 需要用到。
  • cadefault:已经被弃用。
  • context:ssl.SSLContext类型,用来指定 SSL 设置。

抓取网页一般需要对 headers(网页头信息)进行模拟,需要使用到 urllib.request.Request 类:

class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

  • url:url 地址。
  • data:发送到服务器的其他数据对象,默认为 None。
  • headers:HTTP 请求的头部信息,字典格式。
  • origin_req_host:请求的主机地址,IP 或域名。
  • unverifiable:很少用这个参数,用于设置网页是否需要验证,默认是 False。
  • method:请求方法, 如 GET、POST、DELETE、PUT等。

 示例:

import urllib.request

def get_webpage_content(url):
    # 创建一个 Request 对象
    request = urllib.request.Request(url)
    # 发送 GET 请求
    with urllib.request.urlopen(request) as response:
        # 读取响应内容
        html_content = response.read()
        # 将字节内容转换为字符串
        content = html_content.decode('utf-8')

        return content

# 假设我们要获取的网页是 http://example.com
url = 'https://jsonplaceholder.typicode.com/todos/1'
content = get_webpage_content(url)
print(content)  # 打印网页内容

输出结果: 

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}


requests 模块

Python requests 是一个常用的 HTTP 请求库,可以方便地向网站发送 HTTP 请求,并获取响应结果。requests 模块比 urllib 模块更简洁。

# 导入 requests 包
import requests
# 发送请求
x = requests.get('https://www.csdn.com/')
# 返回网页内容
print(x.text)

每次调用 requests 请求之后,会返回一个 response 对象,该对象包含了具体的响应信息,如状态码、响应头、响应内容等:

print(response.status_code)  # 获取响应状态码
print(response.headers)  # 获取响应头
print(response.content)  # 获取响应内容
# 导入 requests 包
import requests
# 发送请求
x = requests.get('https://www.csdn.com/')
# 返回 http 的状态码
print(x.status_code)
# 响应状态的描述
print(x.reason)
# 返回编码
print(x.apparent_encoding)

方法如下:

方法描述
delete(url, args)发送 DELETE 请求到指定 url
get(url, params, args)发送 GET 请求到指定 url
head(url, args)发送 HEAD 请求到指定 url
patch(url, data, args)发送 PATCH 请求到指定 url
post(url, data, json, args)发送 POST 请求到指定 url
put(url, data, args)发送 PUT 请求到指定 url
request(method, url, args)向指定的 url 发送指定的请求方法

示例:

import requests

# 假设的 RESTful API URL
api_url = 'https://jsonplaceholder.typicode.com/posts/1'

# 发送 GET 请求
def send_get_request(url, params=None):
    response = requests.get(url, params=params)
    return response.json()  # 假设响应内容是 JSON 格式

# 发送 POST 请求
def send_post_request(url, data=None, json=None):
    response = requests.post(url, data=data, json=json)
    return response.json()  # 假设响应内容是 JSON 格式

# 发送 PUT 请求
def send_put_request(url, data=None):
    response = requests.put(url, data=data)
    return response.json()  # 假设响应内容是 JSON 格式

# 发送 DELETE 请求
def send_delete_request(url, params=None):
    response = requests.delete(url, params=params)
    return response.json()  # 假设响应内容是 JSON 格式

# 发送 PATCH 请求
def send_patch_request(url, data=None):
    response = requests.patch(url, data=data)
    return response.json()  # 假设响应内容是 JSON 格式

# 示例使用
get_response = send_get_request(api_url, params={'query': 'value'})
print('GET 请求响应:', get_response)

post_response = send_post_request(api_url, json={'key': 'value'})
print('POST 请求响应:', post_response)

put_response = send_put_request(api_url, data={'key': 'new_value'})
print('PUT 请求响应:', put_response)

delete_response = send_delete_request(api_url)
print('DELETE 请求响应:', delete_response)

patch_response = send_patch_request(api_url, data={'key': 'updated_value'})
print('PATCH 请求响应:', patch_response)

运行结果:

GET 请求响应: {'userId': 1, 'id': 1, 'title': 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit', 'body': 'quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto'}
POST 请求响应: {}
PUT 请求响应: {'key': 'new_value', 'id': 1}
DELETE 请求响应: {}
PATCH 请求响应: {'userId': 1, 'id': 1, 'title': 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit', 'body': 'quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto', 'key': 'updated_value'}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值