申请会员ID:happymade【申请通过】
1、申 请 I D :happymade2、个人邮箱:366615@qq.com
3、申请说明:本人是MSRM3(多交换机路由器监控3)软件作者。最近通过软件用户反馈得知有热心群众把我的MSRM3软件发到了此论坛上给大家共享(https://www.52pojie.cn/forum.php?mod=viewthread&tid=1344722),感谢这位热心群众发帖。但又看到围观群众有些有疑问却得不到解答,看的心慌……即想注册个账号,好给大家回复解答疑问。
本人从事网络运维管及软件开发17年,常编写方便自己网络管理工作的各种应用程序。 MSRM3(多交换机路由器监控v3)是我在多年管理企业网络的经验基础上,完全个人编写的一款适用于各类企业、院校、政府及通讯维护业的网络设备的监控管理软件。该软件自己也用于所在企业的网络管理,也作为共享软件免费给大家使用。用后欢迎提出意见和建议,我好改进更新……
4、原创技术文章:《MSRM3快速建立业网络拓扑图》 (该文章已发表于期刊《网络安全和信息化》第2020年12期,知网已收录:https://mall.cnki.net/magazine/article/WAXX202012042.htm)
---------原文内容 开始------------
企业、高校都离不开网络,必然有很多的网络设备,高效的管理运维是网管员的最迫切需要的。用上MSRM3,会让网络管理工作轻松许多。
对于各类企业、院校、政府及通讯维护业的网络管理员来说,手里管理着一堆的交换机、路由器等网络设备,并时时刻刻维护着它们,让网络保持通畅。但偶尔难免某个设备出现故障掉线,或某个设备CPU太忙或流量过高导致网络拥堵。通常来说都是终端用户报告网络不好用时管理员才去关注并分析处理故障,导致终端用户的网络体验不好。
然而管理网络,没有拓扑图哪能行,传统的建立网络网络图,用Visio慢慢的画,按照真实的网络结构来做的话,少说要用大半天时间,画出来的拓扑图通常输出成图片展示,这样的拓扑图不能体现实时的网络状态,不能交互查看更详细的拓扑链路信息。用MSRM3来自动生成实时状态可交互的拓扑图,也就分分钟的事。下面细说如何操作。
MSRM3是一款Windows绿色软件,仅一个大小不足3兆的控制台EXE文件,无需安装直接双击运行,自身也可以注册为Windows系统服务来提供服务。第一次启动控制台程序,将提示要求绑定Web服务端口,直接回车绑定本机TCP 80端口作为Web服务端口。绑定成功后控制台将自动呼出本机默认浏览器,打开MSRM3的Web管理界面。 此时MSRM3配置完成,启动成功。
鼠标滑到页面顶部,点击主菜单右侧的红色用户按钮登录。第一次登录填写的用户名和密码将自动添加为管理员账户。登录成功后,在中间黑色空白拓扑界面点击鼠标右键,打开拓扑菜单,选择【全网拓扑发现】。打开拓扑发现对话框,填写拟作为中心设备IP地址及SNMP团体名,选择发现的层次后,点【开始拓扑发现】。
在执行这一步之前,还须把企业内的网络设备都开启SNMP,设置统一的只读团体名。
以CISCO、锐捷品牌网络设备为例,在全局配置模式下输入:
snmp-server community MSRM ro(设置只读团体名为MSRM)
华为、H3C、HP品牌为例,在全局配置模式下输入:
snmp-agent(开启SNMP-agent服务)
snmp-agent community read MSRM(设置只读团体名为MSRM)
snmp-agent sys-info version v2c(设置仅需开启V2C版本协议)
拓扑发现过程中有进度提示,总共等待大约50秒,界面提示【拓扑发现结束】,以我所在企业为例,共自动发现658个设备,5万多个端口,并按真实情况生成了655条设备端口间连线,此时螺旋环状的真实拓扑图已经生成好了。生成的拓扑图如同蜘蛛网一样,拓扑图上的每根连线都精确到设备的具体的某个物理接口。拓扑图可以用鼠标滚轮缩放和拖动来查看。
自动生成的拓扑图由于设备和连线太多可能显得杂乱,可人工分区整理。选中其中一台汇聚交换机,拖动到一旁,在此设备图标上点击鼠标右键,打开设备菜单,选择【螺旋聚拢…】,这时仅和此台设备相连的设备将聚拢到一起。
为了更直观的分区,此时可新建区域,在黑色空白拓扑图点击鼠标右键,打开拓扑菜单,选择【添加新区域】,新的区域将建立在拓扑图中。拖动区域位置、并配合拉动区域的四个角来调整区域的大小,框住螺旋聚拢的设备,被区域框住的设备将随区域一起移动。要让区域内的设备排列更美观,可在区域内空白处,点击鼠标右键,打开区域菜单,选择【区域内设备调整】勾选【调整区域大小时自动排列】选项,此时,再次拉动区域的四个角来调整区域大小,区域内的设备就会自动整齐化排列。
经过几分钟的分区整理,拓扑图部分明显清爽许多。整理好拓扑布局后,按下热键Ctrl+S 或拓扑空白处右键菜单选择保存拓扑来保存拓扑布局。
可别以为所有的连线都是绿色的,其实并不是,绿色线缆表示的是链路Up的线缆。其实整个拓扑图都是实时的。当交换机端口出现Down,线缆会出现红色或橙色,某个设备如果不能通讯,将在设备上显示【通讯超时】,意外断开的端口将显示【端口故障】。
在拓扑图的设备图标上点击鼠标右键打开设备菜单,可选择Telnet管理此设备。通过Web实现对设备的Telnet管理,这其实是MSRM3服务端向设备发起的Telnet,当你的MSRM3架设在某个服务器,你甚至可以配置交换机仅允许MSRM3服务器的IP连接Telnet,从而实现了部分堡垒机的功能,不管在内外网都可以管理你的企业内部的网络设备。
拓扑图上双击任意一根线缆会出现线缆连接信息。信息包含两端的设备名,端口名,链路速率,是否有告警信息,如开启有端口流量记录,可直接快速查看该端口的流量图。
拓扑图上双击设备图标,将打开设备详细信息边栏。在设备详细信息界面,点击顶部笔形状的修改设备信息按钮,可对此设备各类信息进行编辑,开启设备性能监控、接口监控、告警等。
端口开启流量记录、设备开启性能记录后,经过一段时间的采集,可以看流量图和性能图。流量图和性能图是矢量、可交互的,可鼠标拖动来选择时间范围,滚动鼠标滚轮来缩放,数据详细到每分钟。
如有多个设备和开启多个端口的流量记录后,可以在顶部的【数据排序】功能模块看到所有的设备和开启流量记录的端口,可自定义列,设置分组,各类排序,方便统计管理。
MSRM3还有一个重要功能就是告警通知到微信。在【系统设置】栏目按照操作指南开启通知到微信。当你的设备出现掉线,重要端口出现意外断线,告警信息将实时发送到你的微信。让网络运维从用户报障、被动维护,变为自我发现、主动维护,提升管理服务质量。
MSRM3还有许多实用的功能,作者不久后还将加入全网实时查找定位某个IP/MAC所处交换机端口位置功能。
难怪有搞运维的朋友评价MSRM3:“方便、卫生,见效快”。真希望大家和我一起探索发现改进MSRM3,让网络运维变得高效、简单。
---------原文内容 结束------------
5、个人开发截图证明:
很抱歉,论坛不接受成品申请,可以继续回复通过技术文章,来申请。 先来一个前端的技术文章分享……
分享自己做的一款实用 React 虚拟键盘组件,支持AntDesign,可用于触屏输入文本内容。
(曾分享到CSDN) https://blog.csdn.net/u011527696/article/details/108891363
------------内容-------------
个人在做一个只有触屏的React前端开发,需要输入文本,找了一圈没有好用的React虚拟键盘插件。故自己写了一个,分享给大家。
https://img-blog.csdnimg.cn/20200930233409302.jpg
代码如下:
文件名: VK.jsx
/*--
海皮智造 虚拟键盘 20200930
=============================================
React 内调用说明:
import { VirtualKeyboard } from './VK'
VirtualKeyboard 有2个参数,3个方法。
//
参数1:
VirtualKeyboard.isDisableEnter=true|false
是否禁用Enter键,默认为true。
参数2:
VirtualKeyboard.isDisableTab=true|false
是否禁用Tab键,默认为true。
------------------------
方法1:
.showKeyboardSetState(valueObject,reactComponent)
显示虚拟键盘,此方式主要用于Antd Input组件,由于Antd的输入组件直接修改dom的value不生效,故只能传入值Object对象。
valueObject 是一个Object,Object对象必须使用value属性来传递值。
reactComponent 是当前React Component,用于按键后setState更新显示。
如下例子:
let V={value:'123'}
<Input onClick={()=>VirtualKeyboard.showKeyboardSetState(V,this)} value={V.value}/>
方法2:
.showKeyboard(e)
显示虚拟键盘,此方式主要用于大部分模式。
参数e可是3种类型,
1、字符串,即要联动的dom的id
使用举例: VirtualKeyboard.showKeyboard("inputA")
2、直接是要联动的dom对象,
使用举例: VirtualKeyboard.showKeyboard(document.getElementById("xxx"))
3、鼠标/触摸事件
使用举例: <input onClick={VirtualKeyboard.showKeyboard} />
方法3:
.closeKeyboard()
用命令来关闭键盘,一般来说用不到。
--*/
import React from 'react';
import ReactDOM from 'react-dom';
class VK extends React.Component {
//定义键盘显示内容的字符串数组,字符串内容2个字符的为支持Shift切换按键。
C = [
"~`", "!1", "@2", "#3", "$4", "%5", "^6", "&7", "*8", "(9", ")0", "_-", "+=", "Backspace",
"Tab", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "{[", "}]", "|\\",
"CapsLock", "A", "S", "D", "F", "G", "H", "J", "L", "L", ":;", "\"'", "Enter",
"Shift", "Z", "X", "C", "V", "B", "N", "M", "<,", ">.", "?/", "Space"]
//定义按键宽度的数组,为空时为默认宽度
W = [, , , , , , , , , , , , , 120, 90, , , , , , , , , , , , , 90, 110, , , , , , , , , , , , 135, 140, , , , , , , , , , , 170]
//以上2个数组项目数必须相同
//鼠标按下事件函数,用于拖动键盘位置。
F_MouseDown = (e) => {
e = e.nativeEvent
if (e.button !== 0) return
if (e.target.id.indexOf("VK_") !== 0) {
if ((e.target.innerText === "Enter" && this.props.values.isDisableEnter === true) || (e.target.innerText === "Tab" && this.props.values.isDisableTab === true)) {
return
}
e.target.style.backgroundColor = "#F80"
e.target.style.boxShadow = "0px 0px 4px #000 inset"
this.V.keydom = e.target
document.addEventListener("mouseup", this.F_KeyMouseUp);
return
}
//绑定移动事件
document.addEventListener("mousemove", this.F_MouseMove);
//绑定放开按钮事件
document.addEventListener("mouseup", this.F_MouseUp);
this.V.posX = -e.pageX
this.V.posY = -e.pageY
}
//鼠标移动事件函数,用于拖动键盘位置(当鼠标按下之后才绑定此事件)。
F_MouseMove = (e) => {
let tx = this.V.posX + e.pageX + this.V.x;
let ty = this.V.posY + e.pageY + this.V.y;
this.dom.style.left = tx + 'px'
this.dom.style.top = ty + 'px'
}
//鼠标放开事件函数,用于拖动键盘位置(当鼠标按下之后才绑定此事件)。
F_MouseUp = (e) => {
this.V.x = this.V.posX + e.pageX + this.V.x;
this.V.y = this.V.posY + e.pageY + this.V.y;
//取消事件绑定
document.removeEventListener("mousemove", this.F_MouseMove);
document.removeEventListener("mouseup", this.F_MouseUp);
}
F_KeyMouseUp = (e, dom) => {
this.V.keydom.style.backgroundColor = "#FFF"
this.V.keydom.style.boxShadow = null
document.removeEventListener("mouseup", this.F_KeyMouseUp);
}
F_TouchStart = (e) => {
e = e.nativeEvent
if (e.target.id.indexOf("VK_") !== 0) {
if ((e.target.innerText === "Enter" && this.props.values.isDisableEnter === true) || (e.target.innerText === "Tab" && this.props.values.isDisableTab === true)) {
return
}
e.target.style.backgroundColor = "#F80"
e.target.style.boxShadow = "0px 0px 4px #000 inset"
this.V.keydom = e.target
document.addEventListener("touchend", this.F_KeyTouchEnd);
return
}
document.addEventListener("touchmove", this.F_TouchMove);
document.addEventListener("touchend", this.F_TouchEnd);
this.V.posX = -e.targetTouches.pageX
this.V.posY = -e.targetTouches.pageY
}
F_TouchMove = (e) => {
let tx = this.V.posX + e.targetTouches.pageX + this.V.x;
let ty = this.V.posY + e.targetTouches.pageY + this.V.y;
this.dom.style.left = tx + 'px'
this.dom.style.top = ty + 'px'
}
F_TouchEnd = (e) => {
this.V.x = this.V.posX + e.changedTouches.pageX + this.V.x;
this.V.y = this.V.posY + e.changedTouches.pageY + this.V.y;
document.removeEventListener("touchmove", this.F_TouchMove);
document.removeEventListener("touchend", this.F_TouchEnd);
}
F_KeyTouchEnd = (e) => {
this.V.keydom.style.backgroundColor = "#FFF"
this.V.keydom.style.boxShadow = null
document.removeEventListener("touchend", this.F_KeyTouchEnd);
}
F_KeyDown = (e) => {
let dom = e.target
let txt = dom.innerText
if (txt === "CapsLock") {
this.V.isCaps = !this.V.isCaps
if (this.V.isCaps) {
dom.style.backgroundColor = "#F80"
} else {
dom.style.backgroundColor = "#FFF"
}
this.setState({})
} else if (txt === "Shift") {
this.V.isShift = !this.V.isShift
if (this.V.isShift) {
dom.style.backgroundColor = "#F80"
} else {
dom.style.backgroundColor = "#FFF"
}
this.setState({})
} else if (txt === "Enter") {
if (this.props.values.isDisableEnter === false) {
this.F_ChangeInput(String.fromCharCode(13))
}
} else if (txt === "Space") {
this.F_ChangeInput(" ")
} else if (txt === "Tab") {
if (this.props.values.isDisableTab === false) {
this.F_ChangeInput(String.fromCharCode(9))
}
} else if (txt === "Backspace") {
this.F_ChangeInput(-1)
} else if (txt.indexOf("\n") >= 0) {
if (this.V.isShift) {
this.F_ChangeInput(txt)
} else {
this.F_ChangeInput(txt)
}
} else {
if (this.V.isShift) {
this.F_ChangeInput(txt.toUpperCase() === txt ? txt.toLowerCase() : txt.toUpperCase())
} else this.F_ChangeInput(txt)
}
}
render() {
let keyStyle = {
boxSizing: "border-box",
float: "left",
height: 60,
margin: 2.5,
borderRadius: 4,
border: "1px solid #333",
textAlign: "center",
cursor: "pointer",
}
return (
<div onContextMenu={e => e.preventDefault()} tabIndex="-1" id="VK_Main" ref={dom => this.dom = dom} style={{ outline: 'none', top: this.V.y, left: this.V.x, position: 'absolute', zIndex: '999999999', backgroundColor: '#AAA', padding: 3, width: 970, fontSize: 20, border: '1px solid #444', borderRadius: 8, userSelect: 'none' }} onMouseDown={this.F_MouseDown} onTouchStart={this.F_TouchStart} onBlur={this.F_Close}>
<div id="VK_Title" style={{ fontSize: 14, margin: 5, textAlign: "right" }}><span id="VK_Tip" style={{ float: 'left' }}>海皮智造 © 虚拟键盘</span>如虚拟键盘遮挡显示内容,可以拖动移开或 <button style={{ borderRadius: 6, border: '1px dotted #333' }} onClick={this.F_Close}>关闭虚拟键盘</button></div>
<div id="VK_Keys" style={{ height: 67, lineHeight: 67 }} onClick={this.F_KeyDown} >
{this.C.map((c, n) => {
if (c.length === 2) {
return (<div key={n} style={{ ...keyStyle, width: this.W ? this.W : 60, lineHeight: '28px', backgroundColor: "#fff" }}>
{c}<br />{c}
</div>)
} else {
return <div key={n} style={{ ...keyStyle, width: this.W ? this.W : 60, lineHeight: '60px', backgroundColor: (c === "Tab" && this.props.values.isDisableTab) || (c === "Enter" && this.props.values.isDisableEnter) ? "#888" : "#fff" }}>{c.length === 1 ? (this.V.isCaps ? c.toUpperCase() : c.toLocaleLowerCase()) : c}</div>
}
})}
</div>
</div>
)
}
constructor(props) {
super()
if (props.values.dom !== null) {
this.V.currentDom = props.values.dom
}
if (props.values.value !== null && props.values.state !== null) {
this.V.reactValueObject = props.values.value
this.V.reactStateObject = props.values.state
}
let w = document.body.clientWidth
let h = document.body.clientHeight
this.V.x = w / 2 - 970 / 2
this.V.y = h - 300
}
UNSAFE_componentWillUpdate(props) {
if (props.values.dom !== null) {
this.V.currentDom = props.values.dom
this.V.reactValueObject = null
this.V.reactStateObject = null
} else if (props.values.value !== null && props.values.state !== null) {
this.V.reactValueObject = props.values.value
this.V.reactStateObject = props.values.state
this.V.currentDom = null
}
}
componentDidMount() {
this.dom.focus()
}
F_ChangeInput = (c) => {
let inputContent = ""
if (this.V.currentDom !== null) {
inputContent = this.V.currentDom.innerText || this.V.currentDom.textContent || this.V.currentDom.value
} else inputContent = this.V.reactValueObject.value;
inputContent = inputContent.toString()
let strArr = inputContent.split('')
if (c === -1) {
strArr.pop()
} else strArr.push(c)
if (this.V.currentDom !== null) {
if (this.V.currentDom.nodeName === "INPUT") {
this.V.currentDom.value = strArr.join('')
} else if (this.V.currentDom.nodeName !== undefined) {
this.V.currentDom.innerHTML = strArr.join('')
}
} else if (this.V.reactStateObject !== null && this.V.reactValueObject !== null) {
this.V.reactValueObject.value = strArr.join('')
this.V.reactStateObject.setState({})
}
}
V = {
isCaps: false,
isShift: false,
currentDom: null,
reactValueObject: null,
reactStateObject: null
}
F_Close = () => {
this.props.values.closeKeyboard()
}
}
const data = {
VK: VK.prototype,
div: null,
props: {}
}
export const VirtualKeyboard = {
isDisableEnter: true,
isDisableTab: true,
showKeyboardSetState: (valueObject, reactComponent) => {
data.props.value = valueObject
data.props.state = reactComponent
data.props.dom = null
if (data.div !== null) {
data.VK.setState({})
} else {
data.props.closeKeyboard = VirtualKeyboard.closeKeyboard
data.props.isDisableEnter = VirtualKeyboard.isDisableEnter
data.props.isDisableTab = VirtualKeyboard.isDisableTab
let body = document.getElementsByTagName("body")
if (body === undefined) return
let div = document.createElement("div")
data.div = div
body.appendChild(div)
let V = <VK ref={dom => data.VK = dom} values={data.props} />
ReactDOM.render(V, div)
}
},
showKeyboard: (e) => {
data.props.value = null
data.props.state = null
data.props.dom = null
if (typeof (e) === "string") {
let dom = document.getElementById(e)
if (dom !== null) {
data.props.dom = dom
}
} else if (typeof (e) === "object") {
if (typeof (e.type) === "string" && typeof (e.nodeName) === "string") {
data.props.dom = e
} else if (e.target !== undefined) {
e = e.target
if (typeof (e.type) === "string" && typeof (e.nodeName) === "string") {
data.props.dom = e
}
}
}
if (data.props.dom === null) return
if (data.div !== null) {
data.VK.setState({})
} else {
data.props.closeKeyboard = VirtualKeyboard.closeKeyboard
data.props.isDisableEnter = VirtualKeyboard.isDisableEnter
data.props.isDisableTab = VirtualKeyboard.isDisableTab
let body = document.getElementsByTagName("body")
if (body === undefined) return
let div = document.createElement("div")
data.div = div
body.appendChild(div)
let V = <VK ref={dom => data.VK = dom} values={data.props} />
ReactDOM.render(V, div)
}
},
closeKeyboard: () => {
ReactDOM.render(null, data.div)
data.div.remove()
data.div = null
}
}
调用例子:例子中的<Input /> 是AntD的组件。
import { VirtualKeyboard } from './VK';
class Test extends React.Component {
V={value:"hello"}
render() {
return <Input onClick={() => VirtualKeyboard.showKeyboardSetState(this.V, this)} value={this.V.value} />
}
}
下面再来点实用应用程序技术分享: 再来一个小型应用程序:
windows下管理网络用ping来检查网络通断和延迟判断网络质量太常用不过了,但是也太局限了。如对端服务器禁用了ping,或ping的通,延时不高,可访问服务器却卡的不得了。
如何判断哪里卡,是服务器网络链路质量问题,还是服务器业务端处理(如数据库运算)响应不过来,还是基础服务本身就卡(如遭遇DDOS,建立连接响应不过来)。对此我简单做了一个TCPTest小工具,测试服务器TCP响应速度,可以理解为TCP Ping。
代码为VB.net。编译方法:新建一Visual Basic控制台程序。
在模块中粘贴如下代码:
Imports System.Threading
Module Module1
Sub Main()
Console.WriteLine("TCP 连接测试 【 Happymade 编写 1.0】")
Do
Dim Add As String = ""
Do
Console.WriteLine()
Console.Write("目标IP或者域名>")
Dim S = Console.ReadLine()
If S <> "" Then
Add = S
Exit Do
Else
Console.WriteLine("XXX 目标IP或者域名不能为空")
End If
Loop
Dim Port As Integer
Do
Console.Write("TCP端口(默认80)>")
Dim S As String = Console.ReadLine()
If S = "" Then
Port = 80
Exit Do
Else
If Integer.TryParse(S, Port) Then
If Port < 0 And Port > 65535 Then
Console.WriteLine("XXX 端口超过范围")
Else
Exit Do
End If
Else
Console.WriteLine("XXX 端口必须是数字")
End If
End If
Loop
Dim N As Integer
Do
Console.Write("测试次数(默认100次)>")
Dim S As String = Console.ReadLine()
If S = "" Then
N = 100
Exit Do
Else
If Integer.TryParse(S, N) Then
If N < 0 And N > 1000000 Then
Console.WriteLine("XXX 测试次数超过范围")
Else
Exit Do
End If
Else
Console.WriteLine("XXX 测试次数必须是数字")
End If
End If
Loop
Dim MS As Integer
Do
Console.Write("单次超时时间(默认200ms)>")
Dim S As String = Console.ReadLine()
If S = "" Then
MS = 200
Exit Do
Else
If Integer.TryParse(S, MS) Then
If N < 0 And N > 5000 Then
Console.WriteLine("XXX 单次超时时间超过范围")
Else
Exit Do
End If
Else
Console.WriteLine("XXX 单次超时时间必须是数字")
End If
End If
Loop
Dim W As Integer
Do
Console.Write("单次间隔时间(默认100ms)>")
Dim S As String = Console.ReadLine()
If S = "" Then
W = 100
Exit Do
Else
If Integer.TryParse(S, W) Then
If N < 0 And N > 10000 Then
Console.WriteLine("XXX 单次间隔时间超过范围")
Else
Exit Do
End If
Else
Console.WriteLine("XXX 单次间隔时间必须是数字")
End If
End If
Loop
Dim Lost = 0
Dim OK = 0
Dim ALL = 0
Dim min As Single = 1000000, max As Single = 0
For I = 1 To CInt(N)
Dim TimeoutObject As New ManualResetEvent(False)
Dim IsConnectionSuccessful = False
Dim Tcp As New System.Net.Sockets.TcpClient()
Dim t1 = Date.Now
Tcp.BeginConnect(Add, CInt(Port), New AsyncCallback(Sub(asyncresult As IAsyncResult)
Try
IsConnectionSuccessful = False
Dim tcpclient As System.Net.Sockets.TcpClient = asyncresult.AsyncState
If (tcpclient.Client IsNot Nothing) Then
tcpclient.EndConnect(asyncresult)
IsConnectionSuccessful = True
TimeoutObject.Set()
End If
Catch ex As Exception
End Try
End Sub), Tcp)
If TimeoutObject.WaitOne(MS, True) Then
If (IsConnectionSuccessful) Then
Dim t2 = Date.Now
Dim x = CInt((t2 - t1).TotalMilliseconds * 10) / 10
Dim xx = x.ToString & "."
Dim xxx = xx.Split(".")
Dim xxxx = xxx(0).PadLeft(3, " ") & "." & xxx(1).PadRight(1, "0").Substring(0, 1)
Console.Write(xxxx & " ")
OK += 1
ALL += x
If x < min Then min = x
If x > max Then max = x
Else
Console.Write("--E-- ")
Lost += 1
End If
Else
Console.Write("--T-- ")
Lost += 1
End If
Tcp.Close()
Tcp = Nothing
If W > 0 Then
System.Threading.Thread.Sleep(W)
End If
Next
Console.WriteLine()
Dim AV As Single
If OK = 0 Then
AV = 0
Else
AV = CInt(ALL / OK * 100) / 100
End If
Console.WriteLine("结束,成功=" & OK & ",失败=" & Lost & ",平均=" & AV & ",最小=" & min & ",最大=" & max)
Console.WriteLine()
Console.WriteLine("再来一轮? 直接按回车,其他输入退出。")
Dim K = Console.ReadKey()
If K.Key <> ConsoleKey.Enter Then
Exit Do
End If
Loop
End Sub
End Module
效果图:
如网卡,但TCP ping值不高,可大体分析网络链路质量和基本服务响应无问题,问题可能出在Web应用本身。 要不,再来一个happymade个人应用,好用拿走不用谢。
-----------------
用Git来做版本控制,好用!好用!好用!但是也不好用!
原因:保存代码后要记得签入,并提交到服务器。忘了签入和提交,白搞!再又如:代码在多次修改调试过程中,某些特定情况下CTRL+Z回退不了,重新手动改写回去考记忆,还慢。
为了解决这个问题,方便自己编写代码调试,任何时候可回退到每一调试状态,我写了一个AutoGit程序,辅助自己!
主要原理:为当前程序目录建立Git管理,当检测到发生保存操作,自动commit,并Push到服务器。这样调试(保存)的每一步都被记录了下来并提交到远端,即可回退查询任意时间的点的代码记录。
VB.net代码。控制台应用程序。
Imports System.IO
Module Module1
Sub Main(cs() As String)
Console.WriteLine("HappyInvention AutoGit " & Process.GetCurrentProcess.MainModule.FileVersionInfo.ProductVersion.ToString)
Console.WriteLine("=================================================================")
If cs.Length = 0 Then
Dim ZSPSI As New ProcessStartInfo(Process.GetCurrentProcess.MainModule.FileName)
ZSPSI.Arguments = """" & System.Environment.CurrentDirectory & """"
Process.Start(ZSPSI)
Console.WriteLine("无参数启动,退出...")
Return
End If
Dim Dir1 As String = cs(0)
Dim PSI As New ProcessStartInfo("Git")
PSI.WindowStyle = ProcessWindowStyle.Minimized
Try
Console.WriteLine(">Git " & PSI.Arguments)
Process.Start(PSI).WaitForExit()
Console.WriteLine("!Done")
Catch ex As Exception
Console.WriteLine("你尚未安装Git,按任意键退出...")
Console.ReadKey()
Return
End Try
Console.WriteLine("当前目录:" & Dir1)
Dim FP = (Dir1 & "\.Git\config").Replace("\\", "\")
If IO.File.Exists(FP) = False Then
Do
Console.WriteLine()
Console.WriteLine("该目录尚未初始化Git。")
Console.WriteLine()
Console.WriteLine("请选择功能:")
Console.WriteLine("i、初始化Git到该目录")
Console.WriteLine("c、克隆一个项目到该目录")
Console.WriteLine("q、退出")
Dim k = Console.ReadKey
If k.Key = ConsoleKey.I Then
Console.WriteLine()
Console.WriteLine("请设置Git远程服务器地址,如为空仅初始化本地Git。")
Console.Write("Git远程服务器地址> ")
Dim tS = Console.ReadLine
PSI.Arguments = "init"
Console.WriteLine(">Git " & PSI.Arguments)
Process.Start(PSI).WaitForExit()
Console.WriteLine("!Done")
If tS <> "" Then
PSI.Arguments = "remote add origin " & tS
Console.WriteLine(">Git " & PSI.Arguments)
Process.Start(PSI).WaitForExit()
Console.WriteLine("!Done")
End If
Console.WriteLine("Git初化成功。")
Exit Do
ElseIf k.Key = ConsoleKey.C Then
Console.WriteLine()
Console.WriteLine("请填写Git远程服务器地址。")
Console.Write("Git远程服务器地址> ")
Dim tS = Console.ReadLine
If tS = "" Then
Console.WriteLine("没有填写地址,退出...")
Return
End If
Console.WriteLine("Git开始Clone下载。")
PSI.Arguments = "clone " & tS & " GitCloneDownload"
Console.WriteLine(">Git " & PSI.Arguments)
Process.Start(PSI).WaitForExit()
Console.WriteLine("!Done")
If IO.Directory.Exists(Dir1 & "\GitCloneDownload") = False Then
Console.WriteLine("!!!项目没有下载成功,请检查项目地址是否正确,注意区分大小写!!!")
Else
Dim files = Directory.GetFiles(Dir1 & "\GitCloneDownload")
Dim isErr = False
For Each f In files
Dim nf = Path.Combine({Dir1, Path.GetFileName(f)})
Try
IO.File.Move(f, nf)
Catch ex As Exception
isErr = True
End Try
Next
Dim dirs = Directory.GetDirectories(Dir1 & "\GitCloneDownload")
For Each d In dirs
Dim nd = Path.Combine({Dir1, Path.GetFileName(d)})
Try
IO.Directory.Move(d, nd)
Catch ex As Exception
isErr = True
End Try
Next
Console.WriteLine("Git的Clone完成。")
If isErr = True Then
Console.WriteLine("!!!但部分文件或文件夹没有移动成功,请手动将【GitCloneDownload】目录中的所有文件和文件夹剪切到外层文件夹!!!")
Console.WriteLine("!!!移动完成后再删除【GitCloneDownload】文件夹!!!")
Console.WriteLine("!!!全部完成后按按任意键继续...!!!")
Console.ReadKey()
Else
IO.Directory.Delete(Dir1 & "\GitCloneDownload", True)
End If
Exit Do
End If
ElseIf k.Key = ConsoleKey.Q Then
Console.WriteLine()
Console.WriteLine("你已选择退出...")
Return
Else
Console.WriteLine("无效输入,请重试...")
End If
Loop
End If
Console.WriteLine()
Dim B = IO.File.ReadAllBytes(FP)
Dim S = System.Text.Encoding.Default.GetString(B)
Dim IsRemote As Boolean = False
If S.Contains("[remote """) Then
IsRemote = True
Console.WriteLine("Git已设置远程服务器地址,改变将自动同步到服务器。")
Else
Console.WriteLine("Git仅本地环境。")
End If
Console.WriteLine()
Console.WriteLine("开始监听文件夹改变...")
Dim Queue_FSE As New Queue(Of FileSystemEventArgs)
Dim FSW As New FileSystemWatcher(Dir1)
AddHandler FSW.Changed, Sub(sender As Object, e As FileSystemEventArgs)
Queue_FSE.Enqueue(e)
End Sub
AddHandler FSW.Created, Sub(sender As Object, e As FileSystemEventArgs)
Queue_FSE.Enqueue(e)
End Sub
AddHandler FSW.Deleted, Sub(sender As Object, e As FileSystemEventArgs)
Queue_FSE.Enqueue(e)
End Sub
AddHandler FSW.Renamed, Sub(sender As Object, e As FileSystemEventArgs)
Queue_FSE.Enqueue(e)
End Sub
FSW.IncludeSubdirectories = True
FSW.EnableRaisingEvents = True
Dim List_EX As New List(Of String)
List_EX.Add(Path.Combine({Dir1, ".git"}).ToLower())
If IO.File.Exists(Dir1 & "\exclude.autogit") Then
Dim FS = System.Text.Encoding.Default.GetString(File.ReadAllBytes(Dir1 & "\exclude.autogit"))
Dim FSA = FS.Split(vbCrLf.ToArray)
For Each F In FSA
If F.Trim <> "" Then
List_EX.Add(Path.Combine({Dir1, F}).ToLower())
End If
Next
End If
Do
Threading.Thread.Sleep(500)
If Queue_FSE.Count > 0 Then
Threading.Thread.Sleep(1000)
Dim IsDo As Boolean = False
Do Until Queue_FSE.Count = 0
Dim FSE = Queue_FSE.Dequeue
Dim n = 0
For Each f In List_EX
If FSE.FullPath.ToLower.StartsWith(f) = False Then
n += 1
Else
Exit For
End If
Next
If n = List_EX.Count Then
IsDo = True
Exit Do
End If
Loop
If IsDo Then
Dim T = Now.ToString
Console.WriteLine(T & " 检测到目录改变,开始AutoGit...")
If List_EX.Count > 1 Then
Dim FA = Directory.GetFiles(Dir1)
Dim DA = Directory.GetDirectories(Dir1)
PSI.Arguments = "add"
For Each F In FA
F = F.ToLower
If List_EX.Contains(F) = False Then
PSI.Arguments &= " """ & Path.GetFileName(F) & """"
End If
Next
For Each D In DA
D = D.ToLower
If List_EX.Contains(D) = False Then
PSI.Arguments &= " """ & Path.GetFileName(D) & """"
End If
Next
Else
PSI.Arguments = "add ."
End If
Console.WriteLine(">Git " & PSI.Arguments)
Process.Start(PSI).WaitForExit()
Console.WriteLine("!Done")
PSI.Arguments = "commit -am ""AutoGit自动更新 " & Now.ToString & """"
PSI.WindowStyle = ProcessWindowStyle.Hidden
Console.WriteLine(">Git " & PSI.Arguments)
Dim P = Process.Start(PSI)
P.WaitForExit()
Console.WriteLine("!Done")
If IsRemote Then
PSI.Arguments = "push -f origin master"
Console.WriteLine(">Git " & PSI.Arguments)
Process.Start(PSI).WaitForExit()
Console.WriteLine("!Done")
End If
Threading.Thread.Sleep(1000)
Queue_FSE.Clear()
End If
End If
Loop
End Sub
End Module
使用方法:
在没有git管理的目录下运行 autogit (可以把此应用放在Windows目录下),如图:
选择初始化git管理到该目录,如有远程地址填写。
然后就开始autogit就开始监听此目录的改变,一旦保存就会出发commit和push到服务器。
下次在代码目录直接运行AutoGit即可。 I D:happymade
邮箱:366615@qq.com
申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。 注册成功!报告报道!
页:
[1]