zoukankan      html  css  js  c++  java
  • python-40-初识socket与struct

    前言

    网络中进程间如何通信?我怎么找到某个电脑上的某个程序进行通信呢?那么利用三元组【ip地址,协议,端口】可以进行网络间通信。

    因此,Python中的socket模块便可以使其进行通信!但是通信过程中会出现黏包,Python中可以使用struct模块进行解决。

    一、socket 模块

    tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端。

    两个py文件之间进行通信实例:

    ①基于TCP协议的socket

    server:服务端

    import socket
    sk=socket.socket()
    sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    sk.bind(('12.0.0.1',8080)) # 绑定服务端的:IP+端口
    sk.listen()                       # 监听连接
    conn, addr = sk.accept()          # 接收连接 三次握手conn
    lis=list(addr)
    print('IP:%s 端口:%s 已请求连接!'%(lis[0],lis[1]))
    while 1:
        res=conn.recv(1024).decode('utf-8')        # 接收信息
        print(res)
        if res=='886':break
        ret=input('美女>>>')
        if ret=='886':
            conn.send(bytes(ret.encode('utf-8')))  # 发送信息
        conn.send(bytes(ret.encode('utf-8')))      # 发送信息
    conn.close()                                     # 关闭客户端套接字
    sk.close()                                       #关闭服务器套接字

    ②client:客户端

    import socket
    sk=socket.socket()                         # 创建客户套接字
    sk.connect(('127.0.0.1',8080))       # 尝试连接服务端
    while 1:
        ret=input('帅哥>>>')
        if ret=='886':
            sk.send(bytes(ret.encode('utf-8')))
            break
        sk.send(bytes(ret.encode('utf-8')))     # 发送信息
        msg=sk.recv(1024).decode('utf-8')       # 接收信息
        print(msg)
        if msg=='886':break
    sk.close()                                   # 关闭客户套接字

    2、基于UDP协议的socket

    udp是无链接的,启动服务之后可以直接接受消息,不需要提前建立链接。

    ①server:服务端

    # 2、基于UDP协议的socket
    # udp是无链接的,启动服务之后可以直接接受消息,不需要提前建立链接
    import socket
    udp_sk = socket.socket(type=socket.SOCK_DGRAM)   # 创建一个服务器的套接字
    udp_sk.bind(('127.0.0.1',8080))                  # 绑定服务器套接字
    msg,addr = udp_sk.recvfrom(1024)
    print(msg)
    udp_sk.sendto(b'udp_server',addr)                # 对话(接收与发送)
    udp_sk.close()                                   # 关闭服务器套接

    ②client:客户端

    import socket
    ip_port=('127.0.0.1',8080)
    udp_sk=socket.socket(type=socket.SOCK_DGRAM)
    udp_sk.sendto(b'udp_client',ip_port)
    back_msg,addr=udp_sk.recvfrom(1024)
    print(back_msg.decode('utf-8'),addr)

    3、长链接

    ①长链接:因同一时间只能一个程序链接,所以多个只会连接一个。

    # 3、长链接
    # 因同一时间只能一个程序链接,所以多个只会连接一个
    import socket
    sk=socket.socket()
    sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    sk.bind(('192.168.1.124',8080)) # 绑定服务端的:IP+端口
    sk.listen()                       # 监听连接
    while 1:
        conn, addr = sk.accept()  # 接收连接 三次握手conn
        lis = list(addr)
        print('IP:%s 端口:%s 已请求连接!' % (lis[0], lis[1]))
        while 1:
            res = conn.recv(1024).decode('utf-8')  # 接收信息
            print(res)
            if res=='886':break
            ret=input('美女>>>')
            if ret=='886':
                conn.send(bytes(ret.encode('utf-8')))  # 发送信息
            conn.send(bytes(ret.encode('utf-8')))      # 发送信息
        conn.close()                                     # 关闭客户端套接字

    二、struct 模块

    基本思路:

    • 客户端传输的内容,len长度
    • 将长度经过struct成为4位字节码
    • 服务端解4位字节码,就知道了文件的大小
    • 便开始传输

    1、远程Windows cmd命令实例:

    ①server:服务端

    import socket,struct
    sk=socket.socket()
    sk.bind(('127.0.0.1',8888))
    sk.listen()
    conn,addr=sk.accept()
    while 1:
        cmd=input('请输入命令:')
        if cmd=='q':
            conn.send(b'q')
            break
        conn.send(cmd.encode('gbk'))     # win系统gbk编码
        num=conn.recv(4)
        num=struct.unpack('i',num)[0]    # 将4个字节解码转为原来的大小
        print(num)
        res=conn.recv(int(num)).decode('gbk')
        print(res)
    conn.close()
    sk.close()

    ②client:客户端

    import socket,subprocess,struct
    sk=socket.socket()
    sk.connect(('127.0.0.1',8888))
    
    while 1:
        cmd=sk.recv(1024).decode('gbk')
        if cmd=='q':
            break
        res=subprocess.Popen(cmd,shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        std_out=res.stdout.read()
        std_err=res.stderr.read()
        len_num=len(std_out)+len(std_err)   # 长度
        num_by=struct.pack('i',len_num)     # struct处理后变为4个字节
        sk.send(num_by)                      # 先发送处理后的长度,让对方解字节
        sk.send(std_out)
        sk.send(std_err)
    sk.close()

    欢迎来大家QQ交流群一起学习:482713805

  • 相关阅读:
    分页查询SQL语句
    屏蔽Ctrl+C
    RichtextBox 控件小节
    必须掌握的八个CMD命令
    [唠叨两句]一个关于OpenFileDialog 影响 相对路径的问题
    反序列化出现异常:SerializationException 在分析完成之前就遇到流结尾
    Static块(静态代码块)
    Java ServletContext 详解
    tomcat中conf\Catalina\localhost目录下的J2EE项目METAINF配置文件
    关于【apache tomcat 5.5.15/conf /Catalina/localhost配置虚拟目录】时的一些问题。(配置web项目的方式不止一种,虚拟目录就是一个)
  • 原文地址:https://www.cnblogs.com/gsxl/p/12547241.html
Copyright © 2011-2022 走看看