Weblogというかメモ帳

Lotus-NetWork

topimg

2010/7/22 の記事

今回はPythonにおけるマルチスレッドプログラミングについて。

そもそもマルチスレッドとはなにかといいますと、スレッドという処理の塊の単位を複数に分けること。たとえばCPUのコアが2つなら(デュアルコアCPU)、そのコア一つ一つに処理を割り振ったり。

まぁ並行処理させたり。

その辺はプリエンプティブマルチタスクとか、ノンプリエンプティブマルチタスクの話が絡んでくるのであれだけど。

OSが管理するのがプリエンプティブマルチタスク。アプリケーション自体がタスク、CPUを管理するのがノンプリエンプティブマルチタスク。

メリットとして、

処理の待ち時間の節約。

ネットワーク絡みの処理だとレスポンスまでに時間がかかってその間に処理をおこなう。

複数の処理を並列して行う。

など、メリットがある。リソースの有効な使い方ができる。

今回はそのマルチスレッドプログラミングをPythonで実装する。

Pythonのマルチスレッド機能は、OSのスレッド機能と密接に動くため、オーバヘッドが少ない。

Pythonにおけるマルチスレッドを行うにはthreadingモジュールのThreadクラスを継承すると簡単。他にもthreadingモジュールがある。(threadモジュールのthreadingとは別。)

threadingモジュールに定義されているThreadクラスがスーパークラスで、自分が作成するクラスはそれを継承したサブクラスになる。

このサブクラスではrun()というメソッド(関数)をオーバーライドする。

オーバーライドとはサブクラスでメソッドを再定義すること。書き換えるみたいな感じ。

__init__()メソッドも必要があるならオーバーライドする。初期化とか。

Threadの__init__()メソッドを継承しないとstart()とか使えない。

なお、run()メソッドは直接インスタンスから指定し実行うするのではなく、インスタンスからstart()メソッドを呼び出す。

そうすることで直接ではなく、間接的にrun()で定義した処理を行うことができる。直接run()を呼び出してはいけないみたい。

直接呼び出すと、プロンプトが戻らない(制御きかない。)

今回私はマルチスレッドを活かすため、ネットワークプログラミングにPythonのマルチスレッディングを使用した。

ネットワークプログラミングといっても簡単なもので、Socket通信による簡単なチャットシステム。

一つのスレッドでは処理をまっていないと(listen)いつ相手からメッセージがくるかわからない。

listenしながらも様々な処理を行うためにはどうしてもマルチスレッドを利用せざるを得ない…かも。


import socket
from threading import Thread,Lock
import thread
import sys
 
class SocketServer(Thread,object):
 
    def __init__(self):
 
        #super class init
        Thread.__init__(self)
 
        #socket settings
        self.s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.s.settimeout(1000)
        self.while_count = 0
 
        self.while_flag=True
        self.data=[]
 
         #port number options
         if "-p" in sys.argv[1:]:
            self.port = sys.argv[sys.argv.index("-p")+1]
            try :
                self.port=int(self.port)
            except :
                print "Error! Port number is integer."
                sys.exit() 
 
        #Default port number = 7777 
        else :
            self.port = 7777
 
    #Main Thread.
    def run(self):
 
        print "=" * 50
        print "Start the server program."
        print "Listening at : %s" % self.port
        print "=" * 50
        print "Pending connections..."
 
        try:
            self.s.bind(('',self.port))
            self.s.listen(10)
        except :
            print "Network error."
            print "Is the port number is already being used?"
            sys.exit()
 
        #While get recv
        while self.while_flag:
 
            self.conn,self.addr = self.s.accept()
 
            #print connect to
            if self.while_count == 0:
                print "Connected by %s " % self.addr[0]
                self.while_count=1
 
            else :
                pass
 
            try :
                self.data=self.conn.recv(1024).encode("utf-8")
                self.conn.send("OK")
 
                if self.data == "exit":
                    print "%s is closed the connection" % self.addr[0]
                    self.data="=== Withdrawal ==="
                self.conn.close()
 
            except :
                print "Failed recv."
                self.conn.close()
 
            try :
                if len(self.data) !=0:
                    print "-" * 50
                    print "%s => %s" % (self.addr[0],self.data)
                    self.conn.close()
            except :
                pass
 
            self.conn.close()
 
    #Send to argument.
    def send(self,val):
 
        try :
            self.conn.send(val+"\n")
 
        except :
            print "Error! one more please."
 
    #Thread stop method
    def stop(self):
 
        self.while_flag=False
 
        try:
            print "wait..."
            self.conn.send("Please enter a space , charcter. exsample => [bye].")
 
        except:
            print "Please enter a space , charcter or a client"
 
        self.conn.close()
        print "Connection will be closed"

上記はSocket通信を使ったスレッドの例。

これだけではあまり意味をなさないが、上記の処理をバックグラウンド、というよりスレッドとして後ろで動くので、ネットワーク特有の処置待ちをしないですむ。

このプログラムは、Socket通信をする際、サーバとなるスレッド。

未完成だが、Clientがパケットを送信してくると、サーバのプロンプトにIPアドレスと送られてきた内容を表示する、など簡単なプログラムが組んである。

今、このマルチスレッディングの技術をつかって、開発中なので、また数日し、完成したらここにアップしようかと。

uO