1、套接字
套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络利用程序提供者提供当前可移植标准的对象。它们允许程序接受并进行连接,如发送和接受数据。为了建立通讯通道,网络通讯的每一个端点具有1个套接字对象极其重要。
套接字为BSD UNIX系统核心的1部份,而且他们也被许多其他类似UNIX的操作系统包括Linux所采用。许多非BSD UNIX系统(如ms-dos,windows,os/2,mac os及大部份主机环境)都以库情势提供对套接字的支持。
3种最流行的套接字类型是:stream,datagram和raw。stream和datagram套接字可以直接与TCP协议进行接口,而raw套接字则接口到IP协议。但套接字其实不限于TCP/IP。
2、套接字模块
套接字模块是1个非常简单的基于对象的接口,它提供对低层BSD套接字样式网络的访问。使用该模块可以实现客户机和服务器套接字。要在python中建立具有TCP和流套接字的简单服务器,需要使用socket模块。利用该模块包括的函数和类定义,可生成通过网络通讯的程序。1般来讲,建立服务器连接需要6个步骤。
第1步是创建socket对象。调用socket构造函数。
socket=socket.socket(familly,type)
要创建1个套接字,你必须使用socket.socket()函数,它在socket模块,其中有1般的语法:
下面是参数的描写:
socket_family: 这是AF_UNIX或AF_INET,正如我刚才解释.
socket_type: 这是SOCK_STREAM,或为SOCK_DGRAM.
protocol: 这通常被不用关心,默许为0.
第2步则是将socket绑定(指派)到指定地址上,socket.bind(address)
address必须是1个双元素元组,((host,port)),主机名或ip地址+端口号。如果端口号正在被使用或保存,或主机名或ip地址毛病,则引发socke.error异常。
第3步,绑定后,必须准备好套接字,以便接受连接要求。
socket.listen(backlog)
backlog指定了最多连接数,最少为1,接到连接要求后,这些要求必须排队,如果队列已满,则谢绝要求。
第4步,服务器套接字通过socket的accept方法等待客户要求1个连接:
connection,address=socket.accept()
调用accept方法时,socket会进入'waiting'(或阻塞)状态。客户要求连接时,方法建立连接并返回服务器。accept方法返回1个含有俩个元素的元组,形如(connection,address)。第1个元素(connection)是新的socket对象,服务器通过它与客户通讯;第2个元素(address)是客户的internet地址。
第5步是处理阶段,服务器和客户通过send和recv方法通讯(传输数据)。服务器调用send,并采取字符串情势向客户发送信息。send方法返回已发送的字符个数。服务器使用recv方法从客户接受信息。调用recv时,必须指定1个整数来控制本次调用所接受的最大数据量。recv方法在接受数据时会进入'blocket'状态,最后返回1个字符串,用它来表示收到的数据。如果发送的量超过recv所允许,数据会被截断。过剩的数据将缓冲于接受端。以后调用recv时,过剩的数据会从缓冲区删除。
第6步,传输结束,服务器调用socket的close方法以关闭连接。
建立1个简单客户连接则需要4个步骤。
第1步,创建1个socket以连接服务器 socket=socket.socket(family,type)
第2步,使用socket的connect方法连接服务器 socket.connect((host,port))
第3步,客户和服务器通过send和recv方法通讯。
第4步,结束后,客户通过调用socket的close方法来关闭连接。
实例:
这是Socket Server 部份:
import socket
s = socket.socket()
host = socket.gethostname()
port = 8088
s.bind((host,port))
s.listen(5)
while True:
c, addr = s.accept()
print 'Got connection from', addr
c.send('Thank you for connection')
c.close()
这是Socket Client 部份:
import socket
s = socket.socket()
host = socket.gethostname()
port = 8088
s.connect((host,port))
print s.recv(1024)
运行时,请将对应的端口(这里是8088)添加到防火墙的InBound和OutBound的规则中。
urllib
和 urllib2
是Python标准库中最强的的网络工作库。通过这两个库所提供的上层接口,使我们可以像读取本地文件1样读取网络上的文件。而且
urllib2
其实不是 urllib
的升级版本(应当是1种补充),2者是不可相互替换的。
通过使用 urllib
的 urlopen
函数可以很容易的打开远程的文件,以下:
from urllib import urlopen
webpage = urlopen('http://www.cnblogs.com/IPrograming/')
txt = webpage.readline(45)
print txt # !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
也能够通过在通过在路径的前面添加 file:
来访问本地文件:
from urllib import urlopen
webpage = urlopen(r'file:D:Hsr23updADD_ABBR.txt')
txt = webpage.readline(45)
print txt
如果你还可以通过 urllib
提供的 urlretrieve
函数,来直接保存远程文件副本:
from urllib import urlretrieve
webpage = urlretrieve('http://www.cnblogs.com/IPrograming/','C: emp.html')
print type(webpage) # <type 'tuple'>
除 socket、urllib和urllib2这些模块之外标准库还有很多和网络相干的模块,下面的列表是其中的1部份:
===========================================================
模块 描写
===========================================================
asynchat asyncore的增强版本
asyncore 异步socket处理程序
cgi 基本的CGI支持
Cookie Cookie对象操作,主要用于服务器操作
cookielib 客户端cookie支持
email E-mail消息支持(包括MIME)
ftplib FTP客户端模块
gopherlib gopher客户端博客
httplib HTTP客户端模块
imaplib IMAP4客户端模块
mailbox 读取几种邮件的格式
mailcap 通过mailcap文件访问MIME配置
mhlib 访问MH邮箱
nntplib NNTP客户端模块
poplib POP客户端模块
robotparser 支持解析Web服务器的robot文件
SimpleXMLRPCServer 1个简单的XML-RPC服务器
stmpd SMTP服务器模块
smtplib SMTP客户端模块
telnetlib Telnet客户端模块
urlparse 支持解析URL
xmlrpclib XML-RPC的客户端支持
可使用Python中的网络/互联网编程的1些重要的模块列表.
Protocol | Common function | Port No | Python module |
---|---|---|---|
HTTP | Web pages | 80 | httplib, urllib, xmlrpclib |
NNTP | Usenet news | 119 | nntplib |
FTP | File transfers | 20 | ftplib, urllib |
SMTP | Sending email | 25 | smtplib |
POP3 | Fetching email | 110 | poplib |
IMAP4 | Fetching email | 143 | imaplib |
Telnet | Command lines | 23 | telnetlib |
Gopher | Document transfers | 70 | gopherlib, urllib |
请查看上面提到所有库的合作与FTP,SMTP的POP,IMAP协议.
最后:
1、建立socket
建立socket对象需要弄清通讯类型和协议家族。通讯类型指明了用甚么协议来传输数据。协议的例子包括IPv4、IPv6、IPXSPX、AFP。对internet通讯,通讯类型基本上都是AF_INET(和IPv4对应)。协议家族1般表示TCP通讯的SOCK_STREAM或表示UDP通讯的SOCK_DGRAM。因此对TCP通讯,建立1个socket连接的语句为:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
对UDP通讯,建立1个socket连接的语句为:
s=socket.socket(socket.AF_INET,SOCK_DGRAM)
2、连接socket
连接socket需要提供1个tuple,包括host(主机名或IP)和port(远程端口),类似代码为:
s.connect(("www.baidu.com",80)
3、寻觅端口号
socket库中利用getservbyname()函数可以查询端口号,1般需要两个参数:1是协议名,如http、smtp、pop3等,1个是端口名,如tcp、udp
例如:
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
port=socket.getservbyname('http','tcp')
port的返回值为80。若改成:
port=socket.getservbyname('smtp','tcp')
port的返回值为25。
4、从socket获得信息
建立socket连接后,可以通过getsockname()获得本身的ip地址和端口号,也能够通过getpeername()显示远程机器的ip地址和端口号。
如:在python shell中
>>> import socket
>>> s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
>>> port=socket.getservbyname('http','tcp')
>>> s.connect(('www.baidu.com',port))
>>> print s.getsockname()
('192.168.87.138', 3213)
>>> print s.getpeername()
('220.181.111.147', 80)
Socket 模块的类方法
类方法 说明
Socket 低层网络接口(每一个 BSD API)
socket.socket(family, type) 创建并返回1个新的 socket 对象
socket.getfqdn(name) 将使用点号分隔的 IP 地址字符串转换成1个完全的域名
socket.gethostbyname(hostname) 将主机名解析为1个使用点号分隔的 IP 地址字符串
socket.fromfd(fd, family, type) 从现有的文件描写符创建1个 socket 对象
Socket 模块的实例方法
实例方法 说明
sock.bind( (adrs, port) ) 将 socket 绑定到1个地址和端口上
sock.accept() 返回1个客户机 socket(带有客户机真个地址信息)
sock.listen(backlog) 将 socket 设置成监听模式,能够监听 backlog 外来的连接要求
sock.connect( (adrs, port) ) 将 socket 连接到定义的主机和端口上
sock.recv( buflen[, flags] ) 从 socket 中接收数据,最多 buflen 个字符
sock.recvfrom( buflen[, flags] ) 从 socket 中接收数据,最多 buflen 个字符,同时返回数据来源的远程主机和端口号
sock.send( data[, flags] ) 通过 socket 发送数据
sock.sendto( data[, flags], addr ) 通过 socket 发送数据
sock.close() 关闭 socket
sock.getsockopt( lvl, optname ) 取得指定 socket 选项的值
sock.setsockopt( lvl, optname, val ) 设置指定 socket 选项的值
举例:
>>> import socket
>>> socket.gethostbyname('www.baidu.com')
'220.181.111.147'
>>> socket.gethostbyname('www.126.com')
'123.125.50.22'
>>> socket.getfqdn('123.125.50.22')
'123.125.50.22'
这里getfqdn却不能返回域名?
5、处理毛病
关于毛病异常的处理,主要就是用try、except语句。如将python网络编程学习笔记(1)中gopherclient.py进行1下修改:
filename=sys.argv[2]
try:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
except Socket.error,e:
print "建立socket毛病:%s"%e
try:
s.connect((host,port))
except socket.gaierror,e:
print "host或端口毛病:%s" %e
except socket.error,e:
print "连接毛病:%s" %e
try:
s.sendall(filename+"
")
except socket.error,e:
print "数据发送毛病:%s" %e
sys.exit(1)
参考文献:
http://www.jb51.net/article/50857.htm
http://www.cnblogs.com/IPrograming/p/Python-socket.html
http://blog.csdn.net/alpha5/article/details/24122749
http://www.cppblog.com/lai3d/archive/2008/02/19/42919.html
http://www.showerlee.com/archives/1051