陽光明媚的午后,想想最近要開始從寫Java到寫Python了,就隨手打開電腦來體驗一下Python與Java之間的不同吧~
記得我還在上大二的時候,那個時候才開始學Java,最感興趣的就是Java書最后章節講的socket套接字那部分,第一次看到同時打開多個黑底白字的shell界面的樣子,那么的激動T.T~那個時候還不知道什么是多線程,一個客戶端就讓其他的客戶端不工作了…..那會感覺多線程是我學的最麻煩的地方….那時用了一個下午搞了個多線程的socket程序樂呵呵的玩了好久~~
要說我最討厭Python什么,那一定是它沒有java一個方法中的{},取而代之的居然是縮進….真心好不爽額….吐槽就到這里了T.T,這次看了一下Python的socket教程發現和Java大同小異,依舊是創建連接,客戶和服務器通過send和recv方法通信,最后進行關閉,而為了防止一個客戶端與服務端連接導致其他客戶端掛起的現象,我還特意加上了Python的多線程來保證不會出現這個現象,對於Python的多線程,我更傾向於創建threading.Thread的子類來包裝一個線程對象,可能這與我經常寫Java有關吧~~更熟悉這種方式,下面就把服務端和客戶端的代碼貼出來:
#coding=utf-8 import socket import threading,getopt,sys,string opts, args = getopt.getopt(sys.argv[1:], "hp:l:",["help","port=","list="]) #設置默認的最大連接數和端口號,在沒有使用命令傳入參數的時候將使用默認的值 list=50 port=8001 def usage(): print """ -h --help print the help -l --list Maximum number of connections -p --port To monitor the port number """ for op, value in opts: if op in ("-l","--list"): list = string.atol(value) elif op in ("-p","--port"): port = string.atol(value) elif op in ("-h"): usage() sys.exit() def jonnyS(client, address): try: #設置超時時間 client.settimeout(500) #接收數據的大小 buf = client.recv(2048) #將接收到的信息原樣的返回到客戶端中 client.send(buf) #超時后顯示退出 except socket.timeout: print 'time out' #關閉與客戶端的連接 client.close() def main(): #創建socket對象。調用socket構造函數 #AF_INET為ip地址族,SOCK_STREAM為流套接字 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #將socket綁定到指定地址,第一個參數為ip地址,第二個參數為端口號 sock.bind(('localhost', port)) #設置最多連接數量 sock.listen(list) while True: #服務器套接字通過socket的accept方法等待客戶請求一個連接 client,address = sock.accept() thread = threading.Thread(target=jonnyS, args=(client, address)) thread.start() if __name__ == '__main__': main()
為了防止客戶數量過多而造成后面的客戶等待,我設置了超時時間,雖然不能從更本解決這個問題,但是可以防止一些客戶端白白占用着連接數而不工作,也算是總討巧的方案了~而且通過傳入參數的方式也可以方便的控制監聽的端口號和允許最多的連接數,雖然沒有考證過系統最多開啟多少個進程,不過對於一個練習而言已經足夠了,希望有人知道的話歡迎留言告訴我哈~
下面是客戶端的:
#coding=utf-8 import getopt,socket,sys,string opts, args = getopt.getopt(sys.argv[1:], "hi:p:",["help","ip=","port="]) #設置默認的ip地址和端口號,在沒有使用命令傳入參數的時候將使用默認的值 host="localhost" port=8001 def usage(): print """ -h --help print the help -i --ip Enter the IP address to connect -p --port Enter the port number to connect """ for op, value in opts: if op in ("-i","--ip"): host = value elif op in ("-p","--port"): port = string.atol(value) elif op in ("-h"): usage() sys.exit() def main(): #創建socket對象。調用socket構造函數 #AF_INET為ip地址族,SOCK_STREAM為流套接字 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #設置要連接的服務器的ip號和端口號 sock.connect((host, port)) #客戶端輸入一個字符串給服務器 message = raw_input("inupt:") #pdb.set_trace() sock.send(message) print 'ServerOupt:'+ sock.recv(2048) #關閉與服務器的連接 sock.close() if __name__ == '__main__': main()
客戶端就相對簡單的多了,很簡單的一個讀取用戶輸入,發送給服務器然后接收回來這樣一個簡單的功能,在設置過編碼之后中文什么的也是可以的了~值得注意的就是recw()方法中設置的發送大小,太小的話會報錯的~
總體來說和我第一次用Java來實現的時候比起來,現在已經輕松容易的多了,不過也正好可以借此機會溫習一下過去的知識了~學而不思則罔,思而不學則殆!
