Python 网络客户端编程

如果我们把因特网简化成一个数据交换中心,数据交换的参与者是一个服务提供者和一个服务的使用者。服务器就是服务者,或叫生产者,它提供服务,一般只有一个服务器,和多个消费者。因特网中最流行的事情就是文件的交换。文件交换无处不在。

 

文本传输协议(FTP)主要用于匿名下载公共文件,也可以用于在两台电脑之间传输文件。

下面这个例子简单写了一个连接FTP并下载文件

 

#!/usr/bin/ env python
#coding=utf-8

import ftplib
import os
import socket

HOST = 'ftp.sjtu.edu.cn'
DIRN = 'pub/rfc/fyi/'
FILE = 'fyi10.txt'

def main():
    try:
        f = ftplib.FTP(HOST)
    except (socket.error, socket.gaierror), e:
        print('ERROR: cannot reach "%s"' % HOST)
        return
    print('***Connected to host "%s"' % HOST)

    try:
        f.login()
    except ftplib.error_perm:
        print('ERROR: cannot login anonymously')
        f.quit()
        return
    print('*** Logged in as "anonymously"')

    try:
        f.cwd(DIRN)
    except ftplib.error_perm:
        print('ERROR: cannot cd to "%s"' % DIRN)
        f.quit()
        return
    print('*** Changed to "%s" folder' %DIRN)

    try:
        f.retrbinary('RETR %s' %FILE, open(FILE, 'wb').write)
    except ftplib.error_perm:
        print('ERROR: cannot read file "%s"' % FILE)
        os.unlink(FILE)
    else:
        print('*** Downloaded "%s" to CWD' %FILE)
        f.quit()
        return


if __name__ == '__main__':
    main()



网络新闻传输协议(NNTP)与FTP的操作方式很像,而且简单的多。FTP需要用不同的端口来做登录,数据传输和控制,而NNTP只使用一个标准端口119来做通讯。

我们来下载Python语言新闻组com.lang.python里的一篇文章。


#!/usr/bin/ env python
#coding=utf-8

import nntplib
import  socket

HOST = 'your.nntp.server'
GRNM = 'group name'
USER = 'user'
PASS = 'password'

def displayFirst20(data):
    '''
    获取 data 内前20个有意义的行
    '''
    print('*** first (<=20) meaningful lines:\n')
    count = 0    #创建一个计数器
    '''
    获取文章行列表,rstrip()方法删除字符串尾随的空格
    '''
    lines = (line.rstrip() for line in data)
    lastBlank = True     #上一行为空的标识,作为判断条件
    for line in lines:
        if line:
            lower = line.lower()  #将 line 内容转换小写
            if (lower.startswith('>') and not \
                lower.startswith('>>>')) or \
                lower.startswith('|') or \
                lower.startswith('in article') or \
                lower.endswith('writes:') or \
                lower.endswith('wrote:'):
                continue

        if not lastBlank or (lastBlank and line):  #如果上一行不是空行,或者上一行为空行,但当前行不为空时
            print('    %s' % line)
            if line:         #如果当前行不为空,计数器+1,lastBank 为 false,上一行不为空
                count += 1
                lastBlank = False
            else:
                lastBlank = True

        if count == 20:
            break

def main():
    try:
        n = nntplib.NNTP(HOST)    #尝试连接 NNTP 服务器,如果失败就退出
        #,user=USER,password=PASS
    except socket.gaierror as e:
        print('ERROR:cannot reach host "%s"' % HOST)
        print('    ("%s")' % eval(str(e))[1])
        return
    except nntplib.NNTPPermanentError as e:
        print('ERROR:access denied on "%s"' % HOST)
        print('    %s' % str(e))
        return
    print('****connected to host "%s"' % HOST)

    try:
        rsp, ct , fst, lst, grp = n.group(GRNM)    #尝试读取指定的新闻组
    except nntplib.NNTPTemporaryError as e:      #如果新闻组不存在、或服务器没有保存这个新闻组,或需要身份验证等就退出
        print('ERROR: cannot load group "%s"' % GRNM)
        print('    "%s"' % str(e))
        print('     server may require authentication')
        print('     uncomment/edit login line above')
        n.quit()
        return
    except nntplib.NNTPTemporaryError as e:
        print('ERROR: group "%s" unavaliable' % GRNM)
        print('    %s' % str(e))
        n.quit()
        return
    print('*** found newsgroup "%s"' % GRNM)

    rng = '%s-%s' % (lst,lst)     #给定想要提取消息头的文章范围,因为要获取最后一条信息,所以范围是最后--最后
    rsp, frm = n.xhdr('from',rng)     #获取制定范围的文章信息:服务器响应,指定范围的消息头列表 frm-文章来源
    rsp, sub = n.xhdr('subject',rng)    #sub 文章子标题
    rsp, dat = n.xhdr('date',rng)   #文章主文本
    print('''
            *** found last article (#%s):
            from:%s
            subject:%s
            date:%s
            ''' % (lst, frm[0][1], sub[0][1], dat[0][1]))

            '''
            由于上边选取的范围只有最后一个,所以只获取第一个元素【0】,数
            据元素是一个长度为2的元组,包含文章编号和数据字符串,因此数据字符串frm[0][1]
            '''
    rsp, anum, mid, data = n.body(lst) #根据最后一篇文章的 id 获取(服务器响应信息,文章编号,消息 id,文章所有行)
    displayFirst20(data)  #调用方法只保存前20个有意义的行
    n.quit()      #退出

if __name__ == '__main__':
    main()


 

电子邮件e-mail

SMTP(简单邮件传输协议)是在因特网上MTA之间用于信息交换的最常用的MTS。它被MTA用来把e-mail从一台主机传送到另一台主机。在发送email的时候,必须要连接到一个外部的SMTP服务器,这时,你的邮件程序是一个SMTP客户端。

POP(邮局协议),让用户的工作站可以访问邮箱服务器里的邮件。邮件要能从工作站通过SMTP发送到邮件服务器。POP3指的是POP协议最常用的第三版。


#!/usr/bin/ env python
#coding=utf-8

from smtplib import SMTP
from smtplib import SMTPRecipientsRefused
from poplib import POP3
from time import sleep
import sys

smtpserver = 'smtp.163.com'
pop3server = 'pop.163.com'
emailaddr = 'username@163.com'
username = 'username'
password = 'password'

# 组合邮件格式
origHeaders = ['From: username@163.com',
               'To: username@163.com',
               'Subject: test msg']
origBody = ['test ', 'smtp', 'pop3']
origMsg = '\r\n\r\n'.join(['\r\n'.join(origHeaders), '\r\n'.join(origBody)])

# 发送邮件部分
def sendMail():
    sendSer = SMTP(smtpserver)
    sendSer.set_debuglevel(1)
    print sendSer.ehlo()[0]  # 服务器属性等
    sendSer.login(username, password)  # 邮箱需要验证
    try:
        errs = sendSer.sendmail(emailaddr, emailaddr, origMsg)
    except SMTPRecipientsRefused:
        print 'server refused....'
        sys.exit(1)
    sendSer.quit()
    assert len(errs) == 0, errs

    print '******send a mail ....OK!'
    sleep(10)  # 等待10秒
    print '******Now get the mail .....*******'

# 开始接收邮件
def receiveMail():
    revcSer = POP3(pop3server)
    revcSer.user(username)
    revcSer.pass_(password)

    rsp, msg, siz = revcSer.retr(revcSer.stat()[0])
    sep = msg.index('')
    if msg:
        for i in msg:
            print i
    revcBody = msg[sep + 1:]
    assert origBody == revcBody
    print '******successful get ....'

def main():
    sendMail()
    receiveMail()

if __name__ == '__main__':
    main()


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值