zoukankan      html  css  js  c++  java
  • 套接字进阶(python3入门)

    一、基于TCP的socket简单通信

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    
    import socket
    
    
    # 1、买手机 --- 定义socket的方法
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    #TCP协议就是流式协议
    
    
    
    # 2、插手机卡 --- 绑定IP和端口
    server.bind(('127.0.0.1',8080))
    
    
    # 3、开机(监听) --- 半连接池设定
    server.listen(5)
    
    
    # 4、等待电话拨入 --- 一直保持阻塞的状态,直到有客户端连入,才会让代码运行继续下去
    conn,addr=server.accept()
    # print(conn)
    # print(addr)
    
    
    
    # 5、接受客户端传来的数据
    rec_data = conn.recv(1024)
    print('接收来自客户端的数据:',rec_data)
    
    
    # 6、回复客户端信息
    rep_data = conn.send(rec_data.upper())
    
    
    
    # 7、服务端关闭连接
    conn.close()
    server
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import socket
    
    # 1、买手机
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    
    # 2、拨号码给服务端 --- 连接服务器的ip和指定端口(建立连接)
    client.connect(('127.0.0.1',8080))
    
    
    # 3、发送数据
    sen_data = client.send(b'hello')
    
    
    
    # 4、接收服务端的回应
    rec_data = client.recv(1024)
    print('接收来自服务端的回复:',rec_data)
    
    
    
    # 5、关闭此次通话 --- 关闭本次连接通道
    client.close()
    client

    二、基于TCP的socket简单通信升级版本(通信循环+连接循环)

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    
    import socket
    
    
    # 1、买手机 --- 定义socket的方法
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)    #TCP协议就是流式协议
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)    #为了防止端口被占用,在调试阶段可以反复 复用同一端口
    
    
    
    
    # 2、插手机卡 --- 绑定IP和端口
    server.bind(('127.0.0.1',8080))
    
    
    # 3、开机(监听) --- 半连接池设定
    server.listen(5)
    
    
    
    while True:
    
        # 4、等待电话拨入 --- 一直保持阻塞的状态,直到有客户端连入,才会让代码运行继续下去
        conn,addr=server.accept()
        print('本次连接对对象为:',conn)
        print('本次连接的客户端信息为:',addr)
    
    
        while True:
    
            try:
                print('ssss')
    
                # 5、接受客户端传来的数据
                rec_data = conn.recv(1024)
                if len(rec_data) == 0:break
                print('接收来自客户端的数据:',rec_data)
    
    
                # 6、回复客户端信息
                rep_data = conn.send(rec_data.upper())
    
            except Exception as e:
                break
    
    
    
    
        # 7、服务端关闭连接
        conn.close()
    server
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import socket
    
    # 1、买手机
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    
    # 2、拨号码给服务端 --- 连接服务器的ip和指定端口(建立连接)
    client.connect(('127.0.0.1',8080))
    
    
    while True:
    
        msg = input('>>>>:').strip()
        if len(msg) == 0:continue
    
        # 3、发送数据
        sen_data = client.send(bytes(msg,encoding='utf-8'))
    
        # 4、接收服务端的回应
        rec_data = client.recv(1024)
        print('接收来自服务端的回复:',rec_data)
    
    
    
    # 5、关闭此次通话 --- 关闭本次连接通道
    client.close()
    client

    三、服务端subprocess处理结果返回客户端

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    
    import socket
    import subprocess
    
    
    #买手机
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)    #为了防止端口被占用,在调试阶段可以反复 复用同一端口
    
    #sim卡
    server.bind(('127.0.0.1',8080))
    
    #开机设定半连接池
    server.listen(5)
    
    while True:
    
        #等待电话拨入
        conn,addr = server.accept()
    
        while True:
            #接收客户端发来的数据
            rdata = conn.recv(1024)
            if len(rdata) == 0:break
    
            obj = subprocess.Popen(rdata.decode('utf-8'),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
    
            stdout = obj.stdout.read()
            stderror = obj.stderr.read()
            print(stdout.decode('utf-8'))
            print(stderror.decode('utf-8'))
    
            total_data = stdout+stderror
    
            # print('收到来自客户端发来的消息:',rdata.decode('utf-8'))
    
            #返回数据给客户端
            sdata = conn.send(total_data)
    
        conn.close()
    server
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import socket
    
    #买手机
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    
    #与服务端建立连接
    client.connect(('127.0.0.1',8080))
    
    
    
    
    while True:
    
        msg = input('>>>>:').strip()
        if len(msg) == 0:continue
    
        #发送消息到服务端
        client.send(bytes(msg,encoding='utf-8'))
    
    
        #接收服务端的数据
        rdata = client.recv(1024)
        print('收到来自服务端的回复:')
        print(rdata.decode('utf-8'))
    
    
    client.close()
    client

    四、处理粘包问题

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    '''
    1.什么是粘包
        数据报一个个连续不间断的发回客户端,产生的一种现象。
    
    
    2.为什么会有粘包
        所谓粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的(这是流式协议的锅)
    
    
    3.如何处理粘包
        使用两个变量,一个是接收的total_data,一个是服务端执行结果的长度
        这样客户端就可以通过服务端传回的结果长度,来判断何时可以完成数据接收
        简单来说: 先将执行结果的长度 打包成固定的一个长度的包
                 然后将这个定长的包优先发发送到客户端
                 最后将执行结果推送至客户端
    '''
    
    
    import socket
    import subprocess
    import struct
    
    
    #买手机
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)    #为了防止端口被占用,在调试阶段可以反复 复用同一端口
    
    #sim卡
    server.bind(('127.0.0.1',8080))
    
    #开机设定半连接池
    server.listen(5)
    
    while True:
    
        #等待电话拨入
        conn,addr = server.accept()
    
        while True:
            #接收客户端发来的数据
            rdata = conn.recv(1024)
            if len(rdata) == 0:break
    
            obj = subprocess.Popen(rdata.decode('utf-8'),
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
    
            stdout = obj.stdout.read()
            stderror = obj.stderr.read()
            print(stdout.decode('utf-8'))
            print(stderror.decode('utf-8'))
    
            #将stdout+stderr的长度进行打包
            total_size = len(stdout) + len(stderror)
            total_size = struct.pack('i',total_size)
    
            conn.send(total_size)
    
            total_data = stdout+stderror
    
            # print('收到来自客户端发来的消息:',rdata.decode('utf-8'))
    
            #返回数据给客户端
            sdata = conn.send(total_data)
    
        conn.close()
    server
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import socket
    import struct
    
    #买手机
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    
    #与服务端建立连接
    client.connect(('127.0.0.1',8080))
    
    
    
    
    while True:
    
        msg = input('>>>>:').strip()
        if len(msg) == 0:continue
    
        #发送消息到服务端
        client.send(bytes(msg,encoding='utf-8'))
    
        #优先接收服务端处理结果的长度信息
        total_size = client.recv(4)
        total_size = struct.unpack('i',total_size)[0]
        # print(total_size)
    
        rdata = b''
        rsize = 0
        while rsize < total_size:
            data = client.recv(1024)
            rdata += data
            rsize += len(data)
    
        # #接收服务端的数据
        print('收到来自服务端的回复:')
        print(rdata.decode('utf-8'))
    
    
    client.close()
    client

    五、处理粘包问题终极版

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import socket
    import subprocess
    import json
    import struct
    
    
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)    #为了防止端口被占用,在调试阶段可以反复 复用同一端口
    
    server.bind(('127.0.0.1',8080))
    
    server.listen(5)
    
    
    while True:
        conn,addr = server.accept()
    
        while True:
    
            try:
                rdata = conn.recv(1024)
                if len(rdata) == 0:break
    
                print('来自客户端的消息:')
                print(rdata.decode('utf-8'))
    
                obj = subprocess.Popen(
                    rdata.decode('utf-8'),
                    shell=True,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE
                )
                stdout = obj.stdout.read()
                stderror = obj.stderr.read()
                # print(stdout,stdout.decode('utf-8'))
    
                total_size = len(stdout) + len(stderror)
                # total_size = struct.pack('i',total_size)
    
                header_dic = {
                    'file_name':'test',
                    'total_size':total_size,
                    'hash':'aaabbbcccddd'
                }
                header_str = json.dumps(header_dic)
                header_bytes = header_str.encode('utf-8')
                header_size = struct.pack('i',len(header_str))
    
                sdata = stdout + stderror
                # print(sdata)
    
                conn.send(header_size)  # 先将字典序列化为字符串,计算字符串的长度,将该长度压缩成4个字节发送给客户端
                conn.send(header_bytes) # 然后将字典编码为bytes发送给客户端
                conn.send(sdata)    # 最终将执行结果发送给客户端
    
            except Exception as e:
                print(e)
                break
    
        conn.close()
    server
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import socket
    import json
    import struct
    
    
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    client.connect(('127.0.0.1',8080))
    
    
    while True:
        msg = input('>>>>:')
        if len(msg) == 0:continue
    
        client.send(bytes(msg,encoding='utf-8'))
    
        header_bytes = client.recv(4)   #仅接收服务端打包先发来的前4个字节的数据
        header_size = struct.unpack('i',header_bytes)[0]    #将该4个字节数据进行解压,或者字典序列化成字符串的长度
        # header_dic = json.loads(header_bytes)
    
        header_dic_bytes = client.recv(header_size) # 随即接收上述解压后的字节长度,该出长度中的数据为数据头字典数据
        header_dic_str = header_dic_bytes.decode('utf-8')   # 将该数据进行解码,得到json格式的字符串
        header_dic = json.loads(header_dic_str) # 将json格式的字符串反序列化为字典
        # print(header_dic,type(header_dic))
    
    
        rdata = b''
        rsize = 0
        while rsize < header_dic['total_size']:
            data = client.recv(1024)
            rdata += data
            rsize += len(data)
    
        # rdata = client.recv(1024)
        print('来自服务端的回应:')
        print(rdata.decode('utf-8'))
    
    client.close()
    client

    六、基于UDP协议的客户端与服务端简单通信

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    
    import socket
    
    
    server = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)    # udp数据报协议
    
    server.bind(('127.0.0.1',8080))
    
    while True:
        rdata,addr = server.recvfrom(1024)
    
        print(rdata.decode('utf-8'))
        print(addr)
    
        sdata = server.sendto(rdata.upper(),addr)
    
    server.close()
    server
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    
    import socket
    
    
    client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    
    while True:
        msg = input('>>>>>:')
        client.sendto(msg.encode('utf-8'),('127.0.0.1',8080))   #发送数据所使用的函数与tcp不同,请注意
    
        rdata,server_addr = client.recvfrom(1024)   #接收数据使用的函数与tcp不同,请注意!
        print(rdata.decode('utf-8'))
        print(server_addr)
    
    
    client.close()
    client

    七、socketserver实现简单并发编程

    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import socketserver
    
    class MyHandler(socketserver.BaseRequestHandler):
    
        def handle(self):
    
            while True:
                try:
                    rdata = self.request.recv(1024)
                    if len(rdata) == 0:break
    
                    self.request.send(rdata.upper())
    
    
                    print('从客户端接收到的数据:',rdata.decode('utf-8'))
                    print('客户端的地址为:',self.client_address)
    
                    # print(self.__dict__)
                except Exception as e:
                    print(e)
                    break
    
    
    
    if __name__ == '__main__':
    
        # 多开了一个线程,来服务客户端(线程:可以理解为多加了一个服务员)
        # socketserver.ThreadingTCPServer(server_address=,RequestHandlerClass=,bind_and_activate=)
        obj = socketserver.ThreadingTCPServer(('127.0.0.1',8080),MyHandler,bind_and_activate=True)
        
        # obj.allow_reuse_address = True
        obj.serve_forever()
    sock_server
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import socket
    
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    client.connect(('127.0.0.1',8080))
    
    
    while True:
        msg = input('>>>>:')
        if len(msg) == 0:continue
    
        client.send(bytes(msg,encoding='utf-8'))
    
        rdata = client.recv(1024)
        print(rdata.decode('utf-8'))
    
    
    client.close()
    client1
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import socket
    
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    client.connect(('127.0.0.1',8080))
    
    
    while True:
        msg = input('>>>>:')
        if len(msg) == 0:continue
    
        client.send(bytes(msg,encoding='utf-8'))
    
        rdata = client.recv(1024)
        print(rdata.decode('utf-8'))
    
    
    client.close()
    client2
    #! /usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import socket
    
    client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    
    client.connect(('127.0.0.1',8080))
    
    
    while True:
        msg = input('>>>>:')
        if len(msg) == 0:continue
    
        client.send(bytes(msg,encoding='utf-8'))
    
        rdata = client.recv(1024)
        print(rdata.decode('utf-8'))
    
    
    client.close()
    client3
  • 相关阅读:
    Mac保留Python2安装Python3(Anaconda3)
    Mybatis Plugin 以及Druid Filer 改写SQL
    Jackson替换fastjson
    Java单元测试 Http Server Mock框架选型
    应用中有多个Spring Property PlaceHolder导致@Value只能获取到默认值
    RabbitMQ Policy的使用
    Collectors.toMap不允许Null Value导致NPE
    php 删除标签
    php 替换标签
    jquery拼接html
  • 原文地址:https://www.cnblogs.com/lich1x/p/10150027.html
Copyright © 2011-2022 走看看