第一章 客户端 服务器网络编程(以调用谷歌提供的地理编码API得到邮箱地址"207 N. Defiance St, Archbold, OH"对应的物理地址为例)
1.1 使用requests库
def geocode(address):
base = 'https://nominatim.openstreetmap.org/search'
parameters = {'q': address, 'format': 'json'}
user_agent = 'Foundations of Python Network Programming example search2.py'
headers = {'User-Agent': user_agent}
response = requests.get(base, params=parameters, headers=headers)
reply = response.json()
print(reply[0]['lat'], reply[0]['lon'])
注:requests库的使用(参考)
- 格式:requests.request(method, url, **kwargs)
(也可用如下方式)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210330003923183.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ5MzgzNTA4,size_16,color_FFFFFF,t_70#pic_center)
- method详解
method | 注释 |
---|
get | 获取HTML网页的主要方法,对应HTTP的GET |
head | 获取HTML网页头(响应消息报告)的信息方法,对应HTTP的HEAD |
post | 向HTML网页提交POST请求方法,对应HTTP的POST |
put | 向HTML网页提交PUT请求的方法,对应HTTP的RUT |
patch | 向HTML网页提交局部修改请求,对应于HTTP的PATCH |
delete | 向HTML页面提交删除请求,对应HTTP的DELETE |
- ** kwargs详解
** kwargs | 注释 |
---|
params | 字典或字节序列,作为参数增加到url中 |
data | 字典,字节序列或文件对象,作为Request的内容 |
json | JSON格式数据,作为requests的内容赋值到服务器上的json域 |
headers | 字典,定制http头,定制访问url http的协议头 |
files | 字典类型,传输文件,向某一个链接提供文件 |
timeout | 设定超时时间,秒为单位,发起get请求,如果时间内未返回,产生timeout的异常 |
proxies | 字典类型,设定访问代理服务器,可以增加登录认证(http或https) |
- 下面为几个高级功能
![](https://img-blog.csdnimg.cn/20210330003615667.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ5MzgzNTA4,size_16,color_FFFFFF,t_70)
1.2 使用原始HTTP
def geocode(address):
path = '{}?q={}&format=json'.format('/search', quote_plus(address))
user_agent = b'Foundations of Python Network Programming example search3.py'
headers = {b'User-Agent': user_agent}
connection = http.client.HTTPSConnection('nominatim.openstreetmap.org')
connection.request('GET', path, None, headers)
rawreply = connection.getresponse().read()
reply = json.loads(rawreply.decode('utf-8'))
print(reply[0]['lat'], reply[0]['lon'])
说明:
- str.format(),基本语法是通过 { } 和 : 来代替以前的 % 。
>>>"{} {}".format("hello", "world")
'hello world'
>>> "{0} {1}".format("hello", "world")
'hello world'
>>> "{1} {0} {1}".format("hello", "world")
'world hello world'
- quote()/quote_plus(),对字符串进行编码,二者的区别在于对特殊字符编码的方式不一样。如quote()不编码斜线, 空格编码为‘%20’;quote_plus() 会编码斜线为‘%2F’;,空格编码为‘+’等等。(详情见)
1.3 直接使用套接字
def geocode(address):
unencrypted_sock = socket.socket()
unencrypted_sock.connect(('nominatim.openstreetmap.org', 443))
sock = ssl.wrap_socket(unencrypted_sock)
request_text = """\
GET /search?q={}&format=json HTTP/1.1\r\n\
Host: nominatim.openstreetmap.org\r\n\
User-Agent: Foundations of Python Network Programming example search4.py\r\n\
Connection: close\r\n\
\r\n\
"""
request = request_text.format(quote_plus(address))
sock.sendall(request.encode('ascii'))
raw_reply = b''
while True:
more = sock.recv(4096)
if not more:
break
raw_reply += more
print(raw_reply.decode('utf-8'))
family参数 | 描述 |
---|
socket.AF_UNIX | 只能够用于单一的Unix系统进程间通信 |
socket.AF_INET | 服务器之间网络通信 |
socket.AF_INET6 | IPv6 |
2. type参数(指明所要接收的协议类型,通常为0或者不填)
type参数 | 描述 |
---|
socket.SOCK_STREAM | 流式socket , 当使用TCP时选择此参数 |
socket.SOCK_DGRAM | 数据报式socket ,当使用UDP时选择此参数 |
socket.SOCK_RAW | 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头 |
3. protocol参数
protocol参数 | 描述 |
---|
socket.IPPROTO_RAW | 相当于protocol=255,此时socket只能用来发送IP包,而不能接收任何的数据。发送的数据需要自己填充IP报头,并且自己计算和校验 |
socket.IPPROTO_IP | 相当于protocol=0,此时用于接收任何的IP数据包。其中的校验和和协议分析由程序自己完成 |
相关函数(参考文件)
说明:
- TCP发送数据时,已建立好TCP连接,所以不需要指定地址。UDP是面向无连接的,每次发送要指定是发给谁。
- 服务端与客户端不能直接发送列表,元组,字典。需要字符串化repr(data)。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210330205946968.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ5MzgzNTA4,size_16,color_FFFFFF,t_70#pic_center)