python利用select實現的Socket Server


# 利用python的select模塊實現簡單的Socket Sever

#實現多用戶訪問,再次基礎上可以實現FTP Server應用程序

# 發布目的,在於解決了客戶端強行終止時,服務器端也跟着程序終止

# 程序的關鍵在:讀就是讀,寫就是寫 ,不要讀寫混着來

# 代碼如下:

Server

 1 __author__ = 'Stone'
 2 # -*- coding: UTF-8 -*-
 3 # !/usr/bin/env python3
 4 import socket
 5 import queue
 6 import select
 7 HOST = '0.0.0.0'
 8 PORT = 8000
 9 s = socket.socket()
10 s.bind((HOST,PORT))
11 s.listen(500)
12 # 設定關閉程序后,能馬上釋放服務器的端口,供后續程序使用
13 s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
14 s.setblocking(0) # 設置為非阻塞模式
15 # 設置列表,新建、發送、異常
16 inputs = []
17 outputs = []
18 #exceptions = []
19 # 存放信息
20 msg_dic = {}
21 inputs.append(s)  # 把自身加進去,偵聽是否有新連接
22 while True:
23     readable,writable,exceptional = select.select(inputs,outputs,inputs)  # select 會阻塞socket
22
25     for r in readable:
26         if r is s:
27             # 說明有新連接過來
28             conn,addr = s.accept()
29             print("新連接:",addr)
30             conn.setblocking(0) # 把單個連接也設置為非阻塞模式,比如:某個連接接收的文件比較大,將會一直占用着(別的程序沒機會處理);設置為非阻塞后,可以等着下次for循環繼續接收
31             inputs.append(conn)
32             msg_dic[conn] = queue.Queue()  # 為每個連接創建消息隊列
33         else:
34             # 說明有連接是活動的
35                 try:
36                     data = r.recv(1024)
37                     if data:
38                         print("接收到了數據:",data.decode('utf-8'))
39                         # 放進消息隊列
40                         msg_dic[r].put(data)
41                         if r not in outputs:
42                             outputs.append(r)  # 並放入發送數據列表
43                     else:
44                         # 連接斷開
45                         print("客戶端斷開連接")
46                         if r in outputs:
47                             outputs.remove(r)
48                         inputs.remove(r)
49                         del msg_dic[r]
50                 except socket.error:     # 解決問題(出現客戶端異常斷開,服務器也跟着斷開),后面不做任何處理,留給exceptional做處理
51                     pass
52 
53     for w in writable:
54         try:
55             send_msg = msg_dic[w].get_nowait()
56         except queue.Empty:
57             print("client [%s]"% w.getpeername()[0],"queue is empty...")
58             outputs.remove(w)
59         else:
60             print("sending message to [%s]"% w.getpeername()[0],send_msg)
61             w.send(send_msg)
62             outputs.remove(w)  # 防止再次執行時,發生empty的異常
63 
64     for e in exceptional:
65         if e in outputs:
66             outputs.remove(e)
67         inputs.remove(e)
68         e.close()
69         del msg_dic[e]
70 s.close()

Client:
 1 __author__ = 'Stone'
 2 # -*- coding: UTF-8 -*-
 3 # !/usr/bin/env python3
 4 import socket
 5 HOST = 'localhost'
 6 PORT = 8000
 7 s_client = socket.socket()
 8 s_client.connect((HOST,PORT))
 9 while True:
10     data = input('>>:').strip()
11     if not data:
12         continue
13     s_client.send(data.encode('utf-8'))
14     recv = s_client.recv(1024)
15     print(recv)
16     #break      # 測試,作為客戶端自動離開
17 s_client.close()

 

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM