# HW11 多緒網路程式設計作業 ## 練習1 ### 通過畫面截圖 ![](https://hackmd.io/_uploads/Bkr3ekiH3.png) ### 程式碼 Server ```python= import socket import threading MaxClient = 10 def ThreadMain(threadArgs): clntIndex = threadArgs['clntIndex'] clntSocki = threadArgs['Sock'] echoBuffer = bytearray(1000) while True: recvMsgSize = clntSocki.recv_into(echoBuffer, 1000) # 尋找可用的客戶端索引 if recvMsgSize <= 0: threadArgs['Totalclnt'] -= 1 threadArgs['clntSock'][clntIndex] = 0 print(f"Connection[socket:{clntSocki}] closed. (Current Client:{threadArgs['Totalclnt']})") break clntSocki.sendall(echoBuffer[:recvMsgSize]) clntSocki.close() threadArgs['clntSock'][clntIndex] = 0 def main(): threadArgs = { 'clntIndex': 0, 'clntSock': [0] * MaxClient, 'Totalclnt': 0, 'Sock': None } servSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) servSock.bind(('127.0.0.1', 5678)) servSock.listen(3) print("Server is waiting for clients.") while True: Sock, addr = servSock.accept() for i in range(MaxClient): if threadArgs['clntSock'][i] == 0: threadArgs['clntIndex'] = i break threadArgs['Sock'] = Sock threadArgs['clntSock'][i] = Sock threadArgs['Totalclnt'] += 1 thread = threading.Thread(target=ThreadMain, args=(threadArgs,)) thread.start() print(f"New client with thread ID: {thread.ident} and socket:{threadArgs['clntSock'][i]} (Current Client:{threadArgs['Totalclnt']})") if __name__ == "__main__": main() ``` ### 程式碼 Client ```python= import socket import time MAXLINE = 1024 def main(): serv = ('127.0.0.1', 5678) # 伺服器的 IP 位址和埠號 message = "I love NP!!".encode('utf-8') # 要發送的訊息 sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 建立 TCP socket sd.connect(serv) # 連接到伺服器 while True: str_msg = "How are you?".encode('utf-8') # 要發送的訊息 sd.sendall(str_msg) # 發送訊息到伺服器 print(f"send: {str_msg.decode('utf-8')}") data = sd.recv(MAXLINE) # 接收從伺服器返回的訊息 if not data: # 如果沒有接收到訊息,則跳出迴圈 break str_data = data.decode('utf-8') # 解碼接收到的訊息 print(f"recv: {str_data}") time.sleep(1) # 程式暫停 1 秒 sd.close() # 關閉 socket if __name__ == "__main__": main() ``` ## 練習2 ### 通過畫面截圖 ![](https://hackmd.io/_uploads/HJ_pfJiSn.png) ### 程式碼 Server ```python= import socket import threading MaxClient = 10 def ThreadMain(threadArgs): clntIndex = threadArgs['clntIndex'] # 客戶端索引 clntSocki = threadArgs['Sock'] # 客戶端 socket echoBuffer = bytearray(1000) # 接收和發送資料的緩衝區 while True: recvMsgSize = clntSocki.recv_into(echoBuffer, 1000) # 接收客戶端傳送的資料 if recvMsgSize <= 0: # 如果接收到的資料大小小於等於 0,表示客戶端斷開連接 threadArgs['Totalclnt'] -= 1 # 總客戶端數減 1 threadArgs['clntSock'][clntIndex] = 0 # 清除客戶端 socket print(f"Connection [socket:{clntSocki}] closed. (Current Client:{threadArgs['Totalclnt']})") break clntSocki.sendall(echoBuffer[:recvMsgSize]) # 將接收到的資料回傳給客戶端 clntSocki.close() # 關閉客戶端 socket threadArgs['clntSock'][clntIndex] = 0 # 清除客戶端 socket def main(): threadArgs = { 'clntIndex': 0, # 客戶端索引 'clntSock': [0] * MaxClient, # 客戶端 socket 列表 'Totalclnt': 0, # 目前連接的客戶端數量 'Sock': None # 當前處理的客戶端 socket } servSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 建立 TCP socket servSock.bind(('0.0.0.0', 5678)) # 綁定伺服器 IP 位址和埠號 servSock.listen(3) # 監聽連接請求 print("Server is waiting for clients.") while True: Sock, addr = servSock.accept() # 接受客戶端連接請求 for i in range(MaxClient): if threadArgs['clntSock'][i] == 0: # 找到空閒的客戶端位置 threadArgs['clntIndex'] = i # 設置客戶端索引 break threadArgs['Sock'] = Sock # 設置處理的客戶端 socket threadArgs['clntSock'][i] = Sock # 設置客戶端 socket threadArgs['Totalclnt'] += 1 # 客戶端數量加 1 thread = threading.Thread(target=ThreadMain, args=(threadArgs,)) # 創建新的執行緒處理客戶端連接 thread.start() # 啟動執行緒 print(f"New client with thread ID: {thread.ident} and socket:{threadArgs['clntSock'][i]} (Current Client:{threadArgs['Totalclnt']})") if __name__ == "__main__": main() ``` ### 程式碼 Client ```python= import socket import time MAXLINE = 1024 def main(): serv = ('127.0.0.1', 5678) # 伺服器的 IP 位址和埠號 message = "I love NP!!".encode('utf-8') # 要發送的訊息 sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 建立 TCP socket sd.connect(serv) # 連接到伺服器 while True: str_msg = "How are you?".encode('utf-8') # 要發送的訊息 sd.sendall(str_msg) # 發送訊息到伺服器 print(f"send: {str_msg.decode('utf-8')}") data = sd.recv(MAXLINE) # 接收從伺服器返回的訊息 if not data: # 如果沒有接收到訊息,則跳出迴圈 break str_data = data.decode('utf-8') # 解碼接收到的訊息 print(f"recv: {str_data}") time.sleep(1) # 程式暫停 1 秒 sd.close() # 關閉 socket if __name__ == "__main__": main() ``` ## 練習3 ### 通過畫面截圖 ![](https://hackmd.io/_uploads/By3ZEkjr3.png) ### 程式碼 Server ```python= import socket import threading MaxClient = 10 def ThreadMain(threadArgs): clntIndex = threadArgs['clntIndex'] clntSocki = threadArgs['Sock'] echoBuffer = bytearray(1000) while True: recvMsgSize = clntSocki.recv_into(echoBuffer, 1000) if recvMsgSize <= 0: threadArgs['Totalclnt'] -= 1 threadArgs['clntSock'][clntIndex] = 0 print(f"Connection[socket:{clntSocki}] closed. (Current Client:{threadArgs['Totalclnt']})") break clntSocki.sendall(echoBuffer[:recvMsgSize]) clntSocki.close() threadArgs['clntSock'][clntIndex] = 0 def main(): threadArgs = { 'clntIndex': 0, 'clntSock': [0] * MaxClient, 'Totalclnt': 0, 'Sock': None } servSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) servSock.bind(('0.0.0.0', 5678)) servSock.listen(3) print("Server is waiting for clients.") while True: Sock, addr = servSock.accept() for i in range(MaxClient): if threadArgs['clntSock'][i] == 0: threadArgs['clntIndex'] = i break threadArgs['Sock'] = Sock threadArgs['clntSock'][i] = Sock threadArgs['Totalclnt'] += 1 thread = threading.Thread(target=ThreadMain, args=(threadArgs,)) thread.start() print(f"New client with thread ID: {thread.ident} and socket:{threadArgs['clntSock'][i]} (Current Client:{threadArgs['Totalclnt']})") if __name__ == "__main__": main() ``` ### 程式碼 Client ```python= import socket import threading def ThreadMain(threadArgs): sd = threadArgs.sd str_buffer = bytearray(1024) while True: n = sd.recv_into(str_buffer) if n <= 0: break print(f"recv: {str_buffer[:n].decode()}") sd.close() threadArgs.close() def main(): servAddr = ('127.0.0.1', 5678) sd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sd.connect(servAddr) threadArgs = threading.Thread(target=ThreadMain, args=(sd,)) threadArgs.start() while True: str_input = input() sd.sendall(str_input.encode()) if __name__ == "__main__": main() ``` ## 心得 第三題不知道為甚麼寫不出來,Debug很久了也寫不出來