python学习笔记---socket及socketserver

socket能实现客户端与服务端的通信。
服务端代码

import socket,os,time,hashlib

server = socket.socket()  #创建socker实例
server.bind(("localhost",9981))
#server.bind(("192.168.1.41",9985))
server.listen(5)   #开始监听,最多同时连接五个客户端
while True:
    print("start to listen...")
    coon,addr = server.accept()   #接收并建立与客户端的连接,程序在此处开始阻塞,只有等到客户端连接进来开始往下执行
    print("build new connection: ", addr)
    while True:
        cmd = coon.recv(1024).decode()    #接收到客户端的byte类型
        print("received msgs is : ",cmd)
        if (len(cmd.split())) == 1:   #如果是linux命令
            data = os.popen(cmd).read()
            if len(data) == 0:data = "来自客户端的cmd命令不存在"
            print(data)
            length = len(data.encode("utf-8"))     # 计算cmd命令结果的bytes长度
            coon.send(str(length).encode("utf-8"))        #服务端向客户端发送cmd命令返回值的长度,因为客户端一次接收的数据量有限,需要知道长度,从而确定几次接受完
            print("nianbao:",coon.recv(1024).decode())
            coon.send(data.encode("utf-8"))  #服务端向客户端发送cmd命令返回值,2次连着的send会产生粘包现象,即cmd返回值长度和返回值会一起发送给客户端。中间可以加入coon.recv()或者time.sleep(0.5)来避免

        if (len(cmd.split())) > 1:
            fname = cmd.split()
            if fname[0].startswith('get'):
                #客户端要下载文件
                if os.path.isfile(fname[1]):
                    total_size = os.stat(fname[1]).st_size   #返回文件的总byte长度
                    coon.send(str(total_size).encode("utf-8"))
                    coon.recv(1024)
                    m = hashlib.md5()
                    with open(fname[1],'rb') as fr:
                        for line in fr:
                            coon.send(line)
                            m.update(line)
                    print(coon.recv(1024).decode())
                    coon.send(m.hexdigest().encode("utf-8"))
                else:
                    print("file is not exist")
                    coon.send(b"file is not exist")

        if not cmd: #如果客户端断开,一面服务端进入死循环
            print("client has interrupt")
            break
server.close()

客户端代码

import socket
import hashlib

client = socket.socket()
client.connect(("localhost",9981))   #客户端建立连接,localhost是回环地址,一般用于测试
#client.connect(("192.168.1.41",9985))   #客户端建立连接
while True:
    msg = input("Enter the infomation sent by client: ")
    if len(msg) == 0:continue     #不能发送为长度为0 的信息
    msg = msg.strip()
    if len(msg.split()) == 1:
        client.send(msg.encode("utf-8"))     #客户端发送消息
        total_len = int(client.recv(1024).decode())   #接收cmd返回值的总长
        client.send(("客户端接收到了cmd返回值的长度 [%s] " % total_len) .encode("utf-8"))    
        print("received_len: ",total_len)
        recv_len = 0 
        while recv_len != total_len:
            data = client.recv(1024)
            recv_len += len(data)    #接收到cmd的长度和
            print("recv_len: ",recv_len)
            print(data.decode())
    #ftp below
    if len(msg.split()) > 1 and msg.startswith("get"):
        file_name = msg.split()[1]
        client.send(msg.encode("utf-8"))
        file_size = client.recv(1024).decode()
        if file_size == "file is not exist": print("file is not exist")
        else:
            client.send(b"begin to recv file")
            fw = open(file_name + ".new",'wb')
            m = hashlib.md5()
            recv_size = 0
            print("file_size ",file_size)
            while recv_size < int(file_size):
                data = client.recv(1024)
                recv_size += len(data)  
                print("recv_size ",recv_size)
                fw.write(data)
                m.update(data)
            fw.close()
            client.send(b"client has recvd done")
            print("md5 from server: ",client.recv(1024).decode())
            print("mdf from client: ",m.hexdigest())
    if msg == 'q':
        break            #断开连接
client.close()

上面的socket实现的功能
1.在客户端输入df/pwd等linxu命令得到返回值(像top这种持续动态有返回值是不能用的)
2.文件从服务端下载,客户端想服务端上传的没有写

用socket一次只能和一个客户端进行交互,其余的客户端要交互需要排队等候,等前面的断开。如果想连接多个客户端那就要用socketserver 如下,主要是服务端的不同

import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            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("err",e)
                break

if __name__ == "__main__":
    HOST,PORT = "localhost",9999
    server = socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
    server.serve_forever()   #能连接多个客户端
    server.handle_request()   #只能连接一个客户端,其余的客户端连接的话会被拒绝
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值