Foundations of Python Network Programming - 读书笔记系列(1) - Low-Level Networking

以前,人们热衷于如何将两台机器互相连接,许多连接的方法在今天已经过时,还有很多方法沿用至今。TCP/IP就是之一,可以说,TCP/IP协议是当今使用范围最广的协议,这本书所有的内容都是基于TCP/IP的。TCP/IP的数据传输层是TCP和UDP,我们通过TCP和UDP连接远程机器时,只需要远程机器的IP和端口号,然后建立连接传输数据。其中TCP和UDP又有着许多不同之处。

何时使用TCP?

    1. 你需要确保传输的数据准确的到达并且保持完整。

    2. 你需要发送大量的数据,而不是简单的请求和返回。

    3. 你能忍受建立连接时消耗的时间。(效率低)

何时使用UDP?

    1. 你不关心你发送的包是否准确的到达,或者你能自己处理这些问题。(不稳定)

    2. 你只是希望得到一个简单的请求和返回。

    3. 你需要快速的建立连接。(效率高)

    4. 你发送的数据量不是很大。UDP限制每个包不能超过64KB,通常人们使用UDP时只使用了低于1KB。

在Python中建立一个TCP或UDP连接是一件非常简单的事情,需要使用Socket模块,这是Python的标准模块。

客户端(Network Clients)

  1. 创建一个socket对象

我们上面连接的是一个http站点,默认端口是80,我们可以通过下面的方法获取到默认的端口号:

  1. 连接后,从一个socket对象获取信息

比如,获取本机的IP地址和端口号,获取远程机器的IP地址和端口号,如:

# Information Example - Chapter 2

import socket

print "Creating socket",

= socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print "done."

print "Looking up port number",

port = socket.getservbyname('http''tcp')

print "done."

print "Connecting to remote host on port %d" % port,

s.connect(("www.google.com", port))

print "done."

print "Connected from", s.getsockname()

print "Connected to", s.getpeername() 输出结果会显示:

Creating socket… done.

Looking up port number… done.

Connecting to remote host on port 80… done.

Connected from (‘192.168.XX.XX’, 2548)

Connected to (‘64.233.189.104’, 80)

可以看到,我的本机使用的是一个随机的端口号(2548),每次执行端口号都会不同。

  1. File-like 对象

我们可以通过Socket对象来执行一些比如发送(send(), sendto()),接收数据的操作(recv(), recvfrom()),同时,我们还可以把Socket对象转换为一个类似文件的对象(File-like Object),然后使用其中的write()来发送数据,read(), readline()来接收数据。

File-like对象更适合TCP连接,因为TCP连接必须保证数据流能够完整正确的到达,数据流表现的更像是一个文件。而UDP却不是,它是一个基于包的连接,它只管把这些包发送出去,如果使用File-like对象来处理,将很难追踪定位出现的错误。生成一个File-like对象通过下面的语句:

注意上面在我们发送了数据之后,使用了shutdown方法,是为了保证发送的数据成功到达目标机器。因为shutdown()会等待,直到接收到一个准确的退出代码。

服务器端(Network Server)

通过TCP创建一个服务端可以总结为如下四个步骤:

  1. 创建一个socket对象。(create socket object)

  2. 设置socket对象的属性。(set options)

  3. 绑定一个端口。(bind to a port)

  4. 监听来自客户端的连接。(listen for connection)

针对上面的四个步骤,下面是一个最简单的实现:

通过UDP创建一个服务端步骤也差不多,创建一个socket,设置option,bind端口,然而,UDP不需要listen()和accept(),而是使用recvfrom()就足够了。recvfrom()函数返回两个信息:接受的数据(data)和客户端的地址(address)和端口(port)。下面是UDP服务端的例子:

Domain Name System(DNS)

我们能很轻松的记住博客园的域名,却基本上很难说出它的IP地址来,因为DNS为我们解析了域名。

socket.getaddrinfo()根据主机名或域名等来获取相应的信息。

OK,第一部分就到这里。

[温馨提示]:该文章由原博客园导入而来,如排版效果不佳,请移步:http://www.cnblogs.com/coderzh/archive/2008/06/16/1223287.html

微信扫一扫交流

作者:CoderZh
微信关注:hacker-thinking (程序员思考者)
本文出处:https://blog.coderzh.com/2008/06/16/1223287/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。