获取Windows下某进程监听的TCP/UDP端口
1、在Windows下用CMD netstat命令可以获得当前进程监听端口号的信息,如netstat -ano可以看到IP、port、状态和监听的PID。
那么可以执行CMD这个进程得到监听的端口号信息,C#代码如下:
//进程id
int pid = ProcInfo.ProcessID; //存放进程使用的端口号链表
List<int> ports = new List<int>(); Process pro = new Process();
pro.StartInfo.FileName = "cmd.exe";
pro.StartInfo.UseShellExecute = false;
pro.StartInfo.RedirectStandardInput = true;
pro.StartInfo.RedirectStandardOutput = true;
pro.StartInfo.RedirectStandardError = true;
pro.StartInfo.CreateNoWindow = true;
pro.Start();
pro.StandardInput.WriteLine("netstat -ano");
pro.StandardInput.WriteLine("exit");
Regex reg = new Regex("\\s+", RegexOptions.Compiled);
string line = null;
ports.Clear();
while ((line = pro.StandardOutput.ReadLine()) != null)
{
line = line.Trim();
if (line.StartsWith("TCP", StringComparison.OrdinalIgnoreCase))
{
line = reg.Replace(line, ",");
string[] arr = line.Split(',');
if (arr[] == pid.ToString())
{
string soc = arr[];
int pos = soc.LastIndexOf(':');
int pot = int.Parse(soc.Substring(pos + ));
ports.Add(pot);
}
}
else if (line.StartsWith("UDP", StringComparison.OrdinalIgnoreCase))
{
line = reg.Replace(line, ",");
string[] arr = line.Split(',');
if (arr[] == pid.ToString())
{
string soc = arr[];
int pos = soc.LastIndexOf(':');
int pot = int.Parse(soc.Substring(pos + ));
ports.Add(pot);
}
}
}
pro.Close();
2、如果不执行CMD进程,如何获得?可以参考这篇文章http://www.cnblogs.com/BoyXiao/archive/2012/02/20/2359273.html
文章介绍了使用Windows API获得进程和端口的映射关系:
(1)根据进程 ID 获得该进程所打开的所有的 TCP 和 UDP 端口。
(2)根据端口号来获得打开该端口的进程。
C语言代码如下:
// ProcessorPort.cpp : 定义 DLL 应用程序的导出函数。
// #include "stdafx.h" #include <Windows.h>
#include <Psapi.h>
#include <Iprtrmib.h>
#include <Winsock2.h> #pragma comment(lib,"Psapi.lib")
#pragma comment(lib,"Iphlpapi.Lib")
#pragma comment(lib,"WS2_32.lib") enum TcpOrUdp
{
TcpType,
UdpType
}; typedef struct
{
DWORD dwState; //连接状态
DWORD dwLocalAddr; //本地地址
DWORD dwLocalPort; //本地端口
DWORD dwRemoteAddr; //远程地址
DWORD dwRemotePort; //远程端口
DWORD dwProcessId; //进程标识
}MIB_TCPEXROW,*PMIB_TCPEXROW; typedef struct
{
DWORD dwLocalAddr; //本地地址
DWORD dwLocalPort; //本地端口
DWORD dwProcessId; //进程标识 }MIB_UDPEXROW,*PMIB_UDPEXROW; typedef struct
{
DWORD dwState; //连接状态
DWORD dwLocalAddr; //本地地址
DWORD dwLocalPort; //本地端口
DWORD dwRemoteAddr; //远程地址
DWORD dwRemotePort; //远程端口
DWORD dwProcessId; //进程标识
DWORD Unknown; //待定标识
}MIB_TCPEXROW_VISTA,*PMIB_TCPEXROW_VISTA; typedef struct
{
DWORD dwNumEntries;
MIB_TCPEXROW table[ANY_SIZE];
}MIB_TCPEXTABLE,*PMIB_TCPEXTABLE; typedef struct
{
DWORD dwNumEntries;
MIB_TCPEXROW_VISTA table[ANY_SIZE];
}MIB_TCPEXTABLE_VISTA,*PMIB_TCPEXTABLE_VISTA; typedef struct
{
DWORD dwNumEntries;
MIB_UDPEXROW table[ANY_SIZE];
}MIB_UDPEXTABLE,*PMIB_UDPEXTABLE; //=====================================================================================//
//Name: DWORD AllocateAndGetTcpExTableFromStack() // //
//Descripion: 该函数仅仅只在 Windows XP,Windows Server 2003 下有效 //
//=====================================================================================//
typedef DWORD (WINAPI *PFNAllocateAndGetTcpExTableFromStack)(
PMIB_TCPEXTABLE *pTcpTabel,
bool bOrder,
HANDLE heap,
DWORD zero,
DWORD flags
); //=====================================================================================//
//Name: DWORD AllocateAndGetUdpExTableFromStack() //
//Descripion: 该函数仅仅只在 XP,Windows Server 2003 下有效 //
//=====================================================================================//
typedef DWORD (WINAPI *PFNAllocateAndGetUdpExTableFromStack)(
PMIB_UDPEXTABLE *pUdpTable,
bool bOrder,
HANDLE heap,
DWORD zero,
DWORD flags
); //=====================================================================================//
//Name: DWORD InternalGetTcpTable2() //
//Descripion: 该函数在 Windows Vista 以及 Windows 7 下面效 //
//=====================================================================================//
typedef DWORD (WINAPI *PFNInternalGetTcpTable2)(
PMIB_TCPEXTABLE_VISTA *pTcpTable_Vista,
HANDLE heap,
DWORD flags
); //=====================================================================================//
//Name: DWORD InternalGetUdpTableWithOwnerPid() //
//Descripion: 该函数在 Windows Vista 以及 Windows 7 下面效 //
//=====================================================================================//
typedef DWORD (WINAPI *PFNInternalGetUdpTableWithOwnerPid)(
PMIB_UDPEXTABLE *pUdpTable,
HANDLE heap,
DWORD flags
); //=====================================================================================//
//Name: DWORD GetProcessIdByPort() //
//Descripion: 根据端口号得到打开该端口号的进程ID(支持 XP,Server 2003,Vista,Win7) //
//=====================================================================================//
extern "C" __declspec(dllexport) DWORD __stdcall GetProcessIdByPort(TcpOrUdp type, DWORD dwPort)
{
HMODULE hModule = LoadLibraryW(L"iphlpapi.dll");
if (hModule == NULL)
{
return ;
} if(type == TcpType)
{
// 表明查询的是 TCP 信息
PFNAllocateAndGetTcpExTableFromStack pAllocateAndGetTcpExTableFromStack;
pAllocateAndGetTcpExTableFromStack =
(PFNAllocateAndGetTcpExTableFromStack)GetProcAddress(hModule, "AllocateAndGetTcpExTableFromStack");
if (pAllocateAndGetTcpExTableFromStack != NULL)
{
// 表明为 XP 或者 Server 2003 操作系统
PMIB_TCPEXTABLE pTcpExTable = NULL;
if (pAllocateAndGetTcpExTableFromStack(&pTcpExTable, TRUE, GetProcessHeap(), , AF_INET) != )
{
if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return ;
} for (UINT i = ; i < pTcpExTable->dwNumEntries; i++)
{
// 过滤掉数据,只查询我们需要的进程数据
if(dwPort == ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort))
{
DWORD dwProcessId = pTcpExTable->table[i].dwProcessId;
if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwProcessId;
}
} if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return ;
}
else
{
// 表明为 Vista 或者 7 操作系统
PMIB_TCPEXTABLE_VISTA pTcpExTable = NULL;
PFNInternalGetTcpTable2 pInternalGetTcpTable2 =
(PFNInternalGetTcpTable2)GetProcAddress(hModule, "InternalGetTcpTable2");
if (pInternalGetTcpTable2 == NULL)
{
if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return ;
} if (pInternalGetTcpTable2(&pTcpExTable, GetProcessHeap(), ))
{
if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return ;
} for (UINT i = ;i < pTcpExTable->dwNumEntries; i++)
{
// 过滤掉数据,只查询我们需要的进程数据
if(dwPort == ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort))
{
DWORD dwProcessId = pTcpExTable->table[i].dwProcessId;
if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwProcessId;
}
} if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return ;
}
}
else if(type == UdpType)
{
// 表明查询的是 UDP 信息
PMIB_UDPEXTABLE pUdpExTable = NULL;
PFNAllocateAndGetUdpExTableFromStack pAllocateAndGetUdpExTableFromStack;
pAllocateAndGetUdpExTableFromStack =
(PFNAllocateAndGetUdpExTableFromStack)GetProcAddress(hModule,"AllocateAndGetUdpExTableFromStack");
if (pAllocateAndGetUdpExTableFromStack != NULL)
{
// 表明为 XP 或者 Server 2003 操作系统
if (pAllocateAndGetUdpExTableFromStack(&pUdpExTable, TRUE, GetProcessHeap(), , AF_INET) != )
{
if (pUdpExTable)
{
HeapFree(GetProcessHeap(), , pUdpExTable);
} FreeLibrary(hModule);
hModule = NULL; return ;
} for (UINT i = ; i < pUdpExTable->dwNumEntries; i++)
{
// 过滤掉数据,只查询我们需要的进程数据
if (dwPort == ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort))
{
DWORD dwProcessId = pUdpExTable->table[i].dwProcessId;
if (pUdpExTable)
{
HeapFree(GetProcessHeap(), , pUdpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwProcessId;
}
} if (pUdpExTable)
{
HeapFree(GetProcessHeap(), , pUdpExTable);
} FreeLibrary(hModule);
hModule = NULL; return ;
}
else
{
// 表明为 Vista 或者 7 操作系统
PFNInternalGetUdpTableWithOwnerPid pInternalGetUdpTableWithOwnerPid;
pInternalGetUdpTableWithOwnerPid =
(PFNInternalGetUdpTableWithOwnerPid)GetProcAddress(hModule, "InternalGetUdpTableWithOwnerPid");
if (pInternalGetUdpTableWithOwnerPid != NULL)
{
if (pInternalGetUdpTableWithOwnerPid(&pUdpExTable, GetProcessHeap(), ))
{
if (pUdpExTable)
{
HeapFree(GetProcessHeap(), , pUdpExTable);
} FreeLibrary(hModule);
hModule = NULL; return ;
} for (UINT i = ; i < pUdpExTable->dwNumEntries; i++)
{
// 过滤掉数据,只查询我们需要的进程数据
if (dwPort == ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort))
{
DWORD dwProcessId = pUdpExTable->table[i].dwProcessId;
if (pUdpExTable)
{
HeapFree(GetProcessHeap(), , pUdpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwProcessId;
}
}
} if (pUdpExTable)
{
HeapFree(GetProcessHeap(), , pUdpExTable);
} FreeLibrary(hModule);
hModule = NULL; return ;
}
}
else
{
FreeLibrary(hModule);
hModule = NULL; return -;
}
} //===========================================================================================//
//Name: DWORD GetAllPortByProcessId() //
//Descripion: 根据进程ID得到该进程所打开的所有的端口号,并且在 dwAllPort 数组中返回所有端口号//
// 其中 dwMaxLen 为数组的长度,函数的返回值为进程所打开的端口的数目 //
// (支持 XP,Server 2003,Vista,Win7) //
//===========================================================================================//
extern "C" __declspec(dllexport) DWORD __stdcall GetAllPortByProcessId(TcpOrUdp type, DWORD dwProcessId, DWORD * dwAllPort, DWORD dwMaxLen)
{
DWORD dwPortCount = ;
HMODULE hModule = LoadLibraryW(L"iphlpapi.dll");
if (hModule == NULL)
{
return dwPortCount;
} if(type == TcpType)
{
// 表明查询的是 UDP 信息
PFNAllocateAndGetTcpExTableFromStack pAllocateAndGetTcpExTableFromStack;
pAllocateAndGetTcpExTableFromStack = (PFNAllocateAndGetTcpExTableFromStack)GetProcAddress(hModule, "AllocateAndGetTcpExTableFromStack");
if (pAllocateAndGetTcpExTableFromStack != NULL)
{
// 表明为 XP 或者 Server 2003 操作系统
PMIB_TCPEXTABLE pTcpExTable = NULL;
if (pAllocateAndGetTcpExTableFromStack(&pTcpExTable, TRUE, GetProcessHeap(), , AF_INET) != )
{
if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwPortCount;
} for (UINT i = ; i < pTcpExTable->dwNumEntries; i++)
{
// 过滤掉数据,只获取我们要查询的进程的 Port 信息
if(dwProcessId == pTcpExTable->table[i].dwProcessId)
{
if(dwPortCount < dwMaxLen)
{
dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort);
dwPortCount++;
}
}
} if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwPortCount;
}
else
{
// 表明为 Vista 或者 7 操作系统
PMIB_TCPEXTABLE_VISTA pTcpExTable = NULL;
PFNInternalGetTcpTable2 pInternalGetTcpTable2 = (PFNInternalGetTcpTable2)GetProcAddress(hModule, "InternalGetTcpTable2");
if (pInternalGetTcpTable2 == NULL)
{
if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwPortCount;
} if (pInternalGetTcpTable2(&pTcpExTable, GetProcessHeap(), ))
{
if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwPortCount;
} for (UINT i = ;i < pTcpExTable->dwNumEntries; i++)
{
// 过滤掉数据,只获取我们要查询的进程的 TCP Port 信息
if(dwProcessId == pTcpExTable->table[i].dwProcessId)
{
if(dwPortCount < dwMaxLen)
{
dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pTcpExTable->table[i].dwLocalPort);
dwPortCount++;
}
}
} if (pTcpExTable)
{
HeapFree(GetProcessHeap(), , pTcpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwPortCount;
}
}
else if(type == UdpType)
{
// 表明查询的是 UDP 信息
PMIB_UDPEXTABLE pUdpExTable = NULL;
PFNAllocateAndGetUdpExTableFromStack pAllocateAndGetUdpExTableFromStack;
pAllocateAndGetUdpExTableFromStack = (PFNAllocateAndGetUdpExTableFromStack)GetProcAddress(hModule,"AllocateAndGetUdpExTableFromStack");
if (pAllocateAndGetUdpExTableFromStack != NULL)
{
// 表明为 XP 或者 Server 2003 操作系统
if (pAllocateAndGetUdpExTableFromStack(&pUdpExTable, TRUE, GetProcessHeap(), , AF_INET) != )
{
if (pUdpExTable)
{
HeapFree(GetProcessHeap(), , pUdpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwPortCount;
} for (UINT i = ; i < pUdpExTable->dwNumEntries; i++)
{
// 过滤掉数据,只获取我们要查询的进程的 UDP Port信息
if(dwProcessId == pUdpExTable->table[i].dwProcessId)
{
if(dwPortCount < dwMaxLen)
{
dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort);
dwPortCount++;
}
}
} if (pUdpExTable)
{
HeapFree(GetProcessHeap(), , pUdpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwPortCount;
}
else
{
// 表明为 Vista 或者 7 操作系统
PFNInternalGetUdpTableWithOwnerPid pInternalGetUdpTableWithOwnerPid;
pInternalGetUdpTableWithOwnerPid = (PFNInternalGetUdpTableWithOwnerPid)GetProcAddress(hModule, "InternalGetUdpTableWithOwnerPid");
if (pInternalGetUdpTableWithOwnerPid != NULL)
{
if (pInternalGetUdpTableWithOwnerPid(&pUdpExTable, GetProcessHeap(), ))
{
if (pUdpExTable)
{
HeapFree(GetProcessHeap(), , pUdpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwPortCount;
} for (UINT i = ; i < pUdpExTable->dwNumEntries; i++)
{
// 过滤掉数据,只获取我们要查询的进程的 UDP Port信息
if(dwProcessId == pUdpExTable->table[i].dwProcessId)
{
if(dwPortCount < dwMaxLen)
{
dwAllPort[dwPortCount] = ntohs(0x0000FFFF & pUdpExTable->table[i].dwLocalPort);
dwPortCount++;
}
}
}
} if (pUdpExTable)
{
HeapFree(GetProcessHeap(), , pUdpExTable);
} FreeLibrary(hModule);
hModule = NULL; return dwPortCount;
}
}
else
{
FreeLibrary(hModule);
hModule = NULL; return dwPortCount;
}
}
如果要在.Net平台下使用,将其编译成DLL,使用PInvoke得到DLL导出函数就可以了。
C#测试代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices; namespace ProcessorPortDllTest
{
public enum TcpOrUdp
{
TcpType,
UdpType
}; public class ProcessPortHelper
{
[DllImport("ProcessorPort.dll",CallingConvention = CallingConvention.StdCall)]
public extern static uint GetProcessIdByPort(TcpOrUdp type, uint dwPort); [DllImport("ProcessorPort.dll",CallingConvention = CallingConvention.StdCall)]
public extern static uint GetAllPortByProcessId(TcpOrUdp type, uint dwProcessId, uint[] dwAllPort, uint dwMaxLen);
} class Program
{
static void Main(string[] args)
{
uint port = ;
uint processorId = ProcessPortHelper.GetProcessIdByPort(TcpOrUdp.TcpType, port);
Console.WriteLine("Port {0} is using by processor {1}",port,processorId); uint processorId1 = ; uint[] TcpPorts = new uint[];
uint count = ProcessPortHelper.GetAllPortByProcessId(TcpOrUdp.TcpType, processorId1, TcpPorts, (uint)TcpPorts.Length);
Console.WriteLine("Processor {0} is using TCP port: ", processorId1);
for (uint i = ; i < count; ++i)
{
Console.WriteLine(TcpPorts[i]);
} uint[] UdpPorts = new uint[];
uint count1 = ProcessPortHelper.GetAllPortByProcessId(TcpOrUdp.UdpType, processorId1, UdpPorts, (uint)UdpPorts.Length);
Console.WriteLine("Processor {0} is using UDP port: ", processorId1);
for (uint i = ; i < count1; ++i)
{
Console.WriteLine(UdpPorts[i]);
}
Console.ReadKey();
}
}
}
获得进程监听TCP/UDP端口号的DLL:ProcessorPort.rar
获取Windows下某进程监听的TCP/UDP端口的更多相关文章
- Windows下修改Oracle监听端口
先放开防火墙的端口,再来改监听端口. 只有一个实例: net stop OracleOraDb11g_home1TNSListener 再运行 NET Manager 修改实例名与Listener的端 ...
- (转) windows 下ORA-12514:TNS 监听问题
在使用Orcale数据库的时候不知道各位是否遇到过如图的监听问题(或者显示类似的问题),以下方法就是来解决这样的问题的. 首先右击计算机,选择管理.选择左侧栏的服务与应用程序,右侧栏选服务. ...
- Windows下查看机器监听端口
1.查看所有端口占用情况 在开始-运行-cmd,输入:netstat –ano可以查看所有进程 2.查看指定端口的占用情况 netstat -an |findstr :21
- linux系统实现多个进程监听同一个端口
通过 fork 创建子进程的方式可以实现父子进程监听相同的端口. 方法:在绑定端口号(bind函数)之后,监听端口号之前(listen函数),用fork()函数生成子进程,这样子进程就可以克隆父进程, ...
- 关于获取Windows下性能参数的总结
Windows下特定进程或者所有进程的CPU.物理内存.虚拟内存等性能参数的获取方法小结,包括如何在MFC中以及如何使用C#语言来获取参数. VC API:GlobalMemoryStatus 获取全 ...
- python使用wmi模块获取windows下的系统信息监控系统-乾颐堂
Python用WMI模块获取Windows系统的硬件信息:硬盘分区.使用情况,内存大小,CPU型号,当前运行的进程,自启动程序及位置,系统的版本等信息. 本文实例讲述了python使用wmi模块获取w ...
- Windows下查看进程及结束进程命令[转]
Windows下查看进程及结束进程命令 1)查看占用8080端口的进程号 >netstat –aon | findstr “8080” 结果:TCP 0.0.0.0:8080 ...
- Windows下tomcat进程监控批处理程序
在Windows下tomcat进程监控批处理程序脚本如下: @echo off ::tomcat安装目录 set _tomcatDir=E:\myFiles\apache-tomcat-8.5.31 ...
- Windows平台下Oracle监听服务启动过程中日志输出
Windows平台下Oracle监听服务启动过程中日志输出记录. 日志目录:D:\app\Administrator\diag\tnslsnr\WIN-RU03CB21QGA\listener\tra ...
随机推荐
- Js 的 this 是什么
this指的是调用函数的那个对象,谁调用函数,谁就是this 更多: http://www.cnblogs.com/justany/archive/2012/11/01/the_keyword_thi ...
- 【架构】linkerd:来自Twitter为微服务而生的开源RPC解决方案
大家要如何以规模化方式运维微服务应用程序?实践当中会出现哪些问题,我们又该如何加以解决?在大规模与非预测性工作负载场景当中,我们需要满足哪些条件才能运行一款大型微服务应用程序,而又能够确保不必受到功能 ...
- 64位系统运行32位Oracle程序解决方案
Attempt to load Oracle client libraries threw BadImageFormatException. This problem will occur when ...
- IPC---信号量
一.什么是信号量 信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程) 所拥有. 信号量的值为正的时候,说明它空闲.所测试的线程可以锁定而使用它.若为0,说明 它被占用,测试的线 ...
- poj 1572
一道字符串替换的题目. 题意:给你2*n组字符串,一个是规则,一个是替换的结果. 字符串的题目,确实麻烦,有些细节不处理好就是wa. 这里我提供1组数据 intput 1 abcdef a abcde ...
- “假学习“&”真学习“?(摘)
什么叫做“假学习”? 一.看书 买一堆书,有空看看.看书,这是典型的假学习.看书看不懂还在看,就是假学习,欺骗自己,安慰自己正在学习而已.专业书都写得很好,但大都是写给已经懂的人看的.看书的最大作用就 ...
- 【编程题目】栈的 push、pop 序列
29.栈的 push.pop 序列(栈)题目:输入两个整数序列.其中一个序列表示栈的 push 顺序,判断另一个序列有没有可能是对应的 pop 顺序.为了简单起见,我们假设 push 序列的任意两个整 ...
- SQL常用命令整理
1.增加字段 alter table docdsp add dspcodechar(200)2.删除字段 ALTER TABLE table_NAME DROP COLUMNcolum ...
- jsDoc的使用
nodeJS使用: 直接:npm install jsdoc -g使用:jsdoc [name].js 简介 JsDoc Toolkit 是一款辅助工具,你只需要根据约定在 JavaScript 代码 ...
- 困难的串(dfs)
困难的串 题意: 如果一个字符串包含两个相邻的重复子串,则称它是“容易的串”,其他串称为“困难的串”.例如, BB.ABCDABCD都是容易的串,而D.DC.ABDAD ...