第一章 客户/服务器网络介绍

来源:互联网 发布:app源码 编辑:程序博客网 时间:2024/05/19 17:07


TCP/IP是计算机通信的标准协议。

1.1    理解TCP基础

TCP/IP事实上是一些协议的合集,当前大多数使用中的通信都是使用TCP协议。

Internet是在一些共享的线路上发送数据的。为了实现共享,TCP是通过把你要发送的数据流分解成很多小的信息包在Internet上传输的(也许还伴有其它应用程序的信息包),而这些信息包到了接收者再次重新合成在一起。

1.1.1寻址

为了实现信息包计划,TCP必须处理一些细节问题:

Ø  TCP必须识别远程机器,基于TCP网络,每台机器都有一个唯一的IP,只要知道接收者IP,信息就可以传递过去。

Ø  TCP必须知道与远程机器运行的哪个程序通信,为了实现这个目的,TCP使用端口号,每个程序用一个唯一的端口号。

每一个TCP连接的端点是由一个IP地址和一个端口号来唯一识别的。

1.1.2可靠性

Internet上传送数据会出现错识,出现错识有很多可能:Modem有可能改变了数据的几个字节,某个路由器或许丢失一两个信息包,系统或许收到顺序错识的信息包,一个信息包或许收到两次,再或许网络电缆断了。

TCP是一个可靠协议,这个可靠性通过以下几个规则来实现:

Ø  为了防止数据在传输中被损坏,每个信息包都包含一个校验码,当信息到达目的地时接收方会对比较验码和收到的信息中的数据,如果校验码不正确该消息包被省略。

Ø  为了防止信息包丢失,TCP会要求接收方每收到一个信息包都反馈一下,如果接收方没有提供反馈,发送方会自动重发一次,

Ø  为了防止信息包重复或顺序错误,TCP每传送一个信息包都会传送一个序号,接收方会检查这个序号,确保收到该信息包,并把全部信息按顺序合并,如果接收方发现一个重复的序号,则该信息包被丢弃。

1.1.3路由

为了能使用信息包顺利地从你的机器传送到远程服务器上,信息包通常会经过很多不同的网络。

Internet上负责接收信息包将决定如何把它们传输到目地的设备叫路由器。

1.1.4安全 

因为信息包在Internet上传输的时候,是通过共享网络传输,所以任何有权使用网络的人都能看到它,这些信息还可能被插入或改写。

Ø  当在网络商店购物时,你一定不想你的信用卡账号被陌生人发现。

Ø  另外一个潜在风险,你的连接被拦截到另外一台机器。

SSL一般在TCP之上,它提供服务器的认证(你知道和谁通话)、加密(其它人都不能看到你的通信)和数据完整性(传输中信息包没有人能修改)。

1.2   使用客户/服务器模式

在客户端/服务器的通信结构下,服务器一直在侦听来自客户端的请求,有请求后,就建立连接来处理它们。

1.2.1    服务器端端口号

系统端口列表 /etc/services

如果你编写一个服务器,它的服务不在这个列表上,你应该选择一个比1024大,而且在你的机器没有被占用的端口号。最大的端口号可以使用65535

Linux系统上只有系统管理员才能访问小于1024端口号。

1.2.2    客户端端口号

客户端会由操作系统随机挑选 一个没有被使用的“短命”的端口号,当服务器接收到请求时,请求中带有客户端的端口号,数据会被传输到该端口号上。

1.3    理解UDP

UDP被用来从一个系统向其它系统传送非常短的消息,它只提供一个保证:那就是你收到的消息是完整的。

UDP用得最广的是DNS系统,另外还常被应用于流式音频和视频应用软件。

使用TCP还是UDP指志方针:

使用TCP

Ø  你需要一个可靠的数据传输,以确保你的数据完整无缺地到达目的地。

Ø  你的协议需要不止一个请求和服务器的回答。

Ø  你要发送较多的数据。

Ø  初始连接出现短暂的延迟是可以的。

使用UDP

Ø  你不太关心数据包是否到达或不太在意信息包到的顺序是否正确,再或者你自己可以察觉这些问题并自己解决。

Ø  你的协议只包括基本的请求和响应。

Ø  你需要尽快的建立网络会话。

Ø  只传输很少一部分数据,UDP一个限制是一个信息包不超过64KB的数据,通常人们只用UDP传送1kb以下的数据。

1.4    理解物理传输和以太网

TCP有一个优点就是可以在不同的物理网络硬件之间传送数据。

以太网是当今应用最广泛的物理传输类型,很多不同的协议都要以运行在以太网上。

一个通过TCP/IP连接以太网的计算机有一个和网络接口相关的IP地址,它与一个本网络机器通信时,只需直接向该计算机发送信息即可,如果要和网外的机器通信,就必须把信息发送到本地网络的路由器,然后由路由器决定信息发送到哪里。

1.5    Python网络编程

当用Python来编写网络程序时,你会发现大致有两种情况:有些程序可以利用Python中已经有的协议模块(如HTTPFTP)来写,有些程序则需要你自己写协议。

1.5.1底层接口

Python提供了访问底层操作系统Socket接口的全部方法,需要的时候这些接口可以为你提供灵活而强有力的功能。它还提供一些用于加密和认证通信的服务,SSL/TLS.

1.5.1.1基本客户端操作

gopherclient.py

#!/usr/bin/python

import socket,sys

 

port = 70

host = sys.argv[1]

filename = sys.argv[2]

 

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

s.connect((host,port))

s.sendall(filename+"/r/n")

 

while 1:

 buf= s.recv(2048)

 ifnot len(buf):

   break

 sys.stdout.write(buf)

 

#./ gopherclient.py gopher.quux.org /

 

该程序实现的是Gopher协议,一种Web出现之前在Internet上非常流行的协议。

1.5.1.2错误和异常

Python会自动替你检查异常,并在有错误发生时产生异常,尝试给出一个不存在的主机名,如

./gopherclient.py nonexistant.example.com /

Traceback (most recent call last):

 File "./gopherclient.py", line 8, in ?

   s.connect((host,port))

socket.gaierror: (-2, 'Name or service notknown')

Python会检测到错误并产生一个socket.gaierror异常。

可以稍微修改一个程序,让它出错信息更友好一些。

gopherclient2.py

#!/usr/bin/python

import socket,sys

 

host = sys.argv[1]

filename = sys.argv[2]

port = 70

 

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)

 ifnot len(buf):

   break;

 sys.stdout.write(buf)

 

./gopherclient2.py nonexistant.example.com/

现在如果试图连接一个不存在的服务,程序将终止,你将得到一个友好的错误信息。

1.5.1.3文件类对象

Python库支持文件和文件类对象,Socket对象不提供类似接口,然而Python提供了一个makefile函数来生成你使用的文件类对象。

gopherclient3.py

#!/usr/bin/python

import socket,sys

 

host = sys.argv[1]

filename = sys.argv[2]

port = 70

 

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

s.connect((host,port))

s.sendall(filename+"/r/n")

fd = s.makefile('rw',0)

for line in fd.readlines():

 sys.stdout.write(line)

 

makefile函数,有两个可选参数:操作文件的模式和缓存的模式,操作文件类的模式表明你是只读、只写或者既读又写,缓存主要用于磁盘文件,对于交互式网络程序,它可能会阻碍程序的运行。

1.5.1.4 基本服务器操作

server.py从客户端读一个字符串,显示一个应答,最后关闭客户端socket

#!/usr/bin/python

import socket

 

host = ''

port = 51234

 

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)

 

while 1:

 clientsock,clientaddr= s.accept()

 clientfile = clientsock.makefile('rw', 0)   //不能设置为可读写?

 clientfile.write("Welcome,"+str(clientaddr)+"/n")

 clientfile.write("Please Enter aString:")

 line= clientfile.readline().strip()

 clientfile.write("You entered %s"+line)

 clientfile.close()

 clientsocket.close()

 

调用socket.socket()创建socket

bind()绑定一个端口

调用listen()函数,开始等候客户端连接,设定每次最多等待处理的连接

主循环调用accept(),返回一个新的客户端socket和客户端的IP地址、端口号

1.5.2 高级接口

Python 提供很多协议模块,使你不需要编写太底层的网络程序,它可以很大程度上简化你的编程任务。

httplib:提供解析HTTPheader功能。

gopherlibclient.py

#!/usr/bin/python

import gopherlib,sys

 

host = sys.argv[1]

file = sys.argv[2]

 

f = gopherlib.send_selector(file,host)

for line in f.readlines():

 sys.stdout.write(line)

 

gopherlib模块负责建立socket连接。

Python还提供更高级的模块,为了处理URLPython提供的模块可以让你的代码和几种协议一起工作。

 

urlclient.py

#!/usr/bin/python

 

import urllib,sys

host = sys.argv[1]

file = sys.argv[2]

 

f =urllib.urlopen('gopher://%s%s'%(host,file))

for line in f.readlines():

 sys.stdout.write(line)

download.py

#!/usr/bin/python

import urllib,sys

 

f = urllib.urlopen(sys.argv[1])

while 1:

 buf= f.read(2048)

 ifnot len(buf):

  break

 sys.stdout.write(buf)

./download.pyhttp://http.us.debian.org/debian/ls-lR.gz |gunzip |more

1.6   总结

TCP/IP 协议可以用于多种不同网络传输,如modems连接的网络和以太网,每一个终端靠唯一的IP地址和端口号来区分。

服务器通过一些事先知道的端口号来侦听,当一个客户连接时,它的操作系统通常会选择一个事先不知道的端口号。

有两种常用的数据传输协议,TCP:提供高可靠性和完整的会话,UDP:用于小且简短但是快速的会话。

大多数人用Python编写网络程序,要么自己设计协议,要么用一些内置的模块来实现一些已经存在的协议。

原创粉丝点击