注:想学点Python。找了本《Python网络编程基础》来学习,用Pydev在MyEclipse搭建好,然后照着书里的代码实践一番。
作者用的而是2.x版本的,Python2.x和3.x是不兼容的,因此要在3.x上跑代码,还是要改进一些,顺带了解二者的区别。
一. 客户端,服务器网络
1.TCP是一些协议的合集。Internet是在一些共享的线路上发送数据的。
2.TCP把你要发送的数据流分解成很多小信息包在Internet上传输。
为了实现这个信息包的机会,TCP需要
(1)识别远程机器(IP地址)
(2)识别机器的通信程序(端口号)
(3)仅仅为了设计需要/用户需求(DNS,用DNS替代IP)
3.TCP可靠性的实现:
(1)校验码
(2)接收方反馈
(3)信息包附带序号
4.信息包的转发有路由实现
5.信息的安全有SSL和TLS。提供服务器的认证,加密,数据完整性
6.服务器通常是侦听一个大家都知道的端口号,如Web服务器侦听80端口号。MySQL是3306的端口号。如果是自己写的服务器程序,服务不属于有国际因特网地址分配委员会IANA维护的官方端口列表中任一个,则需要选择一个大于1024,没有被本机占用的端口号。最大可以是65535
7.客户端由操作系统随机选择,客户端程序会选择一个保证没有被使用的“短命”的端口号
8.TCP和UDP区别就是UDP不建立连接,只保证数据的完整性,数据传输快,但是不保证数据是否真的被收到,也不保证数据是够只接收一次,也不保证次序。(天,视频会议用的就是UDP,对网络延迟有很低的容忍度,所以只要我能够
很快
接受到完整的消息就可以了)
UDP:(1)快 不需要花费时间建立和关闭连接
(2)快 偶尔丢失一两个消息包无所谓,但是TCP会严格检查
(3)快 UDP的限制是一个信息包不超过64KB的数据
9.Python网络编程
(1)客户端
Python具有一些协议模块 HTTP FTP
照着代码打,可能是因为Python3的原因,str转换成byte需要encode函数(就是不再支持隐式转换),解答的链接如下:
http://blog.csdn.net/chuanchuan608/article/details/17915959
In python 3, bytes strings and unicodestrings are now two different types. Since sockets are not aware of string encodings, they are using raw bytes strings, that have a slightly differentinterface from unicode strings.
So, now, whenever you have a unicode stringthat you need to use as a byte string, you need toencode() it. And whenyou have a byte string, you need to decode it to use it as a regular(python 2.x) string.
Unicode strings are quotes enclosedstrings. Bytes strings are b"" enclosed strings
于是在str转成byte时使用encode()函数,在byte转换成str时候使用decode()函数,但是quux.org的文件内容输出很乱(不是乱码),不知为何。也许本来如此?
于是心有不甘,去查了颉颃剂的读书笔记,http://book.douban.com/people/antagonist/annotation/2137490/
照着人家改,发现最后输出还是一个样子,后面把2048改成4096,同样不行,不理之。截图:
对于后面的异常捕捉,首先,python2和python3的首要区别就是print不再作为对象而是一个函数,推荐使用这样的形式:
print("Error connecting to server:{}".format(e))
另外,python3下的except不用逗号,用as
(2)服务器端
host = ''代表任意连接均可。设置一个port端口号,开启window中控制面板-程序与功能-打开或关闭windows功能-勾选telnet客户端。启动服务器,在cmd中输入“telnet localhost 51423”就可以连上服务器。输入字符串可以统计输入字符串的字符个数。原文中,按照颉颃剂的修改意见,去掉makefile函数的第二个参数0.
后面的有一个
import gopherlib
看网上资料说从2.6开始就没有gopherlib这个模块了,所以用不了。
对于urllib,没有urlopent这个函数,但是urllib.request有,所以
import urllib.request就可以。
另外,gopher://也用不了,直接打个别的网址,如f= urllib.request.urlopen("http://www.python.org")就OK了。截图:
二.网络客户端
0. 建立socket对象,连接一个socket,通过socket发送消息,等待服务器处理。
1. 建立socket对象,需要通信类型和协议家族
Internet通信,通信类型基本是AF_INET(IPv4),协议家族:TCP(SOCK_STREAM) UDP:(SOCK_DGRAM)
于是写成:s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2. 连接一个socket, 首先,提供一个tuple,包括远程主机名/IP, 端口。另外,在python中,socket对象的connect()函数会根据需要利用DNS把域名自动转换成IP地址。
s.connect(("www.baidu.com", 80))
4. UDP客户端和TCP客户端区别
(1)建立时使用SOCK_DGRAM而不是SOCK_STREAM
(2)端口号是UDP端口号,不是TCP的
(3)没有办法检测服务器什么时候发送完数据,因为这里没有实际的链接
三. 网络服务器
0. 建立socket对象,设置socket选项,绑定到一个端口,侦听连接
1. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 80))
s.listen(5) #5表示的是在服务器实际处理连接时,运行在队列中等待的连接
2. 通常无限循环是不好的,因为它们会耗尽系统的CPU资源。但是这里有一个accept()函数,它是阻塞的,所以客户没有连接成功时不会使用任何资源。
3. 时间戳(返回昨天时间)
服务器端程序 获取time.time()时间,处理为昨天时间,打包成二进制发送给客户端
客户端程序:
发了一个空消息,然后服务器就被激活,发送时间回来,接收时间是直接recvfrom函数。
运行结果:
4. 服务器端不能只为一个单一客户端服务,解决这个问题的方法包括多线程技术,另外一个方法是每当有客户端连接时,启动一个服务器的拷贝。这个技术就是使用inetd或者xinetd
5. 死锁的一个例子程序
服务器端程序,每次读取4K程序
客户端程序:发送10MB的数据,每次发送1KB,启动服务器之后,启动客户端程序,发现程序会在某个时刻停止下来,即读和写的两个进程死锁。
四. 域名系统
1.域名系统是一个庞大的,全球的分布式的数据库,递归实现将主机名转成IP地址。这个最大的好处就是大家想上百度的首页的时候不用打119.75.217.56这么逆天的地址了(你想想ip多了之后怎么记),所以“电话簿”DNS域名系统就出来拯救世界了。
另外一个好处可能比较难想到,就是如果百度今天服务器宕了,换了个IP,难道www.baidu.com就不能登上新的IP?显然不可能,所以DNS允许服务器改变IP,但是可以使用相同的名字。
2. 系统先使用hosts文件来查询,没有的话再去DNS查询。这就是Google不能用了之后,修改hosts强制转换到某个镜像IP的思想了。
3. 正向DNS查询和逆向DNS查询
下面的代码我尝试了百度的两个IP地址 119.75.218.77和119.75.217.56均显示没有域名,后面找了网易的www.163.com的地址222.198.122.4(可以CMD,输入ping www.163.com)也没有找到。然后无奈之下使用了书里提供的192.0.34.166居然显示了。。域名是34-166.lax.icann.org。下面是截图:
4. 查询本机信息
运行结果:IP address的最后一列是自己的Ipv4地址。
5.PyDNS提供了一个功能更强的范文DNS系统的接口]
A记录:指定某个域名的IP,正向DNS查询
AAAA记录:给出一个主机名的IPv6地址
CNAME记录:定义别名
MX记录:指定有限选择的邮件交换服务器的顺序
PTR记录:指定某个IP的主机名,反向DNS查询
NS记录:域名服务器记录,指定该域名由那个DNS服务器进行解析
TXT记录:存储关于一个主机的专门信息
SOA记录:存有起始授权机构信息(Start Of Authority)
五. 高级网络操作
1.广播
还是UDP的操作,但是增加了
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
当接受广播的所有机器运行服务器程序,就可以进行广播接收,这个时候只需要在某个机器上运行发送程序,所有注册广播的机器都将获取得到广播的数据和知道广播机器的IP地址。
服务器端程序:(最下面是结果
)
客户端程序及运行结果:
2.IPv4有一个32位的地址空间,理论上可以提供最大为40亿的地址。
IPv6有168为的地址空间,理论上可以提供3.40 * 10^38的地址。
早在1979年有一种称为流协议(ST,ST+,ST2,ST2+)的协议被定义为5
在Python中,IPv6除了建立连接的时候和IPv4不一样,一旦建立了连接之后就完全一样了。
下面是测试IP地址的支持情况,我的机子对于www.ipv6.org的分析居然没有IPv6, 我查了很久,试过几个方法,结果没有作用。我连我们学校在我们宿舍楼启用IPv6有没有都不清楚,网络中心的人又不回我。。。
但是试了作者的www.ipv5.bieringer.de,居然是这样的(网站打不开,而且可以确认我的IPv6是不能用的,看能不能打开http://ipv6.baidu.com/就知道了。)
3.select()的动画程序
服务器端程序
客户端程序:
运行结果: