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个步骤。
socket=socket.socket(familly,type)
要创建1个套接字,你必须使用socket.socket()函数,它在socket模块,其中有1般的语法:
下面是参数的描写:
-
socket_family: 这是AF_UNIX或AF_INET,正如我刚才解释.
-
socket_type: 这是SOCK_STREAM,或为SOCK_DGRAM.
-
protocol: 这通常被不用关心,默许为0.@H_404_41@
第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))
第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的规则中。
1.2 urllib 和 urllib2 模块
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'>
@H_404_41@
@H_404_41@@H_404_41@
@H_404_41@
1.3 其他与网络相干的模块
除 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的客户端支持
@H_404_41@
@H_404_41@
@H_404_41@
Python网络模块
可使用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 | 143 | imaplib | |
Telnet | Command lines | 23 | telnetlib |
Gopher | Document transfers | 70 | gopherlib,urllib |
请查看上面提到所有库的合作与FTP,SMTP的POP,IMAP协议.
@H_404_41@@H_404_41@
@H_404_41@
@H_404_41@
最后:
1、建立socket
建立socket对象需要弄清通讯类型和协议家族。通讯类型指明了用甚么协议来传输数据。协议的例子包括IPv4、IPv6、IPXSPX、AFP。对internet通讯,通讯类型基本上都是AF_INET(和IPv4对应)。协议家族1般表示TCP通讯的SOCK_STREAM或表示UDP通讯的SOCK_DGRAM。因此对TCP通讯,建立1个socket连接的语句为:@H_404_41@ s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)@H_404_41@ 对UDP通讯,建立1个socket连接的语句为:@H_404_41@ s=socket.socket(socket.AF_INET,SOCK_DGRAM)
2、连接socket
连接socket需要提供1个tuple,包括host(主机名或IP)和port(远程端口),类似代码为:@H_404_41@ s.connect(("www.baidu.com",80)
3、寻觅端口号
socket库中利用getservbyname()函数可以查询端口号,1般需要两个参数:1是协议名,如http、smtp、pop3等,1个是端口名,如tcp、udp
例如:
import socket@H_404_41@ s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)@H_404_41@ port=socket.getservbyname('http','tcp')@H_404_41@ port的返回值为80。若改成:@H_404_41@ port=socket.getservbyname('smtp','tcp')@H_404_41@ port的返回值为25。
4、从socket获得信息
建立socket连接后,可以通过getsockname()获得本身的ip地址和端口号,也能够通过getpeername()显示远程机器的ip地址和端口号。@H_404_41@ 如:在python shell中
>>> import socket@H_404_41@ >>> s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)@H_404_41@ >>> port=socket.getservbyname('http','tcp')@H_404_41@ >>> s.connect(('www.baidu.com',port))@H_404_41@ >>> print s.getsockname()@H_404_41@ ('192.168.87.138',3213)@H_404_41@ >>> print s.getpeername()@H_404_41@ ('220.181.111.147',80)
Socket 模块的类方法@H_404_41@ 类方法 说明@H_404_41@ Socket 低层网络接口(每一个 BSD API)@H_404_41@ socket.socket(family,type) 创建并返回1个新的 socket 对象@H_404_41@ socket.getfqdn(name) 将使用点号分隔的 IP 地址字符串转换成1个完全的域名@H_404_41@ socket.gethostbyname(hostname) 将主机名解析为1个使用点号分隔的 IP 地址字符串@H_404_41@ socket.fromfd(fd,family,type) 从现有的文件描写符创建1个 socket 对象
Socket 模块的实例方法
实例方法 说明@H_404_41@ sock.bind( (adrs,port) ) 将 socket 绑定到1个地址和端口上@H_404_41@ sock.accept() 返回1个客户机 socket(带有客户机真个地址信息)@H_404_41@ sock.listen(backlog) 将 socket 设置成监听模式,能够监听 backlog 外来的连接要求@H_404_41@ sock.connect( (adrs,port) ) 将 socket 连接到定义的主机和端口上@H_404_41@ sock.recv( buflen[,flags] ) 从 socket 中接收数据,最多 buflen 个字符@H_404_41@ sock.recvfrom( buflen[,flags] ) 从 socket 中接收数据,最多 buflen 个字符,同时返回数据来源的远程主机和端口号@H_404_41@ sock.send( data[,flags] ) 通过 socket 发送数据@H_404_41@ sock.sendto( data[,flags],addr ) 通过 socket 发送数据@H_404_41@ sock.close() 关闭 socket@H_404_41@ sock.getsockopt( lvl,optname ) 取得指定 socket 选项的值@H_404_41@ sock.setsockopt( lvl,optname,val ) 设置指定 socket 选项的值
举例:@H_404_41@ >>> import socket@H_404_41@ >>> socket.gethostbyname('www.baidu.com')@H_404_41@ '220.181.111.147'@H_404_41@ >>> socket.gethostbyname('www.126.com')@H_404_41@ '123.125.50.22'@H_404_41@ >>> socket.getfqdn('123.125.50.22')@H_404_41@ '123.125.50.22'@H_404_41@ 这里getfqdn却不能返回域名?
5、处理毛病@H_404_41@ 关于毛病异常的处理,主要就是用try、except语句。如将python网络编程学习笔记(1)中gopherclient.py进行1下修改:
@H_404_41@ # -*- coding: cp936 -*-@H_404_41@ ##modify by 小5义@H_404_41@ import socket,sys@H_404_41@ port =70@H_404_41@ host=sys.argv[1]filename=sys.argv[2]
try:@H_404_41@ s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)@H_404_41@ except Socket.error,e:@H_404_41@ print "建立socket毛病:%s"%e
try:@H_404_41@ s.connect((host,port))@H_404_41@ except socket.gaierror,e:@H_404_41@ print "host或端口毛病:%s" %e@H_404_41@ except socket.error,e:@H_404_41@ print "连接毛病:%s" %e
try:@H_404_41@ s.sendall(filename+" ")@H_404_41@ except socket.error,e:@H_404_41@ print "数据发送毛病:%s" %e@H_404_41@ sys.exit(1)
@H_404_41@ while 1:@H_404_41@ try:@H_404_41@ buf=s.recv(2048)@H_404_41@ except socket.error,e:@H_404_41@ print "接收毛病:%s"%e@H_404_41@ sys.exit(1)@H_404_41@ if 'does not exist' in buf:@H_404_41@ print "%s文件不存在" %filename@H_404_41@ else:@H_404_41@ if not len(buf):@H_404_41@ break@H_404_41@ sys.stdout.write(buf)@H_404_41@@H_404_41@
@H_404_41@
参考文献:
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@H_404_41@