socket模块详解,通过这些基础知识可以使我们更好的理解网络编程。
一、网络知识的一些介绍
1、socket 是网络连接端点。 例说:当你的Web浏览器请求www.jb51.net上的主页时(即就是发送HTTP请求),web浏览器会创建一个
socket对象并命令它去连接www.jb51.net的web服务器主机,web服务器也会对来自的请求在一个socket对象上进行监听。客户端和服
务器端各自使用socket来发送和接收消息。
2、使用过程中,每个socket对象都会绑定到一个特定的IP地址和端口。
IP地址是一个由4个数组成的序列,这4个数均是范围 0~255中的值(例如,220,176,36,76);
端口数值的取值范围是0~65535。端口数小于1024的都是为众所周知的网络服务所保留的(例如Web服务使用的80端口);最大的
保留数被存储在socket模块的IPPORT_RESERVED变量中。你也可以为你的程序使用另外的端口数值。
地址127.0.0.1是本机地址;它始终指向当前的计算机。程序可以使用这个地址来连接运行在同一计算机上的其它程序。
域名服务器(DNS)处理名字到IP地址的映射。每个计算机都可以有一个主机名,即使它没有在官方注册。
3、协议:
例如HTTP协议,它是用在Web浏览器与Web服务器之间通信的协议,它是基于TCP协议,而TCP协议又基于IP协议。
当在你自己的两个程序间传送信息的时候,你通常选择TCP或UDP协议。TCP协议在两端间建立一个持续的连接,并且你所发送的信息
有保证的按顺序到达它们的目的地。UDP不建立连接,它的速度快但不可靠。你发送的信息也可能到不了另一端;或它们没有按顺序
到达。有时候一个信息的多个复制到达接收端,即使你只发送了一次。
二、使用地址和主机
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通
讯。socket()函数,Python 中,我们用 socket()函数来创建套接字,语法格式如下:
socket.socket([family[, type[, proto]]])
参数
family: 套接字家族可以使AF_UNIX或者AF_INET
type: 套接字类型可以根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
protocol: 一般不填默认为0.
socket模块提供了几个函数用于使用主机名和地址来工作。
1、gethostname()返回运行程序所在的计算机主机名
2、gethostbyname(name)尝试将给定的主机名解释为一个IP地址首先将检查当前计算机是否能够解释。如果不能,解释请求将发送
给远程的DNS服务器。gethostbyname函数返回一个IP地址或查找失败后引发异常。
3、扩展形式:gethostbyname_ex(name),返回包含3个元素的元祖。分别是给定地址的主机名、同一IP地址的可选的主机名的
一个列表、关于同一主机的同一接口的其它IP地址的一个列表(列表可能都是空的)。
4、gethostbyaddr(address)函数的作用与gethostbyname_ex相同,只是你提供给它的参数是一个IP地址字符串。
5、getservbyname(service, protocol)函数要求一个服务名和一个协议,返回服务所使用的端口号
6、通常,非Python程序以4个字节包的形式存储和使用IP地址。inet_aton(ip_addr)和inet_ntoa(packed)函数在这个形式和IP地
址间作转换:
三、使用低级的socket通信
1、创建和销毁socket
socket 模块中的socket(family,type[,proto])函数创建一个新的socket对象。family的取值通常是AF_INET。type 的取值通常
是SOCK_STREAM(用于定向的连接,可靠的TCP连接)或SOCK_DGRAM(用于UDP):
family和type参数暗指了一个协议,但是你可以使用socket的第三个可选的参数(proto的取值如IPPROTO_TCP或IPPROTO_RAW)来
指定所使用的协议。代替使用IPPROTO_XX变量,你可以使用函数getprotobyname。
当你使用完工 socket对象时,你应调用close()方法显式的关闭socket以尽快释放资源(尽管socket被垃圾回收器回收时将自动被
关闭)。另外,你也可以使用shutdown(how)方法来关闭连接一边或两边。参数0阻止socket接收数据,1阻止发送,2阻止接收和发
送。
2、连接socket
当两个socket对象连接时(例如使用TCP),一端监听和接收进来的连接,而另一端发起连接。
监听端创建一个socket,调用bind(address) 函数去绑定一个特定的地址和端口,调用listen(backlog)来临听进来的连接,最后
调用accept()来接收这个新的的连接。
服务器端的代码:
注意:上面的代码将一直处于等待直到连接被建立。返回socket new_socket和地址address
下面我们再打开另一个Python解释器,用作客户端;然后键入如下代码:
好了,我们验证一下连接是否建立了。
我们在服务器端可以看到:
服务器=端返回的客户端的socket对象和地址端口号。
服务器向客户端发送消息:下面是字节数
在客户端可以接受消息:
你传递给bind和connect的地址是一个关于AF_INET的socket的元组(ipAddress,port)。
当你调用listen时,你给了它一个参数,这个数值表示在等待队列中允许放置的进来的连接总数。当等待队列已满时,如果有更多
的连接到达,那么远程端将被告知连接被拒绝。在socket模块中的SOMAXCONN变量表明了等待队列所能容纳的最大量。
accept()方法返回形如bind和connect的一个地址,代表远程socket的地址。
UDP是不定向的连接,但是你仍然可以使用给定的目的地址和端口来调用connect去关联一个socket。
三、发送和接收数据
函数send(string[,flags])发送给定的字符串到远程socket。sendto(string[,flags],address)发送给定的字符串到一个特定的
地址。通常,send方法用于可靠连接的socket,sendto方法用于不可靠连接的socket,但是如果你在一个UDP socket上调用
connect来使它与一个特定的目标建立联系,那么这时你也可以使用send方法来代替sendto。
send和sendto都返回实际发送的字节数。
recv(bufsize[,flags]) 方法接收一个进来的消息。如果有大量的数据在等待,它只返回前面的bufsize字节数的数据。
recvfrom(bufsize[,flags])做同样的事,除了它使用AF_INET socket的返回值是(data,(ipAddress,port)),这便于你知道消息来
自哪儿(这对于非连接的 socket是有用的).
MSG_OOB : 处理带外数据(既TCP紧急数据)。
MSG_DONTROUTE : 不使用路由表;直接发送到接口。
MSG_PEEK : 返回等待的数据且不把它们从队列中删除。
makefile([mode[,bufsize]]) 方法返回一个文件类对象,其中封装了socket,以便于你以后将它传递给要求参数为一个文件的代
码(或许你喜欢使用文件的方法来代替send和 recv)。这个可选的mode和bufsize参数的取值和内建的open函数一样。
四、Socket 对象(内建)方法
1、socket对象的getpeername()和 getsockname()方法都返回包含一个IP地址和端口的二元组(这个二元组的形式就像你传递给
connect和bind的)。 getpeername返回所连接的远程socket的地址和端口,getsockname返回关于本地socket的相同信息。
客户端:
2、
服务器端套接字 | |
s.bind() | 绑定地址(host,port)到套接字, 在AF_INET下,以元组(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数据,完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 |
s.recvform() | 接收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为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)。非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常。 |
s.makefile() | 创建一个与该套接字相关连的文件 |
以上是socket套接字对象的方法,后后面用到的时候方便来查找,这个东西没必要记忆。
3、Python Internet 模块(了解部分,等用到在深入)
协议 | 功能用处 | 端口号 | Python 模块 |
HTTP | 网页访问 | 80 | httplib, urllib, xmlrpclib |
NNTP | 阅读和张贴新闻文章,俗称为"帖子" | 119 | nntplib |
FTP | 文件传输 | 20 | ftplib, urllib |
SMTP | 发送邮件 | 25 | smtplib |
POP3 | 接收邮件 | 110 | poplib |
IMAP4 | 获取邮件 | 143 | imaplib |
Telnet | 命令行 | 23 | telnetlib |
Gopher | 信息查找 | 70 | gopherlib, urllib |
python的网络编程就介绍到这里,大致了解socket编程及其客户端和服务器的交互过程。