You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python的socket模块无连接枚举本地网络可用服务器?

用Python Socket模块无连接枚举本地网络服务器

要在本地WiFi网络中无连接枚举服务器,核心思路是利用UDP广播(无连接协议)或者ICMP探测,无需和目标建立完整TCP连接。以下是两种可行方案:

方案一:UDP广播探测(推荐)

UDP是无连接协议,客户端向本地网络的广播地址发送探测包,监听该广播端口的服务器收到后回复自身信息,客户端即可收集到服务器IP。

客户端实现代码

import socket
import threading

def listen_for_responses():
    # 创建UDP套接字
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 绑定到监听端口(和服务器监听端口一致)
    sock.bind(('', 5000))
    
    print("等待服务器响应...")
    while True:
        data, addr = sock.recvfrom(1024)
        print(f"发现服务器: {addr[0]},消息: {data.decode('utf-8')}")

# 启动监听线程
threading.Thread(target=listen_for_responses, daemon=True).start()

# 发送广播探测包
broadcast_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
broadcast_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
# 本地网络广播地址(通常是网关地址最后一位改为255,比如192.168.1.255)
broadcast_addr = ('192.168.1.255', 5000)
broadcast_sock.sendto(b'Hello, servers?', broadcast_addr)

# 保持程序运行
input("按回车退出...\n")

服务器端监听代码(需在目标服务器上运行)

import socket

# 创建UDP套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定到广播端口
sock.bind(('', 5000))

print("服务器监听广播中...")
while True:
    data, addr = sock.recvfrom(1024)
    print(f"收到来自{addr[0]}的探测: {data.decode('utf-8')}")
    # 回复客户端,告知自身存在
    sock.sendto(b'这里是服务器', addr)

方案二:ICMP Ping扫描(无连接探测存活主机)

通过发送ICMP Echo请求(Ping)来探测网络中存活的主机,无需建立TCP/UDP连接。注意:此方法需要管理员/root权限,因为要使用原始套接字。

实现代码

import socket
import struct
import time

def icmp_ping(host):
    # 创建原始套接字,ICMP协议
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
    except PermissionError:
        print("需要管理员/root权限才能运行此扫描")
        return False
    
    # 构造ICMP包
    icmp_type = 8  # Echo请求
    icmp_code = 0
    icmp_checksum = 0
    icmp_id = 12345
    icmp_seq = 1
    # 先构造无校验和的包
    header = struct.pack('!BBHHH', icmp_type, icmp_code, icmp_checksum, icmp_id, icmp_seq)
    data = b'Hello'
    # 计算校验和
    icmp_checksum = calculate_checksum(header + data)
    header = struct.pack('!BBHHH', icmp_type, icmp_code, icmp_checksum, icmp_id, icmp_seq)
    packet = header + data
    
    # 发送包
    sock.sendto(packet, (host, 0))
    sock.settimeout(1)
    
    try:
        recv_packet, addr = sock.recvfrom(1024)
        # 提取ICMP头部
        icmp_header = recv_packet[20:28]
        recv_type, recv_code, _, recv_id, recv_seq = struct.unpack('!BBHHH', icmp_header)
        if recv_type == 0 and recv_id == icmp_id:
            print(f"主机 {host} 存活")
            return True
    except socket.timeout:
        print(f"主机 {host} 无响应")
        return False
    finally:
        sock.close()

def calculate_checksum(data):
    checksum = 0
    data_len = len(data)
    if data_len % 2 != 0:
        data += b'\x00'
        data_len += 1
    for i in range(0, data_len, 2):
        word = (data[i] << 8) + data[i+1]
        checksum += word
    checksum = (checksum >> 16) + (checksum & 0xffff)
    checksum = ~checksum & 0xffff
    return checksum

# 扫描本地网段,比如192.168.1.1到192.168.1.254
for i in range(1, 255):
    host = f'192.168.1.{i}'
    icmp_ping(host)

注意事项

  • UDP广播方案需要服务器配合监听广播端口,适合可控的服务器场景;ICMP扫描无需服务器配合,但需要权限,且部分主机可能禁用ICMP响应。
  • 本地网络广播地址需要根据实际网段调整,可以通过ipconfig(Windows)或ifconfig(Linux/macOS)查看网关地址,将最后一位改为255。
  • 多线程/多进程可以加速ICMP扫描,避免逐个扫描耗时过长。

内容的提问来源于stack exchange,提问作者SeyitAli002

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 02:20:00