socket编程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了socket编程相关的知识,希望对你有一定的参考价值。

一.socket介绍

1.socket在tcp/ip五层结构中的位置

技术分享

  socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

2.类型

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

  套接字家族的名字:AF_UNIX

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

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

  套接字家族的名字:AF_INET

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

3.套接字工作流程

技术分享

二.基于TCP的套接字

1.以打电话为例实现套接字通信

 

技术分享
import socket

#买手机
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)       #tcp协议
#绑定手机卡
phone.bind((127.0.0.1,8080))
#开机
phone.listen(5)            #最大挂起的连接数
#等待连接
print(starting...)
conn,client_addr=phone.accept()       #(套接字链接,客户端的ip和port)
print(>>>>>>>)
#收消息
data=conn.recv(1024)            #1024最大的限制
print(客户端消息:,data)
#发消息
conn.send(data.upper())
#挂电话
conn.close()
#关机
phone.close()
服务端
技术分享
import socket

#买手机
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)       #tcp协议
#发起连接
phone.connect((127.0.0.1,8080))
#发消息
phone.send(hello world.encode(utf-8))
#收消息
data=phone.recv(1024)
print(data)
#关机
phone.close()
客户端

2.加上链接循环与通信循环

技术分享
import socket

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)       #tcp协议
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((127.0.0.1,8080))
phone.listen(5)            #最大挂起的连接数
while True:
    conn,client_addr=phone.accept()       #(套接字链接,客户端的ip和port)
    print(client_addr)
    while True: #通信循环
        try:
            data=conn.recv(1024)            #1024最大的限制
            print(客户端消息:,data)
            if not data:break   #针对Linux系统
            conn.send(data.upper())
        except ConnectionResetError:
            break
    conn.close()
phone.close()
服务端
技术分享
import socket

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)       #tcp协议
phone.connect((127.0.0.1,8080))
while True:
    msg=input(>>:).strip()
    if not msg: continue
    phone.send(msg.encode(utf-8))
    data=phone.recv(1024)
    print(data.decode(utf-8))

phone.close()
客户端

3.实现ssh远程执行命令

技术分享
import socket,subprocess

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)       #tcp协议
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((127.0.0.1,8080))
phone.listen(5)            #最大挂起的连接数
while True:
    conn,client_addr=phone.accept()       #(套接字链接,客户端的ip和port)
    print(client_addr)
    while True: #通信循环
        try:
            cmd=conn.recv(1024)            #1024最大的限制
            print(客户端消息:,cmd)
            if not cmd:break   #针对Linux系统
            obj = subprocess.Popen(cmd.decode(utf-8), shell=True,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            stdout_res=obj.stdout.read()
            stderr_res=obj.stderr.read()
            conn.send(stdout_res+stderr_res)
        except ConnectionResetError:
            break
    conn.close()
phone.close()
服务端
技术分享
import socket

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)       #tcp协议
phone.connect((127.0.0.1,8080))
while True:
    cmd=input(>>:).strip()
    if not cmd: continue
    phone.send(cmd.encode(utf-8))
    cmd_res=phone.recv(1024)
    print(cmd_res.decode(gbk))
phone.close()
客户端

三.粘包

技术分享

 

技术分享
import socket,subprocess,struct

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)       #tcp协议
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((127.0.0.1,8080))
phone.listen(5)            #最大挂起的连接数
while True:
    conn,client_addr=phone.accept()       #(套接字链接,客户端的ip和port)
    print(client_addr)
    while True: #通信循环
        try:
            cmd=conn.recv(1024)            #1024最大的限制
            print(客户端消息:,cmd)
            if not cmd:break   #针对Linux系统
            obj = subprocess.Popen(cmd.decode(utf-8), shell=True,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            stdout_res=obj.stdout.read()
            stderr_res=obj.stderr.read()
            #先发报头
            data_size=len(stdout_res)+len(stderr_res)
            conn.send(struct.pack(i,data_size))
            conn.send(stdout_res)
            conn.send(stderr_res)
        except ConnectionResetError:
            break
    conn.close()
phone.close()
服务端
技术分享
import socket,struct

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)       #tcp协议
phone.connect((127.0.0.1,8080))
while True:
    cmd=input(>>:).strip()
    if not cmd: continue
    phone.send(cmd.encode(utf-8))
    #先收报头
    head_strct=phone.recv(4)
    total_size=struct.unpack(i,head_strct)[0]
    cmd_res=b‘‘
    recv_size=0
    while recv_size<total_size:
        recv_data=phone.recv(1024)
        cmd_res+=recv_data
        recv_size+=len(recv_data)
    print(cmd_res.decode(gbk))
phone.close()
客户端

 

技术分享
import socket,subprocess,struct,json

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)       #tcp协议
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind((127.0.0.1,8080))
phone.listen(5)            #最大挂起的连接数
while True:
    conn,client_addr=phone.accept()       #(套接字链接,客户端的ip和port)
    print(client_addr)
    while True: #通信循环
        try:
            cmd=conn.recv(1024)            #1024最大的限制
            print(客户端消息:,cmd)
            if not cmd:break   #针对Linux系统
            obj = subprocess.Popen(cmd.decode(utf-8), shell=True,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            stdout_res=obj.stdout.read()
            stderr_res=obj.stderr.read()
            #制作报头
            head_dic={
                filename:a.txt,
                total_size:len(stdout_res)+len(stderr_res),
                md5:fiwehfoaejrfanf
            }
            head_json=json.dumps(head_dic).encode(utf-8)
            #先发报头长度
            conn.send(struct.pack(i,len(head_json)))
            #再发报头
            conn.send(head_json)
            #再发数据
            conn.send(stdout_res)
            conn.send(stderr_res)
        except ConnectionResetError:
            break
    conn.close()
phone.close()
服务端
技术分享
import socket,struct,json

phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)       #tcp协议
phone.connect((127.0.0.1,8080))
while True:
    cmd=input(>>:).strip()
    if not cmd: continue
    phone.send(cmd.encode(utf-8))
    #先收报头长度
    struct_res=phone.recv(4)
    head_size=struct.unpack(i,struct_res)[0]
    #先收报头
    head_json=phone.recv(head_size).decode(utf-8)
    head_dic=json.loads(head_json)

    cmd_res=b‘‘
    recv_size=0
    total_size=head_dic[total_size]
    while recv_size<total_size:
        recv_data=phone.recv(1024)
        cmd_res+=recv_data
        recv_size+=len(recv_data)
    print(cmd_res.decode(gbk))
phone.close()
客户端

 

以上是关于socket编程的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段——JS中的面向对象编程

VSCode自定义代码片段9——JS中的面向对象编程

使用 Pygments 检测代码片段的编程语言

面向面试编程代码片段之GC

如何在 Django Summernote 中显示编程片段的代码块?

以编程方式将按钮添加到片段