最近在学习python多线程和网络socket编程,以一个小的多线程socket程序作为练习,展示python多线程及网络socket编程的主要使用方法。
python多线程实现方式主要有三种:
其中,常用的方法为第一种和第三种。第一种方法实现相对简单,直接将待执行函数作为参数传递我给threading.Tread(target = func , args = ( XX,XX ))执行,其中target参数是即将在线程中执行的函数,args是函数参数。示例如下:
import threading
def add(x , y) :
print(x + y)
t = threading.Thread(target=add , args=(1 , 2))
t.start()
第三种方法使用较为灵活,自定义线程类继承自threading.Thread类,并重写run方法即可,将线程需要执行的操作在run方法中实现,示例如下:
import threading
class MyThread(threading.Thread) :
def run(self):
print("my thread")
t = MyThread()
t.start()
使用自定义线程类定义聊天线程,其中重写Thread类的run方法控制线程执行:
#coding:utf-8
"""
Created by cheng star at 2018/4/27 20:13
@email : [email protected]
"""
import threading
"""
使用threading.Thread 线程类创建聊天线程
"""
class ChatThread(threading.Thread) :
def __init__(self , func , args , name = ""):
threading.Thread.__init__(self)
self.func = func # 线程待执行的函数
self.args = args # 线程待执行函数的参数
self.name = name # 线程名
def run(self) :
# 执行线程
self.res = self.func(*self.args) # 使用可变长参数处理创建线程时传入的参数元组,
def getResult(self):
# 获取线程执行结果
return self.res
if __name__ == "__main__" :
pass
2、socket服务端开发
socket服务端开发基本流程:
以下代码基于第一节自定义的聊天线程实现服务器端的多线程:
#coding:utf-8
"""
Created by cheng star at 2018/4/27 19:19
@email : [email protected]
"""
import socket
from time import ctime
from DataAnalysisForPython.python_learning.python_threading_socket import chatThread
import sys
class TCPServer() :
def __init__(self , host , port) :
print("enter function >>>>>> %s" % sys._getframe().f_code.co_name)
self.host = host
self.port = port
self.bufsize = 1024 # 设置缓冲区大小
self.addr = (self.host , self.port) # 进行主机和端口时使用的参数(元组)
def getTcpConnection(self):
# 创建TCP连接对象
print("enter function >>>>>> %s" % sys._getframe().f_code.co_name)
self.tcpServer = socket.socket(socket.AF_INET , socket.SOCK_STREAM) # 创建tcp连接对象
self.tcpServer.bind(self.addr) # 绑定主机和端口
self.tcpServer.listen(5) # 设置允许的最大连接数
def waitingConnection(self):
print("enter function >>>>>> %s" % sys._getframe().f_code.co_name)
# 等待客户端连接
index = 1
while True :
print("waitting for connection ...")
conn , addr = self.tcpServer.accept() # 获取客户端连接返回的连接对象和连接地址,此连接对象用于和客户端交互
print("connected from %s" %addr[0])
ct = chatThread.ChatThread(self.chatting , (conn ,)) # 基于自定义线程类创建聊天线程,其中参数self.chatting是待执行的聊天处理函数,(conn ,)是参数元组,注意元组最后的逗号
ct.start() # 启动线程
def chatting(self , conn) :
# 聊天处理函数
print("enter function >>>>>> %s" % sys._getframe().f_code.co_name)
try :
while True :
data = conn.recv(self.bufsize).decode("utf8") # 接受客户端发送的信息并进行转码
print("server receive data %s" %data)
if data.strip().lower() == "bye" :
# 判断是否结束聊天
break
conn.send(("[%s] %s" %(ctime() , data)).encode("utf8")) # 服务端发送信息到客户端,已bytes数组格式发送
except InterruptedError as e :
pass
except EOFError as e :
pass
except Exception as e :
pass
finally :
print("close connection")
conn.close() # 断开当前tcp连接
def tcpClose(self):
print("enter function >>>>>> %s" % sys._getframe().f_code.co_name)
self.tcpServer.close()
def main() :
host = "localhost"
port = 1234
testChat = TCPServer(host , port)
testChat.getTcpConnection()
testChat.waitingConnection()
if __name__ == "__main__" :
main()
3、socket客户端开发
socket客户端代码开发不用实现多线程,每个客户端即为一个线程,客户端只需要与服务端建立连接即可与服务端进行通信,与服务端建立连接的函数为connect,其参数与socket服务端bind函数参数相同,即为(主机、端口),连接建立后即可进行通信。服务端代码实现如下:
#coding:utf-8
"""
Created by cheng star at 2018/4/27 19:41
@email : [email protected]
"""
import socket
import sys
class TcpClient() :
def __init__(self , host , port):
print("enter function >>>>>> %s" %sys._getframe().f_code.co_name)
self.host = host
self.port = port
self.bufsize = 1024
self.addr = (self.host , self.port)
def getTcpConnection(self):
print("enter function >>>>>> %s" % sys._getframe().f_code.co_name)
self.tcpClient = socket.socket(socket.AF_INET , socket.SOCK_STREAM) # socket.SOCK_STREAM 建立TCP连接
self.tcpClient.connect(self.addr) # 通过执行主机地址和端口号与服务端建立连接
def chatting(self):
print("enter function >>>>>> %s" % sys._getframe().f_code.co_name)
while True :
data = input("> ").encode("utf8")
if data.decode("utf8").strip().lower() == "bye" :
break
print(data)
self.tcpClient.send(data) # 发送信息到服务端
recvData = self.tcpClient.recv(self.bufsize) # 接受服务端的信息
if recvData.decode("utf8").strip().lower() == "bye" :
break
print(recvData.decode("utf8"))
self.tcpClient.close() # 关闭客户端连接
def main() :
host = "localhost"
port = 1234
tc = TcpClient(host , port)
tc.getTcpConnection()
tc.chatting()
if __name__ == "__main__" :
main()
基于上述代码,首先运行服务端进行监听,然后分别启动三个客户端程序与客户端通信,三个客户端分别发送hello java,hello python,hello javascript字符串,服务端响应结果如下所示:
以上分别简述了python threading模块多线程编程的常用方法及简单示例,并结合python socket网络编程实现多线程和网络编程的示例。
以上仅代表个人观点,谢谢!
参考文献:Python核心编程(中文第二版) Wesley J.Chun 著 CPUG 译