计算机网络就是把各个计算机连接在一起,在网络中的计算机可以互相通信。
网络编程是如何在程序中实现两台计算机的通信。
网络通信是两台计算机上的两个进程之间的通信。
为了把全世界的所有不同类型的计算机都连接起来,就必须规定一套全球通用的协议,互联网协议包含了上百种,但最重要的有TCP和IP协议。
TCP/IP 协议被分为4层:应用层、传输层、网络层、接口层:
通信双方必须知道对方的标识,互联网每个计算 机的唯一标识就是IP地址。如果一台计算机同时接入两个或更多的网络,如路由器,就要有两个或多个IP地址。所以,IP地址对应的实际上是计算机的网络接口,通常是网卡。
TCP协议是建立IP协议之上的,负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。TCP协议会通过握手建立连接,然后对每个IP包编号,确保对方按顺序收到,如果包丢掉了,就自动重发。
socket 是应用层与传输层、网络层之间进行通信的中间软件抽象层,是一组接口,把复杂的TCP/IP协议隐藏在socket接口后面,对用户来说,一组简单的接口就是全部,调用socket接口函数去组织数据,以符合指定的协议,这样网络间的通信业就简单了许多。
Python 提供了两个基本的socket处理模块。
服务器
服务器端进程需要申请套接字,然后绑定套接字进行监听。当有客户端发送请求,则接收数据并进行处理,处理完后对客户端进行响应。
import socket
# socket模块的socket()函数能创建socket对象
socket.socket([family[,type[,proto]]])
'''
family:设置套接字种族,包括AF_UNIX和AF_INET,常用AF_INET选项。
type:设置套接字类型。
proto:协议类型,默认为0,一般不填。
'''
s1 = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 网络通信,协议类型
s1.bind(address) # address 地址必须是一个元组:(host,port)
s1.bind((host,port))
s1.listen(backlog) # backlog指定最多允许多少个客户端连接服务器
connection,address = s1.accept() # 阻塞状态
# 数据以字节串格式返回,bufsize指定最多可以接受的数量。
connection.recv(bufsize[,flag])
# 发送给连接的客户端套接字
connection.send(string[,flag])
s1.close()
客户端
客户端只需要申请一个套接字,然后通过套接字连接到服务器端,建立连接之后就可以通信。
import socket # 导入socket模块
s2 = socket.socket() # 实例化socket 对象
s2.connect(address) # address 地址必须是一个元组:(host,port)
# 数据以字节串格式返回,bufsize指定最多可以接受的数量。
s2.recv(bufsize[,flag])
# 将参数string包含的字节串发送到服务器端
s2.send(string[,flag])
s2.close()
示例:使用socket模块构建一个网络通信服务。
# 新建server.py,输入以下命令,作为服务器端响应文件
import socket
# 创建服务端服务
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('localhost',6999)) # 绑定要监听的端口,本地计算机6999
s.listen(5) # 开始监听,使用5个连接排队
while True:
conn,addr = s.accept()
print(conn,addr) # 输出连接信息
try:
data = conn.recv(1024) # 接收数据
print('recive:',data.decode()) # 解码
conn.send(data.upper()) # 发送数据
conn.close() # 关闭连接
except:
print('出现异常')
break
# 新建client.py,输入以下命令,作为客户端请求文件
import socket
c = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
c.connect(('localhost',6999)) #
msg = '欢迎新同学!'
c.send(msg.encode('utf-8')) # 发送一条信息,将字符串转换为字节流
data = c.recv(1024) # 接收信息,大小为1024字节
print('recv:',data.decode()) # 输出接收信息
c.close() # 关闭
socketserver模块封装了socket模块和select模块,使用多线程处理多个客户端的连接,使用select模块处理高并发访问。
服务类
服务类包含5种类型:
请求处理类
socketserver 模块提供请求处理类BaseRequestHandler, 以及派生类StreamRequestHandler(处理流式套接字)和DatagramRequestHandler(处理数据报套接字)。请求处理类有3种方法:
使用socketserver创建一个服务,具体步骤如下:
示例:使用socketserver模块构建一个网络通信服务。
# 新建server1.py,输入以下命令,作为服务器端响应文件
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler): # 自定义请求处理类
def handle(self): # 重写handle()方法
try:
while True:
self.data = self.request.recv(1024) # 接收数据
print(self.client_address,self.data) # 打印数据
if not self.data: # 如果没有接收到数据
print('连接丢失')
break # 结束轮询
self.request.sendall(self.data.upper()) # 向客户端响应数据
except Exception as e:
print(self.client_address,'连接断开')
finally:
self.request.close() # 关闭
def setup(selfself): # 重写setup()方法
print('setup被执行')
def finish(self): # 重写finish()方法
print('finish被执行')
if __name__ == "__main__":
s = socketserver.TCPServer(('localhost',9999),MyTCPHandler)
s.serve_forever()
# 新建client1.py,输入以下命令,作为客户端请求文件
import socket
c = socket.socket()
c.connect(('localhost',9999)) # 连接到服务器
while True:
cmd = input('是否退出(y/n)').strip() # 是否退出
if len(cmd)==0:
continue
if cmd=='y' or cmd=='Y': # 退出交流
break
c.send(cmd.encode()) # 发送信息
cmd_res=c.recv(1024) # 接收信息
print(cmd_res.decode()) # 打印信息
c.close() # 关闭