概述
一. python 网络编程
1.socket模块
要使用socket.socket()函数来创建套接字。其语法如下:
socket.socket(socket_family,socket_type,protocol=0)
socket_family可以是如下参数:
socket.AF_INET IPv4(默认)
socket.AF_INET6 IPv6
socket.AF_UNIX 只能够用于单一的Unix系统进程间通信
socket_type可以是如下参数:
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_RDM 是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在需要执行某些特殊操作时使用,如发送ICMP报文。SOCK_RAM通常仅限于高级用户或管理员运行的程序使用。
socket.SOCK_SEQPACKET 可靠的连续数据包服务
protocol参数:
0 (默认)与特定的地址家族相关的协议,如果是 0 ,则系统就会根据地址格式和套接类别,自动选择一个合适的协议
2.套接字对象内建方法
服务器端套接字函数
s.bind() 绑定地址(ip地址,端口)到套接字,参数必须是元组的格式例如:s.bind(('127.0.0.1',8009))
s.listen(5) 开始监听,5为最大挂起的连接数
s.accept() 被动接受客户端连接,阻塞,等待连接
客户端套接字函数
s.connect() 连接服务器端,参数必须是元组格式例如:s.connect(('127,0.0.1',8009))
公共用途的套接字函数
s.recv(1024) 接收TCP数据,1024为一次数据接收的大小
s.send(bytes) 发送TCP数据,python3发送数据的格式必须为bytes格式
s.sendall() 完整发送数据,内部循环调用send
s.close() 关闭套接字
3.demo程序
server
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import socket
import time
IP_PORT = ('127.0.0.1',8009)
BUF_SIZE = 1024
tcp_server = socket.socket()
tcp_server.bind(IP_PORT)
tcp_server.listen(5)
while True:
print("waiting for connection...")
conn,addr = tcp_server.accept()
print("...connected from:",addr)
while True:
data = tcp_server.recv(BUF_SIZE)
if not data:break
tcp_server.send('[%s] %s'%(time.ctime(),data))
tcp_server.close()
client
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import socket
HOST = '127.0.0.1'
PORT = 8009
BUF_SIZE = 1024
ADDR = (HOST,PORT)
client = socket.socket()
client.connect(ADDR)
while True:
data = input(">>> ")
if not data:break
client.send(bytes(data,encoding='utf-8'))
recv_data = client.recv(BUF_SIZE)
if not recv_data:break
print(recv_data.decode())
client.close()
4.自定义协议简单demo
使用自定义协议实现Python向Netty传输数据 - 知乎
网络编程常用struct库使用可参考
python(29):struct模块_python开发笔记的博客-CSDN博客_python struct模块
参考文档
socket — Low-level networking interface — Python 3.10.5 documentation
python中socket模块详解-木庄网络博客
https://www.csdn.net/tags/MtTaMgwsMjc1NzAyLWJsb2cO0O0O.html
网络嗅探
https://www.csdn.net/tags/MtTaAg0sNjEzNDQwLWJsb2cO0O0O.html
python 网络嗅探实验_摸鱼学带师的博客-CSDN博客_python网络嗅探
copy网络嗅探代码
import socket
import threading
import time
import logging
import struct
import ctypes
activeDegree = dict()
flag = 1
'''
IP层 协议字段:占8比特。指明IP层所封装的上层协议类型,如ICMP(1)、IGMP(2) 、TCP(6)、UDP(17)
'''
def main():
global activeDegree
global glag
# 获取本机IP地址
HOST = socket.gethostbyname(socket.gethostname())
print("HOST: ", HOST)
# 创建原始套接字,适用于Windows平台
# 对于其他系统,要把socket.IPPROTO_IP替换为socket.IPPROTO_ICMP
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((HOST, 0))
# s.connect((''))
# 设置在捕获数据包中含有IP包头
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
# 启用混杂模式,捕获所有数据包
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
# 开始捕获数据包
while flag:
data, addr = s.recvfrom(65535)
mac_len = parse_mac(data)
ip_len, pro = parse_ip(data)
if pro == 6:
parse_tcp(data, ip_len)
elif pro == 1:
parse_icmp(data, ip_len)
# if len(data) - mac_len - ip_len >= 8:
elif pro == 17:
parse_udp(data, mac_len + ip_len)
# print('mac: ', mac)
# print('get addr', addr)
host = addr[0]
activeDegree[host] = activeDegree.get(host, 0) + 1
# if addr[0] != HOST:
# print(addr[0])
# 关闭混杂模式
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
s.close()
def parse_mac(raw_buffer):
# parse ethernet header
eth_length = 14
eth_header = raw_buffer[:eth_length]
eth = struct.unpack('!6s6sH', eth_header)
eth_protocol = socket.ntohs(eth[2])
print('Destination MAC : ' + eth_addr(raw_buffer[0:6]) +
' Source MAC : ' + eth_addr(raw_buffer[6:12]) + ' Protocol : ' + str(eth_protocol))
# print('P->13/14: '+eth_protocol(raw_buffer[12:14]))
return eth_length
def eth_addr(a):
b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (a[0], a[1], a[2], a[3], a[4], a[5])
return b
def parse_tcp(raw_buffer, iph_length):
tcp_header = raw_buffer[iph_length: iph_length + 20]
tcph = struct.unpack('!HHLLBBHHH', tcp_header)
source_port = tcph[0]
dest_port = tcph[1]
sequence = tcph[2]
acknowledgement = tcph[3]
doff_reserved = tcph[4]
tcph_length = doff_reserved >> 4
print(('TCP => Source Port: {source_port}, Dest Port: {dest_port}'
' Sequence Number: {sequence} Acknowledgement: {acknowledgement}'
' TCP header length: {tcph_length}').format(
source_port=source_port, dest_port=dest_port,
sequence=sequence, acknowledgement=acknowledgement,
tcph_length=tcph_length
))
def parse_udp(raw_buffer, idx):
udph_length = 8
udp_header = raw_buffer[idx: idx + udph_length]
udph = struct.unpack('!HHHH', udp_header)
source_port = udph[0]
dest_port = udph[1]
length = udph[2]
checksum = udph[3]
print(('UDP => Source Port: {source_port}, Dest Port: {dest_port} '
'Length: {length} CheckSum: {checksum}').format(
source_port=source_port, dest_port=dest_port,
length=length, checksum=checksum
))
def parse_ip(raw_buffer):
# IP 头
ip_header = raw_buffer[0:20]
# 解析IP头
# see http://blog.guozengxin.cn/2013/07/25/python-struct-pack-unpack
iph = struct.unpack('!BBHHHBBH4s4s', ip_header)
version_ihl = iph[0]
version = version_ihl >> 4
ihl = version_ihl & 0xF
iph_length = ihl * 4
ttl = iph[5]
protocol = iph[6]
s_addr = socket.inet_ntoa(iph[8])
d_addr = socket.inet_ntoa(iph[9])
print(('IP -> Version: {version}, Header Length: {header},'
'TTL: {ttl}, Protocol: {protocol}, Source IP: {source},'
'Destination IP: {destination}').format(
version=version, header=iph_length,
ttl=ttl, protocol=protocol, source=s_addr,
destination=d_addr
))
return iph_length, protocol
def parse_icmp(raw_buffer, iph_length):
buf = raw_buffer[iph_length : iph_length + ctypes.sizeof(ICMP)]
icmp_header = ICMP(buf)
print(('ICMP -> Type:%d, Code: %d, CheckSum: %d'
% (icmp_header.type, icmp_header.code, icmp_header.checksum)))
class ICMP(ctypes.Structure):
"""ICMP 结构体"""
_fields_ = [
('type', ctypes.c_ubyte),
('code', ctypes.c_ubyte),
('checksum', ctypes.c_ushort),
('unused', ctypes.c_ushort),
('next_hop_mtu', ctypes.c_ushort)
]
def __new__(self, socket_buffer):
return self.from_buffer_copy(socket_buffer)
def __init__(self, socket_buffer):
pass
t = threading.Thread(target=main)
t.start()
time.sleep(60)
flag = 0
t.join()
for item in activeDegree.items():
print(item)
strcut,黏包现象
网络编程中的黏包现象 - 知乎
浅析Python中的struct模块 - 糖拌咸鱼 - 博客园
最后
以上就是超级大米为你收集整理的python(42): socket 网络编程自定义私有协议一. python 网络编程的全部内容,希望文章能够帮你解决python(42): socket 网络编程自定义私有协议一. python 网络编程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复