[Python专题学习]-python Socket网络编程
一.Socket简介
Socket是什么?
a.Socket是电脑网络中进程间数据流的端点
b.Socket操作系统的通信机制
c.应用程序通过Socket进行网络数据的传输


Socket通信方式:Socket分为UDP和TCP两种不同的通信方式。
为什么是Socket?
a.Socket能够适应多种网络协议
b.Socket是基础应用,了解Socket可以举一反三
c.服务器传输大量涉及网络协议,离不开socket应用
二.Socket通信入门
服务端程序socket_server.py
#导入模块 import socket #创建实例 sk = socket.socket() #定义绑定ip和port ip_port = ("127.0.0.1", 8888) #绑定监听 sk.bind(ip_port) #最大连接数 sk.listen(5) #提示信息 print("正在进行等待接受数据...") #接受数据 conn, address = sk.accept() #定义信息 msg = "Hello World!" #返回信息 conn.send(msg)
客户端程序socket_client.py
#导入模块 import socket #实例初始化 client = socket.socket() #访问的服务器端的IP和端口 ip_port = ("127.0.0.1", 8888) #连接主机 client.connect(ip_port) #接收主机信息 data = client.recv(1024) #打印接收的数据 #此处的byte型数据特指python3.x以上 print(data.decode())
先运行服务器端程序,会进入等待接受数据

再运行客户端程序

此时,可以看到服务器端的程序也结束运行了

三.socket客户端连续消息发送
服务端:
#导入模块 import socket import random #创建实例 sk = socket.socket() #定义绑定ip和port ip_port = ("127.0.0.1", 8888) #绑定监听 sk.bind(ip_port) #最大连接数 sk.listen(5) #不断循环,不断接受数据 while True: #提示信息 print("正在进行等待接受数据...") #接受数据 conn, address = sk.accept() #定义信息 msg = "连接成功!" #返回信息 #python3.x以上,网络数据的发送接受都是byte类型 #如果发送的数据是str型的则需要进行编码 conn.send(msg.encode()) #不断接收客户端发来的消息 while True: #接收客户端消息 data = conn.recv(1024) #打印数据 print(data.decode()) #接收到退出指令 if data == b'exit': break #处理客户端数据 conn.send(data) #发送随机数信息 conn.send(str(random.randint(1, 1000)).encode()) #主动关闭连接 conn.close()
客户端:
#导入模块 import socket #实例初始化 client = socket.socket() #访问的服务器端的IP和端口 ip_port = ("127.0.0.1", 8888) #连接主机 client.connect(ip_port) #定义一个循环,不断的发送消息 while True: #接收主机信息 data = client.recv(1024) #打印接收的数据 #此处的byte型数据特指python3.x以上 print(data.decode()) #定义一个循环,不断的发送消息 #输入发送的消息 msg_input = input("请输入发送的消息:") #消息发送 client.send(msg_input.encode()) if msg_input == "exit": break data = client.recv(1024) print(data.decode())
首先运行服务端,再运行先后运行两次客户端如下:


但如果同时开启两个以上socket_client,则会报错,提示每个套接字地址只允许使用一次。这是因为当前的客户端和服务端正在进行通讯,是一种阻塞的状态,当下一个客户端进行连接的时候,它并不能直接马上进行通讯,所以报错了。
四.socket实例化参数含义



五.socket udp通信
socket_server_udp.py
#导入模块 import socket #创建实例 sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #定义绑定的ip和port ip_port = ("127.0.0.1", 8888) #绑定监听 sk.bind(ip_port) #不断循环接受数据 while True: #接收数据 data = sk.recv(1024) #打印数据 print(data.decode())
socket_client_udp.py
#导入模块 import socket #定义实例 sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #定义需要连接的服务器的ip和port ip_port = ("127.0.0.1", 8888) #循环数据的输入 while True: #输入发送的信息 msg_input = input("请输入发送的消息:") #退出循环条件 if msg_input == "exit": break #数据发送 sk.sendto(msg_input.encode(), ip_port) #发送关闭信息 sk.close()
先运行服务器端,再先后运行两次客户端:


与TCP不同的是,UDP的通讯方式是可以进行多次数据发送以及多客户端的连接,因为UDP的通讯方式并不建立一个可靠的通信通道。UDP对于接收来的消息是否同一个客户端发送并不是特别的关心,因此对于多个客户端的连接,UDP服务器虽然没有一个特殊的定义,但是依然能够进行连接。
六.socket非阻塞模块
Socket的非阻塞
平常的访问我们没有见到有阻塞的情况啊,python无法实现吗?如何解决阻塞呢?当然能够解决。
socketserver这个模块可以同时多个客户端进行连接,即实现非阻塞的socket程序,主要是因为它使用了多线程的方式,每进行一次连接就会启一个线程,通过不断启线程的方式来达到与多个客户端连接的目的。它引用了socket、selectors、threading等模块,如下所示:

BaseRequestHandler模块有四个方法,初始化方法和另外三个完全pass的方法,对于要使用socketserver模块的话,就要通过自已定义的类去对这三个方法进行定义,以覆盖原来的方法,这三个方法的执行顺序是setup、handle、finish。

socket_server_tcp2.py
#导入模块 import socketserver import random #定义一个类 class MyServer(socketserver.BaseRequestHandler): #如果handle方法出现报错,则会进行跳过,setup方法和finish方法无论如何都会进行执行 #一般情况下,我们只需去进行handle方法的书写 #首先执行setup def setup(self): pass #然后执行handle def handle(self): #定义连接变量 conn = self.request #发送消息定义 msg = "Hello World!" #消息发送 conn.send(msg.encode()) #进入循环,不断接收客户端的消息 while True: #接收客户端消息 data = conn.recv(1024) #打印消息 print(data.decode()) #接收到exit则进行循环的退出 if data == b'exit': break conn.send(data) conn.send(str(random.randint(1, 1000)).encode()) conn.close() #最后执行finish def finish(self): pass if __name__ == "__main__": #创建多线程实例 server = socketserver.ThreadingTCPServer(("127.0.0.1", 8888), MyServer) #开启异步多线程,等待连接 server.serve_forever()
此时先运行socket_server_tcp2,再运行socket_client


这样的服务器可以同时接收多个客户端的连接和消息处理。
七.文件上传下载
socket用处:运维的时候经常遇见需要文件上传的情况。尤其是运维脚本中需要同时第三方软件没有命令行的时候。
这时候我们可以自已实现。
file_recv.py
#导入模块 import socket #实例化 sk = socket.socket() #定义连接ip和port ip_port = ('127.0.0.1', 9999) #绑定ip和port sk.bind(ip_port) #最大连接数 sk.listen(5) #进入循环接收数据 while True: #等待客户端连接 conn, address = sk.accept() #一直使用当前连接进行数据发送,直到结束标志出现 while True: #打开文件等待数据写入 with open("file", "ab") as f: #接收数据 data = conn.recv(1024) if data == b'quit': break #写入文件 f.write(data) #接收完成标志 conn.send('success'.encode()) #打印提示信息 print('文件接收完成') #关闭连接 sk.close()
file_send.py
#导入模块 import socket #实例化模块 sk = socket.socket() #定义连接ip和port ip_port = ('127.0.0.1', 9999) #服务器连接 sk.connect(ip_port) #文件上传 #打开文件 with open('socket_server_tcp2.py', 'rb') as f: #按每一段分割文件 for i in f: #数据上传 sk.send(i) #等待接收完成 data = sk.recv(1024) #判断服务器是否真正的接收完成 if data != b'success': break #给服务器端发送结束信息 sk.send('quit'.encode())
先运行服务端,再运行客户端,能正常实现文件的上传。
我们可以看到file_recv.py的最后一行代码开发工具给我们标出了黄色,这里的关闭连接没有生效,因为我们上面是while True直接进入等待,我们可以在文件接收的时候,可以接收关闭的程序,将服务器的程序进行关闭的操作等等。
posted on 2019-04-21 10:59 bijian1013 阅读(241) 评论(0) 收藏 举报
浙公网安备 33010602011771号