目录
网络编程
Socket是网络编程的一个抽象概念。通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可。
tcp和udp两种方式、全双工的呦(可以同时发、收)
TCP是建立可靠连接、UDP则是面向无连接的协议
TCP编程
socket.SOCK_STREAM tcp协议
互发数据都是用的send(数据)方法
互收数据都是用的recv(字节)
- 客户端
-
# 导入socket库: import socket # 创建一个socket # AF_INET指定使用IPv4协议,如果要用更先进的IPv6,就指定为AF_INET6 # SOCK_STREAM指定使用面向流的TCP协议 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 建立连接: s.connect(('127.0.0.1', 9999)) # 接收欢迎消息: print(s.recv(1024).decode('utf-8')) for data in [b'Michael', b'Tracy', b'Sarah']: # 发送数据: s.send(data) print(s.recv(1024).decode('utf-8')) s.send(b'exit') s.close()
- 服务器端
-
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 监听端口: s.bind(('127.0.0.1', 9999)) # 开始监听端口,传入的参数指定等待连接的最大数量 s.listen(5) # 每个连接都必须创建新线程(或进程)来处理 # 否则,单线程在处理连接的过程中,无法接受其他客户端的连接 def tcplink(sock, addr): print('Accept new connection from %s:%s...' % addr) sock.send(b'Welcome!') while True: data = sock.recv(1024) time.sleep(1) if not data or data.decode('utf-8') == 'exit': break sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8')) sock.close() print('Connection from %s:%s closed.' % addr) # 永久循环来接受来自客户端的连接 while True: # accept()会等待并返回一个客户端的连接 sock, addr = s.accept() # 创建新线程来处理TCP连接: t = threading.Thread(target=tcplink, args=(sock, addr)) t.start()
UDP编程
服务器端无需 listen(),客户端也无需connect()
socket.SOCK_DGRAM udp协议
互发数据都是用:sendto()方法
互收数据:服务器recvfrom(字节)、客户端recv(字节)
- 客户端
-
import socket # SOCK_DGRAM指定了这个Socket的类型是UDP s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) for data in [b'Michael', b'Tracy', b'Sarah']: # 发送数据: s.sendto(data, ('127.0.0.1', 9999)) # 接收数据: print(s.recv(1024).decode('utf-8')) s.close()
- 服务器
-
import socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 绑定端口: s.bind(('127.0.0.1', 9999)) while True: # 接收数据: data, addr = s.recvfrom(1024) print('Received from %s:%s.' % addr) s.sendto(b'Hello, %s!' % data, addr)
电子邮件
SMTP发送邮件
SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件
Python对SMTP支持有smtplib
和email
两个模块,email
负责构造邮件,smtplib
负责发送邮件
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
def _format_addr(s):
name, addr = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), addr))
# 第一个参数就是邮件正文,'plain'表示纯文本,utf-8编码保证多语言兼容性
msg = MIMEText('hello, send by Python...', 'plain', 'utf-8')
# 邮件主题、如何显示发件人、收件人等信息包含在发给MTA的文本中
msg['From'] = _format_addr('Python爱好者 <%s>' % from_addr)
msg['To'] = _format_addr('管理员 <%s>' % to_addr)
msg['Subject'] = Header('来自SMTP的问候……', 'utf-8').encode()
# 通过SMTP发出去
# 输入Email地址和口令:
from_addr = input('From: ')
password = input('Password: ')
# 输入收件人地址:
to_addr = input('To: ')
# 输入SMTP服务器地址:
smtp_server = input('SMTP server: ')
import smtplib
server = smtplib.SMTP(smtp_server, 25) # SMTP协议默认端口是25
# 可以打印出和SMTP服务器交互的所有信息
server.set_debuglevel(1)
# 登录SMTP服务器
server.login(from_addr, password)
# 可以发给多个人,所以用了list
server.sendmail(from_addr, [to_addr], msg.as_string())
server.quit()
POP3收取邮件
收取邮件最常用的协议是POP协议,目前版本号是3,俗称POP3
Python内置一个poplib
模块,实现了POP3协议,可以直接用来收邮件
收取邮件分两步:
第一步:用poplib
把邮件的原始文本下载到本地;
第二部:用email
解析原始文本,还原为邮件对象。
import poplib
# 输入邮件地址, 口令和POP3服务器地址:
email = input('Email: ')
password = input('Password: ')
pop3_server = input('POP3 server: ')
# 连接到POP3服务器:
server = poplib.POP3(pop3_server)
# 可以打开或关闭调试信息:
server.set_debuglevel(1)
# 可选:打印POP3服务器的欢迎文字:
print(server.getwelcome().decode('utf-8'))
# 身份认证:
server.user(email)
server.pass_(password)
# stat()返回邮件数量和占用空间:
print('Messages: %s. Size: %s' % server.stat())
# list()返回所有邮件的编号:
resp, mails, octets = server.list()
# 可以查看返回的列表类似[b'1 82923', b'2 2184', ...]
print(mails)
# 获取最新一封邮件, 注意索引号从1开始:
index = len(mails)
resp, lines, octets = server.retr(index)
# lines存储了邮件的原始文本的每一行,
# 可以获得整个邮件的原始文本:
msg_content = b'\r\n'.join(lines).decode('utf-8')
# 稍后解析出邮件:
msg = Parser().parsestr(msg_content)
# 可以根据邮件索引号直接从服务器删除邮件:
# server.dele(index)
# 关闭连接:
server.quit()