以前,人们热衷于如何将两台机器互相连接,许多连接的方法在今天已经过时,还有很多方法沿用至今。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)
- 创建一个socket对象
我们上面连接的是一个http站点,默认端口是80,我们可以通过下面的方法获取到默认的端口号:
- 连接后,从一个socket对象获取信息
比如,获取本机的IP地址和端口号,获取远程机器的IP地址和端口号,如:
# Information Example - Chapter 2
import socket
print "Creating socket",
s = 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),每次执行端口号都会不同。
- 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创建一个服务端可以总结为如下四个步骤:
-
创建一个socket对象。(create socket object)
-
设置socket对象的属性。(set options)
-
绑定一个端口。(bind to a port)
-
监听来自客户端的连接。(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/
文章版权归本人所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。