python编程学习之socket编程

无人久伴 提交于 2020-02-29 08:51:56

讲解

C/S架构

客户机和服务器结构

Server唯一的目的就是等待client的请求,client连上server发送必要的数据,然后等待server端完成请求的范阔

C/S网络编程

Server端进行设置,首先创建一个通信端点,让server端能够监听请求,之后就进入等待和处理Client请求的无限循环中

Client编程相对Server端编程简单,只要创建一个通信端点,建立到服务器的连接,就可以提出wing我就来

套接字(socket)

是一种具有之前所说的“通信端点”概念的计算机网络数据结构。网络化的应用程序在开始任何通讯之前都必须创建套接字

套接字 = (ip, 端口)

Python支持:

- AF_UNIX –> Unix下进行通信的

- AF_NETLINK –> 是Linux下的套接字

- AF_INET –> 是基于网络的套接字 (我们下面的重点)

Python的socket模块创建TCP/IP套接字,方法如下:

1234
# 参数(套接字家族,套接字类型)# AF_INET:基于网络的, SOCK_SREAM:代表TCP/IPtcp_scoket = socket(socket.AF_INET, socket.SOCK_SREAM)

套接字对象的方法:

服务端套接字函数:

公共用途套接字函数:

创建连接之后要关闭

实例:

反弹Shell:

在客户端获取服务端的shell

1.获取Linux的shell:

server.py

1234567891011121314151617181920212223242526272829303132333435
"""反弹shell"""import socketfrom subprocess import Popen,PIPE     # 执行系统命令HOST = ''   # 如果是本机最为服务端,地址可以不用填写PORT = 8888BUFSIZE = 1024ADDR = (HOST,PORT)tcp_server = socket.socket()   # type默认是tcptcp_server.bind(ADDR)tcp_server.listen(5)print("开始监听")while True:    # 服务端和客户端的循环连接    print("Waiting fpr connecting...")    coon, addr = tcp_server.accept()  # 获取对等套接字(conn), 以及客户端地址(addr). 这个【只执行一次】,放到外面防止阻塞    print("... connected from:" + str(addr))    # 下面是通信的循环    while True:        data = coon.recv(BUFSIZE)          # 读取客户端发送的消息 (指明一次性能接收的最大字节数量)        if data:            try:                # 执行获取服务端的系统命令(在客户端连接后可以执行服务端的命令)                cmd = Popen(['/bin/zsh', '-c', data], stdin=PIPE, stdout=PIPE)                cmd_data = cmd.stdout.read()                coon.send(cmd_data)            except Exception:                continue        else:            print("客户端{}已断开".format(addr))            break

2.获取Window的shell:

12

client.py不变

1234567891011121314151617181920212223242526
import socketHOST = ''   # 如果是本机最为服务端,地址可以不用填写PORT = 8888BUFSIZE = 1024ADDR = (HOST,PORT)tcp_cient = socket.socket()tcp_cient.connect(ADDR)print("客户端:\n")# 数据交互循环while True:    msg = input('>>>')    if msg:        tcp_cient.send(msg.encode())   # 只能发送 bytes 类型的数据        data = tcp_cient.recv(BUFSIZE)        if not data:            break        print(data.decode())    else:        break# tcp_cient.close()# c.close()    # 主动断开   # 服务端会recv到一个空字符串

1.阻塞的套接字

阻塞套接字不能和多个客户端进行通信

server.py

1234567891011121314151617181920212223242526272829303132333435
"""服务端:阻塞套接字:  --->  阻塞套接字不能和多个客户端进行通信"""import socketHOST = ''   # 如果是本机最为服务端,地址可以不用填写PORT = 8888BUFSIZE = 1024ADDR = (HOST,PORT)tcp_server = socket.socket()   # type默认是tcp#tcp_server.bind(('',8888))     tcp_server.bind(ADDR)    tcp_server.listen(5)           # 可以挂起的最大连接数    accept就不算挂起print("开始监听")while True:    # 服务端和客户端的循环连接    print("Waiting fpr connecting...")    coon, addr = tcp_server.accept()  # 获取对等套接字(conn), 以及客户端地址(addr). 这个【只执行一次】,放到外面防止阻塞    print("... connected from:" + str(addr))    # 下面是通信的循环    while True:        data = coon.recv(BUFSIZE)          # 读取客户端发送的消息 (指明一次性能接收的最大字节数量)        if data:            print(data.decode())            # 向client发送收到的信息            coon.send(data)        else:            print("客户端{}已断开".format(addr))            break             #server端关闭连接#tcp_server.close()#accpet 阻塞   recv阻塞(读不到数据,就一直等到有数据为止)

client.py

12345678910111213141516171819202122232425262728293031
"""最简单的客户端三种方式的客户端都是一样的"""import socketHOST = ''   # 如果是本机最为服务端,地址可以不用填写PORT = 8888BUFSIZE = 1024ADDR = (HOST,PORT)tcp_cient = socket.socket()tcp_cient.connect(ADDR)print("客户端:\n")# 数据交互循环while True:    msg = input('>>>')    if msg:        tcp_cient.send(msg.encode())   # 只能发送 bytes 类型的数据        data = tcp_cient.recv(BUFSIZE)        if not data:            break        print(data.decode())    else:        break# tcp_cient.close()# c.close()    # 主动断开   # 服务端会recv到一个空字符串

2.I/O多路复用的套接字

server.py

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
"""服务端I/O多路复用"""# IO多路复用# epoll  事件通知事件# IO事件  计算机  可读事件(有数据了...)# 通知机制       (某一事情发送之后,可读之后)  轮询# epoll: 当socket变为可读的时候,发出通知# epoll: 是惰性的事件回调:    操作系统只起到通知的作用。# epoll: 目前Linux上效率最高的IO多路复用 技术 !# 1.监听套接字  2.对等套接字import socketimport selectors# windows没有epollsel = selectors.DefaultSelector()   # 会根据不同的操作系统选择相应的解释器   在linux是epoll   根据系统自动选择sel2 = selectors.EpollSelector()   # 会根据不同的操作系统选择相应的解释器   在linux是epoll     Linuxserver = socket.socket()server.bind(('127.0.0.1',8888))server.listen(5)def accept(server):    coon, addr = server.accept()    sel.register(coon, selectors.EVENT_READ, read)def read(coon):    data = coon.recv(1024)    if data:        print(data)        server.send(data.encode())    else:        print('Closing:',coon)        sel.unregister(coon)   # 取消监听        coon.close()# 注册事件  事件触发直接调用sel.register(server, selectors.EVENT_READ, accept)   # 监听事件的发生  参数三个: 套接字,可能发送的事件(变为可读事件),回调函数print("开始监听")while True:    events_list = sel.select()   # 返回发生了事件的列表  查询已经准备好的套接字    print("有套接字发生变化")    for key, _ in events_list:  # 列表里面是个元组, key是元组里面的第一个值        callback = key.data   # 某个套接字绑定的函数  key.data是函数        callback(key.fileobj)   # 调用这个回调函数     fileobj是对应套接字# sel.select()     有两种情况:#1.  客户端请求连接 key.data是accept  key.fileobj 是server#2.  客户端请求连接 key.data是read  key.fileobj 是conn"""1.先在指定的套接字上注册对应的事件及回调2.不断的查询所有已经准备好资源的套接字3.不需要考虑套接字与事件只管调用"""

client.py 相同

3.非阻塞的套接字

server.py

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
"""服务端非阻塞套接字"""import sockets = socket.socket()           # type默认是tcps.bind(('127.0.0.1', 8888))# 这个必须在操作之前设置s.setblocking(False)   # 变为非阻塞套接字, 立刻返回异常s.listen(5)client_list = []while True:        # 第一层循环只负责生成对等套接字    try:        coon, addr = s.accept()     # 多个coon才能与多个客户端进行通信    except BlockingIOError as e:        pass    else:        print("客户端{}连接成功".format(addr))        coon.setblocking(False)  # 设置为非阻塞        client_list.append(coon)   # 保留已生成的对等套接字        # print(coon, addr)    for client_socket in client_list:   # 第二层循环 把所有已保留的套接字都执行一遍        try:            data = client_socket.recv(1024)        except BlockingIOError:            pass        else:            if data:                print('{}:{}'.format(client_socket, data.decode()))                client_socket.send(data)            else:                print('{}'.format(client_socket))                client_socket.close()                client_list.remove(client_socket)    # 成功处理完一个,就移除一个## 实现方法:非阻塞+轮询# connect操作一定会引发BlockingIOError异常# 如果连接没有建立,那么send操作引发OSError异常"""accept 阻塞:在没有新的套接字来之前,不能处理已经建立连接的套接字的请求recv 阻塞:在没有接受到客户端请求数据之前,不能与其他客户端建立连接"""

client.py 相同


成为大师
1234567891011121314
"""1. 多练习,一定要善于发现感兴趣的内容,通过所学知识去实现2. 关注相关领域:	寻找大师,跟随大市,与大师同行,洞察大师,成为大师	知乎,ve2x.com, github3.扩展:	想要提高,就不能守着自己现有的东西而不去学习新的4.应用:	根据自己的需求,动手实践,达到目标	安全:	分析行为:通过日志,分析攻击行为(re)"""
 
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!