zoukankan      html  css  js  c++  java
  • socket套接字的学习与简单应用

    1566819497322

    1566819468118

    socket套接字

    Socket又称为套接字,它是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口提高了效率
    socket就是一个模块。我们通过调用模块中已经实现的方法建立两个进程之间的连接和通信。也
    为什么存在socket抽象层?
    如果直接与操作系统数据交互非常麻烦,繁琐,socket对这些繁琐的的操作高度的封装,简化.	
    socket在python中就是一个模块.
    

    基于文件类型的套接字家族

    套接字家族的名字:AF_UNIX

    unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信

    基于网络类型的套接字家族

    套接字家族的名字:AF_INET

    (还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)

    tcp链接+循环 通信 服务端常驻

    img

    server端

    import socket
    phone=socket.socket()#买手机
    phone.bind(('127.0.0.1',6666))#绑卡
    phone.listen(5)#设置连接数一个连接加5个等待 缓存池
    while 1:
        conn,addr=phone.accept()
        print(f'用户{addr}来了')
        while 1:
            try:
                from_client_data=conn.recv(1024)
                if from_client_data.decode('utf-8')=='Q':
                    print('正常断开')
                    break
                print(f'来自客户端{addr}消息{from_client_data.decode("utf-8")}')
                to_client_data=input('>>>>>>>')
                conn.send(to_client_data.encode('utf-8'))
            except Exception:
                break
        conn.close()
    phone.close()
    

    client端

    # 自己的
    import socket
    phone=socket.socket()
    phone.connect(('127.0.0.1',6666))
    while 1:
        to_server_data=input('>>>>>>q退出')
        if not to_server_data:
            print('不可以输入空')
            continue
        phone.send(to_server_data.encode('utf-8'))#因为不可以让他发空 所以放在判断下
        if to_server_data.upper()=='Q':
            break
        from_server_data=phone.recv(1024)
        print(f'来自客户端消息{from_server_data.decode("utf-8")}')
    phone.close()
    

    tcp执行远端命令

    server端

    # 用到的模块
    import subprocess
    # import subprocess
    # obj = subprocess.Popen('系统命令',
    #                        shell=True,
    #                        stdout=subprocess.PIPE,
    #                        stderr=subprocess.PIPE,
    #                        )
    # print(obj.stdout.read().decode('gbk'))  # 正确命令
    # print(obj.stderr.read().decode('gbk'))  # 错误命令
    # 错误的是空字符串
    
    import socket
    import subprocess
    phone = socket.socket()
    
    phone.bind(('127.0.0.1',8848))
    
    phone.listen(2)
    while 1:
        conn,addr = phone.accept()  # 等待客户端链接我,阻塞状态中
        print(f'链接来了: {conn,addr}')
        while 1:
            try:
                from_client_data = conn.recv(1024)  # 最多接受1024字节
                if from_client_data.upper() == b'Q':
                    print('客户端正常退出聊天了')
                    break
                obj = subprocess.Popen(from_client_data.decode('utf-8'),
                                       shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       )
                result = obj.stdout.read() + obj.stderr.read()
    
                conn.send(result)
            except ConnectionResetError:
                print('客户端链接中断了')
                break
        conn.close()
    phone.close()
    

    client端

    # 用到的模块
    import subprocess
    # import subprocess
    # obj = subprocess.Popen('系统命令',
    #                        shell=True,
    #                        stdout=subprocess.PIPE,
    #                        stderr=subprocess.PIPE,
    #                        )
    # print(obj.stdout.read().decode('gbk'))  # 正确命令
    # print(obj.stderr.read().decode('gbk'))  # 错误命令
    # 错误的是空字符串
    
    import socket
    import subprocess
    phone = socket.socket()
    
    phone.bind(('127.0.0.1',8848))
    
    phone.listen(2)
    while 1:
        conn,addr = phone.accept()  # 等待客户端链接我,阻塞状态中
        print(f'链接来了: {conn,addr}')
        while 1:
            try:
                from_client_data = conn.recv(1024)  # 最多接受1024字节
                if from_client_data.upper() == b'Q':
                    print('客户端正常退出聊天了')
                    break
                obj = subprocess.Popen(from_client_data.decode('utf-8'),
                                       shell=True,
                                       stdout=subprocess.PIPE,
                                       stderr=subprocess.PIPE,
                                       )
                result = obj.stdout.read() + obj.stderr.read()
    
                conn.send(result)
            except ConnectionResetError:
                print('客户端链接中断了')
                break
        conn.close()
    phone.close()
    

    利用udp建立通讯

    udp是无链接的,先启动哪一端都不会报错

    img

    server端

    import socket
    
    udp_server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  # 基于网络,udp协议的socket
    
    udp_server.bind(('127.0.0.1', 9000))#绑卡
    
    while 1:
        from_client_data = udp_server.recvfrom(1024)#接收 前面消息 后面是ip端口
        print(f'来自{from_client_data[1]}的消息:{from_client_data[0].decode("utf-8")}')
        to_client_data = input('>>>').strip()
        udp_server.sendto(to_client_data.encode('utf-8'),from_client_data[1])
    

    client端

    import socket
    
    udp_client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  # 基于网络,udp协议的socket
    
    while 1:
        to_server_data = input('>>>').strip()
        udp_client.sendto(to_server_data.encode('utf-8'),('127.0.0.1', 9000))
        from_server_data = udp_client.recvfrom(1024)#发送端 端口不知道
        print(f'来自{from_server_data[1]}的消息:{from_server_data[0].decode("utf-8")}')
    

    tcp实现文件上传 客户端-->服务端

    server端

    # 1. 接收固定长度的4个字节 2. 利用struct反解 3. 接收bytes类型的报头 4. 将bytes类型的报头转化成json
    # 5. 将json类型报头转化成字典形式的报头有一个MD5校验# 6. 接收原始数据
    #在文件读取时同时进行md5效验 一举两得
    import socket
    import struct
    import json
    import os
    import hashlib
    MY_FILE = os.path.join(os.path.dirname(__file__),'my_file')#拼接出来的要存入的总路径
    
    def socket_server(MY_FILE):
        server = socket.socket()
        server.bind(('127.0.0.1',8848))
        server.listen(5)
        conn, addr = server.accept()
        four_bytes = conn.recv(4)#1 接收固定长度的4个字节
        head_len = struct.unpack('i',four_bytes)[0]#2  利用struct反解
        head_dic_json_bytes = conn.recv(head_len)#3接收bytes类型的报头
        head_dic_json = head_dic_json_bytes.decode('utf-8')#4 将bytes类型的报头转化成json
        head_dic = json.loads(head_dic_json)#5将json类型报头转化成字典形式的报头
        with open(os.path.join(MY_FILE,head_dic['new_file_name']),mode='wb') as f1:#6接收原始数据
    
            total_size = 0
            ret = hashlib.md5()
            while total_size < head_dic['file_size']:
                every_data = conn.recv(1024)
                f1.write(every_data)
                total_size += len(every_data)
                ret.update(every_data)
            if ret.hexdigest()==head_dic['MD5']:
                print('md5效验成功')
            else:
                print('md5效验失败')
                os.remove(os.path.join(MY_FILE,head_dic['new_file_name']))
        conn.close()
        server.close()
    socket_server(MY_FILE)
    

    client端

    # 1.制作字典形式的报头2. 获取json形式的报头 3. 获取bytes形式的报头4. 获取bytes报头的总字节数 5. 将bytes报头的总字节数转化成固定4个字节#
    # 6. 发送固定的4个字节 7.发送报头 8. 发送总数据
    # 循环条件设定:1. 根据总子节数: file_size: 493701, 每次循环1024个,2. 每次取数据不为空,即可.
    import socket
    import os
    import json
    import struct
    import hashlib
    FILE_PATH = os.path.join(os.path.dirname(__file__), 'demo.mp4')#拼接出来的总路径
    def md5_file(path):
        ret = hashlib.md5()
        with open(path,mode='rb') as f1:
            while 1:
                content = f1.read(1024)
                if content:
                    ret.update(content)
                else:
                    return ret.hexdigest()
    def socket_client(path,md5,name):
        client = socket.socket()
        client.connect(('127.0.0.1',8848))
        head_dic = {#1.制作字典形式的报头
            'MD5': md5,
            'file_name':path,#路径
            'file_size': os.path.getsize(FILE_PATH),#利用文件路径判断文件大小
            'new_file_name': name,#文件名
        }
        head_dic_json = json.dumps(head_dic)#2. 获取json形式的报头
        head_dic_json_bytes = head_dic_json.encode('utf-8')#3. 获取bytes形式的报头
        head_len = len(head_dic_json_bytes)#4. 获取bytes报头的总字节数
        four_bytes = struct.pack('i',head_len)#5. 将bytes报头的总字节数转化成固定4个字节
        client.send(four_bytes)#6. 发送固定的4个字节
        client.send(head_dic_json_bytes)#7.发送报头
        with open(FILE_PATH,mode='rb') as f1:# 8. 发送总数据
            while 1:
                every_data = f1.read(1024)
                if every_data:
                    client.send(every_data)
                else:
                    break
        client.close()
    socket_client(FILE_PATH,md5_file(FILE_PATH),'demo1.mp4')
    

    tcp实现文件下载 服务端-->客户端

    qq聊天的代码

    server

    
    

    基于UDP协议的socket通信

    server

    import socket
    server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    # 基于网络的UDP协议的socket
    server.bind(('192.168.14.198',9000))
    
    while 1:
    
        from_client_data = server.recvfrom(1024)  # 阻塞,等待客户来消息
        print(f'33[1;35;0m来自客户端{from_client_data[1]}: {from_client_data[0].decode("utf-8")} 33[0m')
        # to_client_data = input('>>>').strip()
        # server.sendto(to_client_data.encode('utf-8'),from_client_data[1])
    
    
    # 1. 基于udp协议的socket无须建立管道,先开启服务端或者客户端都行.
    # 2. 基于udp协议的socket接收一个消息,与发送一个消息都是无连接的.
    # 3. 只要拿到我的ip地址和端口就都可以给我发消息,我按照顺序接收消息.
    

    client端

    import socket
    client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    # 基于网络的UDP协议的socket
    
    while 1:
    
        to_server_data = input('>>>:').strip()
        client.sendto(to_server_data.encode('utf-8'),('127.0.0.1',9000))
        # data,addr = client.recvfrom(1024)
        # print(f'来自服务端{addr}消息:{data.decode("utf-8")}')
    

    摘抄题

    1.简述socket套接字
    2,执行远端命令用到的模块
    3.文件上传下载
    
  • 相关阅读:
    1.1 java变量及数据类型
    3. 软件测试的类型
    2.3 软件测试模型之 敏捷测试
    2.2 软件测试的手段
    2.1 软件测试的阶段
    1.1 软件测试基础概念
    浅谈内联元素inline
    微信内置浏览器清除缓存的方法
    我的package.json清单
    我的gulp.js清单
  • 原文地址:https://www.cnblogs.com/saoqiang/p/12388417.html
Copyright © 2011-2022 走看看