Python3 Socket和SocketServer 網絡編程


socket只能實現同時一個服務和一個客戶端實現交互,socketserver可以實現多個客戶端同時和服務端交互

1.利用Socket編寫簡單的同一個端口容許多次會話的小案例:

服務端:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
# Author:CarsonLi

import socket
'''模擬服務端'''
server=socket.socket()
server.bind(('localhost',6969)) #綁定需要監聽的端口
server.listen(5) #開始監聽
print('開始等待客戶端發起請求')
while True:
    conn,addr=server.accept() #等待客戶端連接,並且返回兩個參數
    #conn是客戶端連接過來而在服務器為期生成的一個連接實例, addr為連接的地址
    print('服務器為客戶端連接生成的實例:',conn)
    print('客戶端連接地址:',addr)
    while True:
        data=conn.recv(1024) #接收客戶端發來的信息
        print(data.decode())
        conn.send(data.upper()) #返回個客戶端信息
server.close()

  客戶端:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
# Author:CarsonLi
import socket
'''模擬客戶端'''
client=socket.socket() #聲明socket類型,同時創建socket連接對象
client.connect(('localhost',6969))
while True:
    msg=input('請輸入需要發送的內容>>:').strip()
    if len(msg)==0: #輸入信息為空時不發送,否則在linux下運行時會出現死循環
        continue
    else:
        client.send(msg.encode("utf-8")) #發送信息 在python3以后都只能發送byte類型,
        data=client.recv(1024)#接收到的信息,需要定義大小
    print(data.decode())

client.close()

  服務端運行結果:

D:\Python3.7.0\python.exe D:/PycharmProjects/OldManS14/day07/socket_server.py
開始等待客戶端發起請求
服務器為客戶端連接生成的實例: <socket.socket fd=436, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 6969), raddr=('127.0.0.1', 64403)>
客戶端連接地址: ('127.0.0.1', 64403)
第一次
第二次
第三次
第四次
第五次

  客戶端運行結果:

D:\Python3.7.0\python.exe D:/PycharmProjects/OldManS14/day07/socket_client.py
請輸入需要發送的內容>>:第一次
第一次
請輸入需要發送的內容>>:第二次
第二次
請輸入需要發送的內容>>:第三次
第三次
請輸入需要發送的內容>>:第四次
第四次
請輸入需要發送的內容>>:第五次
第五次
請輸入需要發送的內容>>:

 2.SocketServer 支持多個客戶端

'''
SocketServer 支持多個客戶端
'''
import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):
    '''
    處理我們的socket,這個類必須繼承socketserver.BaseRequestHandler
    並且實現里面的handler函數
    '''

    def setup(self):
        print("這里處理請求前的的事情,也可以不寫")
        pass

    def handle(self):
        '''處理客戶端請求'''
        while self:
            try:
                self.data = self.request.recv(1024).strip()
                print("{} wrote:".format(self.client_address[0]))#客戶端地址
                print(self.data)
                self.request.send(self.data.upper())
            except ConnectionResetError as e:
                print("客戶端斷開", e)
                break

    def finish(self):
        print("處理請求完成之后的事情,也可以不寫")
        pass

if __name__=="__main__":
    HOST,PORT = "localhost",6969
   # server = socketserver.TCPServer((HOST,PORT),MyTCPHandler  #不支持多並發
    server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler) #支持多線程,多並發
   # server = socketserver.ForkingTCPServer((HOST, PORT), MyTCPHandler)  # 支持多進程,多並發,windows不能實現,linux上可以
    #server.allow_reuse_address() #解決 在 socketServer程序里面出現 地址已經被占用
    server.serve_forever()

 3.模擬ftp上傳下載(只實現了里面的上傳功能,其他功能也大同小異,就沒有一一去寫)

import socketserver,os,json

'''模擬ftp上傳下載的服務端'''

class MyTCPHandler(socketserver.BaseRequestHandler):

    def setup(self):
        pass

    def handle(self):
        while True:
            try:
                self.data = self.request.recv(1024).strip()
                print("{}".format(self.client_address[0]))
                msg_dic = json.loads(self.data.decode())
                print(msg_dic)
                if hasattr(self,"server_"+msg_dic.get("action")):
                    func = getattr(self,"server_"+msg_dic.get("action"))
                    func(msg_dic)
            except ConnectionResetError as e:
                print(e)
                break

    def server_put(self,*args):
        '''服務端文件上傳操作'''
        msg_dic = args[0]
        file_name = msg_dic.get("file_name") #文件名稱
        file_size = msg_dic.get("file_size")#文件大小
        if os.path.isfile(file_name):
            files = file_name.split(".") #截取文件名添加new ,例如 file.txt ==> file_new.txt
            f = open(files[0]+"_new."+files[1],"wb")
        else:
            f = open(file_name, "wb")
        self.request.send(b"200 ok")
        recv_file_size = 0
        while recv_file_size < file_size:
            recv_data = self.request.recv(1024)
            f.write(recv_data)
            recv_file_size += len(recv_data) #大小計算
        else:
            print("file [%s] has uploaded..." % file_name)
            f.close()

    def server_get(self,*args):
        ''' 下載文件功能 '''
        pass

    def server_del(self,*args):
        ''' 下載刪除功能 '''
        pass

if __name__ == "__main__":
    ip,port = "localhost",9999
    server = socketserver.ThreadingTCPServer((ip,port),MyTCPHandler)
    server.serve_forever()

  客戶端:

import socket,os,json

'''模擬ftp上傳下載的客戶端'''

class MyTCPClient(object):

    def __init__(self):
        self.client=socket.socket()

    def help(self):
        pass

    def connection(self,ip,port):
        '''連接服務器'''
        self.client.connect((ip, port))

    def interactive(self):
        while True:
            input_str = input(">>:").strip()
            if len(input_str) == 0: continue
            action = input_str.split()[0]
            if hasattr(self,"cmd_"+action): #用反射判斷是否存在
                func = getattr(self,"cmd_"+action)
                func(input_str)
            else:
                print(action,"is not exist!")

    def client_put(self,*args):
        '''客戶端文件上傳操作'''
        input_str = args[0]
        input_split = input_str.split()
        if os.path.isfile(input_split[1]):  # 判斷是否是文件
            file_size = os.stat(input_split[1]).st_size
            msg_dic = {
                "action":input_split[0],
                "file_name":input_split[1],
                "file_size":file_size
            }
            self.client.send(json.dumps(msg_dic).encode("utf-8"))  #序列化之后編碼
            server_respone = self.client.recv(1024)  #等待客戶端確認
            f = open(input_split[1],"rb") #打開文件
            for line in f:
                self.client.send(line)
            else:
                print(input_split[1],"upload success!")
                f.close() #關閉文件
        else:
            print(input_split[1], "is not exist!")

    def client_get(self,*args):
        '''文件下載操作'''
        pass

    def client_del(self,*args):
        '''刪除功能'''
        pass

if __name__ == "__main__":
    tcp_client = MyTCPClient()
    tcp_client.connection("localhost",9999)
    tcp_client.interactive()

  

 


免責聲明!

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



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