Python中Socket编程
目录
Python中Socket编程 1
一、Socket概述 1
二、python中socket模块使用 1
三、socket之聊天室 3
四、socket之端口探测 7
五、scapy之tcp端口探测 11
Python中Socket编程
一、Socket概述
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
socket即是一种特殊的文件,socket函数就是对其进行的操作(读/写IO、打开、关闭)
socket模块是针对 服务器端 和 客户端Socket 进行【打开】【读写】【关闭】
二、python中socket模块使用
通给指定地址簇和socket类型来进行创建
Socket地址簇 | 描述 |
---|---|
socket.AF_UNIX | 只能够用于单一的Unix系统进程间通信 |
socket.AF_INET | 服务器之间网络通信IPv4 |
socket.AF_INET6 | IPv6 |
socket类型 | 描述 |
socket.SOCK_STREAM | 流式socket , for TCP |
socket.SOCK_DGRAM | 数据报式socket , for UDP |
socket.SOCK_RAW | 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。 |
socket.SOCK_SEQPACKET | 可靠的连续数据包服务 |
创建TCP Socket: | s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) |
创建UDP Socket: | s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) |
Socket常用函数 | 描述 |
sk.bind(address) | 将socket绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。 |
sk.listen(backlog) | 开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。 |
sk.connect(address) | 连接到address处的socket。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。 |
sk.connect_ex(address) | 同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061 |
sk.close() | 关闭socket |
sk.recv(bufsize) | 接受socket的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。 |
sk.send(string) | 将string中的数据发送到连接的socket。 |
sk.sendall(string) | 将string中的数据发送到连接的socket,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。 |
sk.settimeout(timeout) | 设置socket操作的超时期,timeout是一个浮点数,单位是秒。超时期应该在刚创建socket时设置. |
sk.accept() | 接受连接并返回(conn,address),其中conn是新的socket对象,可以用来接收和发送数据。address是连接客户端的地址。 |
三、socket之聊天室
简单收发
编程思路
服务端:
1 创建socket,因为socket是特殊的文件(需要close),所以通过with
as来自动释放文件资源
with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as sk:
2 绑定套接字到本地IP与端口,开始监听连接
s.bind((HOST,PORT))
s.listen()
3接受客户端的连接请求,
conn, addr = s.accept()
4 通过accept创建的新socket对象接收数据并发送给对方数据
为了保证能收到所有发送来的信息,通过while循环来一直接受数据,直到数据为空
服务器端代码
import socketHOST = '127.0.0.1'
PORT = 33333with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s:s.bind((HOST,PORT))s.listen()conn, addr = s.accept()with conn:print('conn by',addr)while True:data = conn.recv(1024)if not data:breakprint(data)conn.sendall(b'hello,client')
客户端代码
import socketHOST = '127.0.0.1'
PORT = 33333with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s:s.connect((HOST,PORT))s.sendall(b'hello,friend')data = s.recv(1024)print('rece',repr(data))
socket聊天室
服务器
问题1:首先服务器能同时连接多个客户端
Socket.listen()后通过while循环
sk.accept()不断接收新的连接并创建socket
问题2:服务器要连接客户端后能一直接受数据,直到接受到空数据
多个连接之间肯定是独立的,并行的
所以通过线程的方式来实现
问题3:服务器要指定客户端端口和地址后进行回复信息
通过while 循环来一直接收input数据来指定发送
但是上面为了处理多个客户端时,也用了while
所以将连接多个客户端写入函数通过线程来实现,使之并行
服务器代码
from socket import *
import threadingdef text_recv(CliSock,addr):while True:data = CliSock.recv(1024)print(addr,"send to you:",data)if not data:breakdef socket_up():SerSock = socket(AF_INET, SOCK_STREAM)SerSock.bind(('127.0.0.1',58787))SerSock.listen()while True:CliSock, addr = SerSock.accept()print('connnecting from:', addr)Host[str(addr[1])] = CliSockt = threading.Thread(target=text_recv,args=(CliSock,addr))t.start()if __name__ == '__main__':Host = {}t = threading.Thread(target=socket_up)t.start()while True:try:target_info = input('please input your target : msg,port >\n ').split(',')msg = target_info[0]port = target_info[1]conn = Host[port]conn.sendall(msg.encode())except Exception as e:print(e)
客户端
同服务端问题3一致
客户端代码
import threading
from socket import *def text_recv(SerSock):while True:data = SerSock.recv(1024)print("send to you:",data)if not data:breakif __name__ == '__main__':CliSock = socket(AF_INET, SOCK_STREAM)CliSock.connect(('127.0.0.1',58787))t = threading.Thread(target=text_recv, args=(CliSock,))t.start()while True:data1 = input('please input want send > \n')CliSock.send(data1.encode())if not data1:break
四、socket之端口探测
探测原理:当通过socket连接目标主机未开放端口时会传出异常
例:ConnectionRefusedError: [WinError 10061]
由于目标计算机积极拒绝,无法连接。
编程思路
1 通过线程创建socket,对目标主机的范围端口进行尝试连接
2.对于没有抛出异常的端口尝试接受数据了解端口信息
问题:有些端口开放但不能接收到信息,就会将进程卡在接受数据那
解决:通过给socket对象设置settimeout()属性来限制超时时间,当超过时间时抛出新的异常:即timeout
所以 except timeout 也是存活端口,但是端口信息没有获取到
3.将存活端口和端口信息加入到字典中,最后遍历输出
实现代码
import threading
from socket import *def port_find(p):try:with socket(AF_INET, SOCK_STREAM) as sk:sk.connect((HOST, p))sk.settimeout(3)alive[p] = sk.recv(1024).strip().decode()print("port[{}] is alive\n".format(p), end='')except timeout:print("port[{}] is alive\n".format(p), end='')alive[p] = 'this not have info'except:passif __name__ == '__main__':HOST = '10.30.25.199'alive = {}threads = []for p in range(1, 65535):t = threading.Thread(target=port_find, args=(p,))threads.append(t)t.start()for t1 in threads:t1.join()for k,v in alive.items():print(k,'--->',v)
connect_ex探究使用
connect_ex相对于connect来说多了返回值,连接成功时返回 0
,连接失败时候返回编码,例如:10061
那么就可以通过返回值来对是否存活进行判断
但是还是需要接收那些没有数据的端口,所以设置settimeout,然后在进一步尝试执行,成功就记录收到的数据,失败就表示端口开放但是没有数据
实现代码
import threading
from socket import *def port_find(p):with socket(AF_INET, SOCK_STREAM) as sk:re = sk.connect_ex((HOST, p))sk.settimeout(3)if re == 0:print("port[{}] is alive\n".format(p), end='')try:alive[p] = sk.recv(1024).strip().decode()except:alive[p] = 'this not have info'else:print("port[{}] is dead\n".format(p), end='')if __name__ == '__main__':HOST = '10.30.25.199'alive = {}threads = []for p in range(1, 65535):t = threading.Thread(target=port_find, args=(p,))threads.append(t)t.start()for t1 in threads:t1.join()for k,v in alive.items():print(k,'--->',v)
探究:因为线程开启太多会损害性能
那么如何用两个线程去完成socket的端口探测?
这里用到了python的队列(queue)
编程思想
将扫描的端口一次性put加入到队列中
调用二个子线程开始并行
回调函数中while不断利用get从队列取出端口号进行扫描
就实现了两个线程的并行扫描,互不干涉
实现代码
from socket import *
from queue import Queue
import threadingdef port_find():while not port_que.empty():p = port_que.get()with socket(AF_INET, SOCK_STREAM) as sk:re = sk.connect_ex((HOST, p))sk.settimeout(3)if re == 0:print("port[{}] is alive\n".format(p), end='')try:alive[p] = sk.recv(1024).strip().decode()except:alive[p] = 'this not have info'else:print("port[{}] is dead\n".format(p), end='')if __name__ == '__main__':HOST = '192.168.84.130'alive = {}threads = []port_que = Queue()for i in range(30):port_que.put(i)t1 = threading.Thread(target=port_find)t2 = threading.Thread(target=port_find)threads.append(t1)threads.append(t2)t1.start()t2.start()for t in threads:t.join()for k, v in alive.items():print(k, '--->', v)
五、scapy之tcp端口探测
抓包分析
失败流程:1.SYN-> 2.RST,ACK->
成功流程:1.SYN-> 2.SYN,ACK-> 3.ACK->
可知:Socket是通过tcp三次握手进行端口探测
scapy中TCP(flags=‘S’)可以实现第一次握手,发送SYN包
flags=‘SA’–SYN,ACK包,flags=’RA’—RST,ACK包
编程思路
先用scapy构造一个 flags 的值为 S 的报文,S 代表SYN,就是请求建立一个 TCP
连接,在接收到服务器返回的报文中,如果 flagw
上的值为SA(SYN,ACK),那么就代表服务器确定接收到发送的连接请求并同意建立连接,这时候客户端再回应一个AR(ACK,RST)报文,确定接收到服务器的响应,建立连接后又立刻断开。
实现代码
from scapy.all import *
from scapy.layers.inet import IP, TCPdef port_scan(port):packet = IP(dst=ip)/TCP(dport=port,flags='S') # 构造一个 flags 的值为 S 的报文result = sr1(packet,timeout=2,verbose=0)if result.haslayer('TCP'):if result['TCP'].flags == 'SA': # 判断目标主机是否返回 SYN+ACKsend = sr1(IP(dst=ip)/TCP(dport=port,flags='AR'),timeout=2,verbose=0) # 向目标主机发送 ACK+RSTprint('[+] {} is open'.format(port))elif result['TCP'].flags == 'RA':passif __name__ == '__main__':ip = '192.168.84.130'threads = []for p in range(1, 30):t = threading.Thread(target=port_scan, args=(p,))threads.append(t)t.start()for t in threads:t.join()
Python中Socket编程相关推荐
- python的socket编程_Python Socket编程详细介绍
在使用Python做socket编程时,由于需要使用阻塞(默认)的方式来读取数据流,此时对于数据的结束每次都需要自己处理,太麻烦.并且网上也没找到太好的封装,所以就自己写了个简单的封装. 封装思路 1 ...
- python中socket怎么用_Python 之socket的应用
本节主要讲解socket编程的有关知识点,顺便也会讲解一些其它的关联性知识: 一.概述(socket.socketserver): python对于socket编程,提供了两个模块,分别是socket ...
- Python中socket解读
操作系统底层原理 操作系统:(Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在"裸机"上的最基本的系统软件,任何其他软件都必须 ...
- Python学习,python中socket解读
操作系统底层原理 操作系统:(Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在"裸机"上的最基本的系统软件,任何其他软件都必须 ...
- Python:socket编程教程
ocket是基于C/S架构的,也就是说进行socket网络编程,通常需要编写两个py文件,一个服务端,一个客户端. 首先,导入Python中的socket模块: import socket Pytho ...
- python中socket模块常用吗_python中socket模块详解
socket模块简介 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket.socket通常被叫做"套接字",用于描述IP地址和端口,是一个通信 ...
- android c++ socket编程,C++ 中 socket编程实例详解
C++ 中 socket编程实例详解 sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW):基于TCP的soc ...
- python中IO编程中关于StringIO的读写问题
阅读前请看一下:我是一个热衷于记录的人,每次写博客会反复研读,尽量不断提升博客质量.文章设置为仅粉丝可见,是因为写博客确实花了不少精力.希望互相进步谢谢!! 文章目录 阅读前请看一下:我是一个热衷于记 ...
- Python基础-socket编程
一.网络编程 自从互联网诞生以来,现在基本上所有的程序都是网络程序,很少有单机版的程序了. 计算机网络就是把各个计算机连接到一起,让网络中的计算机可以互相通信.网络编程就是如何在程序中实现两台计算机的 ...
最新文章
- 【Android 异步操作】Handler 机制 ( MessageQueue 空闲任务 IdleHandler 机制 )
- 随笔汇总_索取资料请进入
- 不停刷朋友圈的人_不停刷新闻、朋友圈、微信群的朋友,休息一下,看多了伤身!...
- Linux学习-15-学习LVM逻辑卷
- linkbot 中文教程系列 linkbot破解教程
- 在c 语言中 一个函数由函数头和,C语言程序设计基础教程_习题答案
- python 字符集转换-灰常慢
- Hadoop用户配置免密登陆
- 函数的参数个数是不固定_EXCEL这些序号技巧,你还真不一定都知道
- 2019牛客多校第二场E MAZE(线段树 + 矩阵)题解
- 程序包androidx.appcompat.app不存在
- 百度人脸识别:功能开通
- paip.提升用户体验-----c++ 实现360浏览器收藏动作星星动画效果
- devcon-计算机硬件设备的禁用与启动说明
- pe擦除服务器硬盘,怎么彻底删除硬盘数据
- 项目管理过程组-十五至尊图
- 微信小程序 - 小程序分享转发
- 支付宝支付成功之后的接口_继支付宝微信之后,51信用卡还款也开始收费了,手续费再创新高...
- C语言——用函数方法判断闰年
- com.alibaba.fastjson.JSONException: syntax error, pos 1