一、理解TCP基础
1.寻址
TCP要能识别远程的机器,基于TCP/IP网络的每台机器都有一个唯一的IP地址。(ip)
TCP需要知道与远程机器上运行的哪个程序通信,每个程序要使用一个唯一的端口号。(port)
因此,每个TCP连接的端点是由一个IP地址和一个端口号来唯一标识。(ip:port)
虽然有IP和端口号,TCP就能很好的工作,但是记住一串数字比较困难,由于这个原因出现了DNS。
现在想要和远程机器建立连接,可以申请连接该机器IP地址相对应的DNS(如:www.baidu.com),
DNS会提供一个IP地址,接下来就可以建立连接。
2.可靠性
TCP是一个可靠的协议,除非整个网络出现问题,否则数据将被完好的按原样正确的传送到另外一端。
这个可靠性通过以下规则实现:
(1) 为了防止数据在传输的过程中被破坏,每个信息都包含一个校验码。这个校验码是一个用来保证信息包在传输过程中没有被更改的代码。当信息包到达目的地的时候,接收方会对比校验码和收到的信息中的数据。如果校验码不对,该信息包将被省略。
(2) 为了防止信息包丢失,TCP会要求接收方每收到一个信息包都反馈一下。如果接收方没有提供反馈,发送方会自动重发一次。由于系统会自动处理这个问题,所以程序的开发者根本不用知道问题的出现。TCP会一直试着发送信息包,一直到接收者收到为止,或者它会判断出网络连接断了,并在程序中返回一个错误提示。
(3) 为了防止信息包重复或顺序错误,TCP每传送一个信息包都会传送一个序号。接收方会检查这个序号,确保收到该信息包,并把全部信息包按顺序重新合并。同时,如果接收方看到一个已经看过的序号,则该信息包就会被丢弃。
二、使用客户/服务器模式
在客户/服务器结构下,服务器一直侦听来自客户端的请求,有请求后,就建立连接来处理它们。
客户端总是最开始申请连接的一端,服务器则是等待客户端连接的一端。
1.服务器端端口号
在www.iana.org上有一份由国际因特网地址分配委员会维护的官方已分配的端口列表。
如果编写一个服务器,它的服务不在这个列表,那就应该选一个比1024大,而且在机器上没有被占用的端口号。
这样就避免和其他服务冲突,端口号最大可以为65535。
2.客户端端口号
通常,客户端的端口号不是很重要。一般情况下,客户端会由操作系统随机挑选一个端口号。
客户端的系统会挑选一个保证没有被使用的,被称为“短命”的端口号。
三、理解UDP基础
UDP,它被用来从一个系统向其他的系统传送非常短的消息。
它只提供一个保证:那就是您收到的数据是完整的。
它既不能保证数据是否真的被收到,也不能保证数据是不是只接受一次,还不能保证收到的信息次序是否和发送时候一致。
但是只要没有受到攻击者绕过安全措施后的攻击,通过UDP接收的数据通常都会是完整的。
优点,因为不提供上面那些保证,所以比TCP低级,TCP建立和关闭连接要花费时间,而UDP对连接没有什么概念,所以不存在花费时间建立和关闭连接的问题。(如DNS系统)。
使用参考:
TCP:
# 您需要一个可靠的数据传输,以确保数据完整无缺的到达目的地。
# 您的协议需要不止一个请求和服务器的回答
# 您要发送较多的数据
# 初始连接出现短暂的延迟是可以容忍的
UDP:
# 您不太关心信息包是否到达或者不太在意信息包到达的顺序是否正确,再或者您可以自己察觉这些问题并自己解决
# 您的协议只包括基本请求和回答
# 您需要建立网络会话
# 只传送很少一部分数据.UDP的限制是一个信息包不超过64KB的数据,通常人们只用UDP传送1KB以下的数据
四、底层接口
1.基本客户端操作
import socket,sys
port = 70
host = 'quux.org'
filename = '/'
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
s.connect((host,port))
except socket.gaierror ,e:
print "Error connecting to server: %s"%e
sys.exit(1)
s.sendall(filename + '\r\n')
while 1:
buf = s.recv(2048)
if not len(buf):
break
sys.stdout.write(buf)
1.1.文件类对象
import socket,sys
port = 70
host = 'quux.org'
filename = '/'
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
s.connect((host,port))
except socket.gaierror ,e:
print "Error connecting to server: %s"%e
sys.exit(1)
fd = s.makefile('rw',0)
fd.write(filename + "\r\n")
for line in fd.readlines():
sys.stdout.write(line)
通过makefile()函数生成文件类对象,有两个可选参数:操作文件类模式和缓存模式。
操作文件类模式,只读、只写、又读又写。
缓存模式主要用在磁盘文件,但是对于交互式的网络程序,它可能会阻碍程序的运行,所以最好通过设置为0来关上它。
2.基本服务器操作
import socket
host = ''
port = 51423
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host,port))
s.listen(1)
print "Server is running on port %d; press Ctrl-C to terminate."%port
while 1:
clientsock,clientaddr = s.accept()
clientfile = clientsock.makefile('rw',0)
clientfile.write("Welcome, " + str(clientaddr) + '\n')
clientfile.write('Please enter a string: ')
line = clientfile.readline().strip()
clientfile.write('You entered %d characters.\n'%len(line))
clientfile.close()
clientsock.close()
###### 结果 ######
Welcome, ('127.0.0.1', 62460)
Please enter a string: 123
You entered 3 characters.
遗失对主机的连接。
C:\Users\Administrator>