python套接字socket编程,原理、步骤、计算器实例
什么是套接字socket编程
套接字socket是一种客户端/服务器端,即C/S的架构机制,主要用于网络中的进程之间的通信。需要两个特殊的文件,一个在服务器端,一个在客户端,并各自维护。
套接字socket编程更重要的是其编程思想,而且每一种计算机语言(可以用来写后端的语言)基本上都可以实现套接字socket编程,而不是python的专有的。
socket(网络)编程实际上就是对文件进行打开、关闭、读/写的操作,之前在网络编程那一章节介绍过网络编程到底编了个啥,里头有介绍说了网络编程更多的是在应用层开发,处理数据包的组装、发送、接收、解码、呈现等通信任务,这其中的数据包便可理解为文件。
python语言socket编程服务器端的原理机制、步骤
如上所言,socket编程的过程实际上就是对文件进行“打开、关闭、读/写”的操作,下面,我们就基于这三个步骤来堆socket编程的原理机制进行进一步的细化。
步骤:服务器端接收文件
服务器端打开文件之前,需要接收文件,于是就有了下面的方法、步骤:
- 创建socket对象:用socket()函数;
- 绑定IP地址和端口:用bind()函数;
- 监听端口,等待客户端发送来的请求:用listen()函数;
- 阻塞客户端的请求:用accept()函数,参考:阻塞和非阻塞;
- 接收数据:用recv()函数
步骤:服务器端读/写数据
服务器端通过socket套接字接收数据之后,就是相应的数据处理,或者说是数据交互,这个过程中可以根据自个的需求来设计程序。
步骤:服务器端发送数据
数据处理完成之后,需要通过发送处理完的数据给客户端,以完成C/S架构的数据交互,该过程中使用send()或sendall()函数。
步骤:服务器端关闭连接
客户端的请求处理完成之后,服务器端的socket需要关闭连接,好腾出线程时间片。这个过程中close()函数。
客户端socket编程的原理机制、步骤
客户端的socket编程基本类似,不过相对来说会简单许多:
步骤:客户端创建socket对象
也是用socket()函数;
步骤:客户端通过IP/端口链接服务器端
用connect( address )向服务器端发起连接,其中address以元组的形式传参,如果发生错误,会引发socket.error错误。
步骤:客户端发送数据
用send()或sendall()函数
步骤:客户端接收数据
用recv()函数
步骤:客户端关闭连接
用close()函数
socket编程实例
下面我们用python的socket编程开发一个客户端和服务器端交互而成的计算器。注意,这里的客户端和服务器端都在本地(本机)。
server.py服务器端
# -*- coding:utf-8 -*-
import socket
ip_port = ('127.0.0.1',5656)
#记住address是元组的格式,其中127.0.0.1通常用来表示本机,5656表示端口;
# 通常情况下,0~1023是保留端口,1024~65535为用户端口,可以随便设置。
#步骤:用socket()方法创建socket对象
sk = socket.socket()
#步骤:用bind()方法绑定服务器地址,这里是本机
sk.bind(ip_port)
#步骤:用listen()函数监听客户端发送来的请求
sk.listen(5)
#其中5表示在拒绝连接之前,操作系统可以挂起的最大连接数量
#步骤:利用阻塞机制,等待连接
connect, address = sk.accept()
#accept()函数返回的connect是连接的通信对象,用来接收、发送数据,address是连接客户端的地址
while True:
data = connect.recv(1024).decode()
#1024为一次接收数据的最大量——数据可以分多次进行接收——这样可以避免数据太大,瘫痪内存;
#网络编程就是对数据按规定好的协议进行组装成包、发送、接收、解码、呈现等过程的处理,
#所以注意decode()函数解码的作用
if data == 'socket_ok':
print('通信完成')
break
datalist = list(data)
f = datalist[1]
a = float(datalist[0])
b = float(datalist[2])
if f == '+':
result = a+b
elif f == '-':
result = a-b
elif f == '*':
result = a*b
elif f== '/':
result = a/b
else:
continue
connect.sendall(str(result).encode()) #这里为什么要用str()函数来转化呢?因为int或float类型没有encode()函数
#有解码,就必须有编码encode()就是用来编码的
connect.close()
client.py客户端
# -*- coding:utf-8 -*-
import socket
ip_port = ('127.0.0.1', 5656)
#注意要与server端的保持一致
#创建socket对象
sk = socket.socket()
#连接server端
sk.connect(ip_port)
while True:
data = input('计算:')
if data == '':
continue
data = data.encode() #发送之前要进行编码
sk.sendall(data)
if data == 'socket_ok':
print("socket结束!")
recv_data = sk.recv(1024).decode()
if recv_data != '':
print('%s = %s'%(data,recv_data))
sk.close()
如何同时运行python两个脚本文件
因为这是服务器端和客户端的通信,所以必须两个都是启动运行的状态。我们可以用如下代码在终端同时运行两个python脚本文件:
python3 server.py & python3 client.py
需要注意两点:1、为什么是python3而不是python,这是为了避免python版本的冲突导致程序出错;2、server.py服务器端的脚本文件应该先运行。
上面实例的代码输出:
算:1+2
b'1+2' = 3.0
计算:1/2
b'1/2' = 0.5
计算:1*2
b'1*2' = 2.0
socket编程出现 [Errno 61] Connection refused错误怎么办
因为服务器端和客户端都在本地(本机上),所以很可能会发生 [Errno 61] Connection refused错误,那该怎么办呢?可以参考:socket编程出现 [Errno 61] Connection refused错误解决办法
python的socket编程的原理、步骤就先介绍到这里,下一节我们将介绍socket的多线程服务器。