温故而知新–day5

温故而知新–day5

ip地址

IP是英文Internet Protocol的缩写,意思是“网络之间互连的协议”,也就是为计算机网络相互连接进行通信而设计的协议。当多个设备要进行通信的时候,ip地址必须唯一。

IP地址=网络地址+主机地址,(又称:网络号和主机号组成)
网络号、主机号的确定需要“子网掩码”

公网ip分类

  • A类:该类IP地址的最前面为“1000”(1.0.0.0-126.0.0.0)(默认子网掩码:255.0.0.0或 0xFF000000)
  • B类:该类IP地址的最前面为“1100”(128.1.0.0-191.255.0.0)(默认子网掩码:255.255.0.0或0xFFFF0000)
  • C类:该类IP地址的最前面为“1110”(192.0.1.0-223.255.255.0)(子网掩码:255.255.255.0或 0xFFFFFF00)
  • D类:是多播地址。该类IP地址的最前面为“1110”,所以地址的网络号取值于224~239之间。一般用于多路广播用户。
  • E类:是保留地址。该类IP地址的最前面为“1111”,所以地址的网络号取值于240~255之间。

私有地址
私有地址是不能直接在Internet网络中应用的,要上Internet的话要转为公有地址。私有ip有以下几种:

  • A::10.0.0.0-10.255.255.255 即10.0.0.0/8
  • B:172.16.0.0-172.31.255.255即172.16.0.0/12
  • C:192.168.0.0-192.168.255.255 即192.168.0.0/16

子网掩码
子网掩码是用来判断任意两台计算机的ip地址是否属于同一子网络的根据。最为简单的理解就是两台计算机各自的ip地址与子网掩码进行and运算后,得出的结果是相同的,则说明这两台计算机是处于同一个子网络上的,可以进行直接的通讯。

IP地址与子网掩码

IP地址与子网掩码

图中还可以写成:192.168.1.1/24
24就是1的个数
端口
只使用ip地址进行通信只能精确到某台主机,因此加入了可以区别不同程序的标识符:端口。

端口使用2个比特来表示,范围为是0~25535。
端口分为两种:

  • 周知端口(Well Known Ports)
    • 周知端口是众所周知的端口号,范围从0到1023,其中80端口分配给WWW服务,21端口分配给FTP服务等。
    • 周知端口的监听需要有root权限。
  • 动态端口(Dynamic Ports)
    • 动态端口的范围是从1024到65535。之所以称为动态端口,是因为它一般不固定分配某种服务,而是动态分配。

更多见:

iso七层

详细

详细

iso七层与数据传输

socket

socket为套接字,是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。socket是”打开—读/写—关闭”模式的实现。
socket

TCP

TCP/IP协议是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。
TCP协议就像打电话一样,有“打-通话-挂”三个过程,“打”:是指客户端与服务端建立链接(三次握手);“通话”:两端进行通信;“挂”:客户端或服务端发起断开请求。
三次握手、四次挥手

注:seq:”sequance”序列号;ack:”acknowledge”确认号;SYN:”synchronize”请求同步标志;;ACK:”acknowledge”确认标志”;FIN:”Finally”结束标志。

在python中简单使用TCP

参考tcp cs模型:
TCP C/S模型

"""
服务端
"""

import socket
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)   # SOCK_STREAM是tcp协议

# 绑定ip地址和监听的端口
tcp_sock.bind(("", 8899))      # ip地址为空字符串时,指的是本机
tcp_sock.listen(50)            # 缓存区大小

# 等待链接
new_sock, addr = tcp_sock.accept()


recv_data = new_sock.recv(1024)     # 收
print(recv_data.decode())
new_sock.send(recv_data)            # 发
# 关闭
new_sock.close()
tcp_sock.close()




"""
客户端
"""

import socket

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

# 连接
s.connect(("127.0.0.1", 8899))
s.send(b"hello")

data = s.recv(1024)
print(data.decode())

s.close()

并发

上面这个简单的例子只能简单处理一个请求,要想同时处理多个请求,可以用一下方法实现:

  • 多线(进)程

    """
    服务端
    """
    
    import socket
    from concurrent.futures import ThreadPoolExecutor
    
    
    def process_client(client, addr):
    	"""
    	处理过来的链接,进行收发处理
    	"""
    	try:
    		while True:
    			recv_data = client.recv(1024)     # 收
    			print(recv_data.decode())
    			client.send(recv_data)            # 发
    	finally:
    		# 关闭
    		client.close()
    
    
    def main():
    
    	tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    	tcp_sock.bind(("", 8899))      # ip地址为空字符串时,指的是本机
    	tcp_sock.listen(50)            # 缓存区大小
    
    	# 等待链接
    	try:
    		while True:
    			new_sock, addr = tcp_sock.accept()
    			with ThreadPoolExecutor(12) as t:
    				t.submit(process_client, new_sock, addr)
    				# 假如是多进程的话,此时应该加上 new_socke.close()
    				# 因为在使用多进程时,资源会再复制一份到另一进程
    	finally:
    		tcp_sock.close()
    
    
    if __name__ == '__main__':
    	main()
    
    """
    客户端
    """
    
    import socket
    
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 连接
    s.connect(("127.0.0.1", 8899))
    
    while True:
    	data = input(">>>")
    	if not data:
    		continue
    	s.send(data.encode())
    	print(s.recv(1024).decode())
    
    s.close()
  • socketserver
    python中除了有socket库提供socket支持外,还有socketserver提供服务器中心类,可以简化网络服务器的开发。
    使用步骤:

    • 1、创建一个继承socketserver.BaseRequestHandler的类

    • 2、类中必须重写一个名为handler的方法

    • 3、实例化一个服务器类,传入服务器的地址和请求处理程序类

    • 4、调用serve_forever()事件循环监听

    注意:类中的self.request在TCP时为已链接的套接字对象;UDP时为(data, udp socket对象) 需要借助self.client_address发数据

    """
    服务端
    """
    
    import socketserver
    
    
    class MyServer(socketserver.BaseRequestHandler):
       def handle(self) -> None:
       	print(self.client_address)      # 地址
       	while True:
       		recv_data = self.request.recv(1024)     # 收
       		# print(recv_data.decode())
       		self.request.send(recv_data)           # 发
    
    
    def main():
       s = socketserver.ThreadingTCPServer(("", 8899), MyServer)
       s.serve_forever()
    
    
    if __name__ == '__main__':
       main()

    更多见:socketserver模块使用方法

  • io多路复用
    见day4的最后例子

UDP

无连接的、简单的、面向数据包的传输层协议。

简单收发例子

"""
服务端
"""

import socket


udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

udp_sock.bind(("", 8899))

while True:
    data, addr = udp_sock.recvfrom(1024)
    print(data)
    udp_sock.sendto(data, addr)


"""
客户端
"""

import socket

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

data = input(">>>")
# 发送消息,数据+ip端口
s.sendto(data.encode(), ("127.0.0.1", 8899))
print(s.recvfrom(1024))

s.close()

udp广播
要点:

  1. 发送地址为<broadcast>
  2. 设置socket选项
    """
    udp广播
    局域内,只要监听8899端口,都能收到消息
    """
    
    import socket
    
    udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 发送的地址
    ip_port = ("<broadcast>", 8899)
    # 修改socket选项, 固定格式
    udp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    udp_sock.sendto(b"test", ip_port)
    
    while True:
       recv_data = udp_sock.recvfrom(1024)
       print(recv_data)
    

http

什么是http协议

http协议是Hypertext Transfer Protocol –(超文本传输协议)的缩写,在互联网领域用得非常多的通讯协议。
HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型。HTTP是一个无状态的协议。
HTTP协议是建立在TCP协议之上的一种应用。
1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。
2)在HTTP 1.1中,可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。
http的过程

  1. 服务端监听80端口,等待请求
  2. 客户端(一般为浏览器)发起请求
  3. 服务端处理请求,返回数据
  4. 客户端或服务端断开链接

URI和URL

URI用字符串标示某一互联网资源,而URL表示资源的地点。可见URL是URI的子集。
URI要使用涵盖全部必要信息的URI、绝对URL以及相对URL。
相对URL是指从浏览器中基本URI处理的URL,来先看下URI的格式:
url

请求报文

请求报文

请求报文

POST /test/index.html HTTP/1.1
Accept: */*
Accept-Language: zh-cn
host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 12
Connection:close
sn=123&n=asa

响应报文

HTTP/1.1 200 OK
Server:Apache Tomcat/5.0.12
Date:Mon,6Oct2003 13:23:42 GMT
Content-Length:112
 
<html>
<head>
<title>HTTP响应示例<title>
</head>
<body>
Hello HTTP!
</body>
</html>

请求方法

  • GET
    服务器将URL定位的资源放在响应报文的数据部分,回送给客户端
    利用在URL的结尾表示传参,多个参数之间用&隔开,如/index.html?id=10&op=bind传递参数长度受限制,且不适合传送私密数据

  • POST
    POST方法将请求参数封装在HTTP请求数据中,以名称/值的形式出现,可以传输大量数据。如请求报文哪里的例子。

  • HEAD
    像GET,只不过服务端接受到HEAD请求后只返回响应头,而不会发送响应内容。适用于查看某个页面的状态。

  • PUT
    可用来传输文件,就像FTP协议的文件上传一样,要求在请求报文的主体中包含文件内容,然后保存到请求url指定的位置。由于put的方法不带验证机制,任何人都可以上传文件,存在安全性问题。

  • DELETE
    用来删除文件,是与put相反的方法,delete方法按照请求url删除指定的资源。其本质和put方法一样不带验证机制。

全部方法:
http请求方法

状态码

状态代码由三位数字组成,第一个数字定义了响应的类别,且有五种可能取值。

1xx:指示信息–表示请求已接收,继续处理。
2xx:成功–表示请求已被成功接收、理解、接受。
3xx:重定向–要完成请求必须进行更进一步的操作。
4xx:客户端错误–请求有语法错误或请求无法实现。
5xx:服务器端错误–服务器未能实现合法的请求。
常见状态代码、状态描述的说明如下。

200 OK:客户端请求成功。
400 Bad Request:客户端请求有语法错误,不能被服务器所理解。
401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。
403 Forbidden:服务器收到请求,但是拒绝提供服务。
404 Not Found:请求资源不存在,举个例子:输入了错误的URL。
500 Internal Server Error:服务器发生不可预期的错误。
503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常,举个例子:HTTP/1.1 200 OK(CRLF)。

Cookie是用于维持服务端会话状态的,通常由服务端写入,在后续请求中,供服务端读取的一段文本。
cookie技术通过在请求和相应报文中写入cookie信息来控制客户端的状态。cookie会根据从服务端发送的相应报文内的一个叫做set-cookie的首部字段信息,通知客户端保存cookie。当下次客户端再往服务器发送请求的时候,客户端会自动在请求头加入cookie值后发送出去

更多:细说Cookie

session

Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。
Session对象在客户端第一次请求服务器的时候创建。
更多:cookie和session的详解与区别

https

详见此文:HTTPS科普扫盲帖

websocket

【待完成】

扩展

计算机网络基础知识总结

我的github
我的博客
我的笔记

Tags: