异或

异或(Exclusive OR,简称 XOR)是一种数学运算符,常用于逻辑运算与计算机中的位运算。当且仅当两个输入值不同时,异或运算输出为真(1),否则输出为假(0),即“同为 0,异为 1”。异或运算可以通过数学符号“⊕”表示, 具有交换律、结合律、恒等律等性质。 异或运算常见的应用包括奇偶校验、加法器设计、密码学中的加密与解密操作以及变量交换等。异或运算的一个重要特性是自反性:任何值与自身异或的结果为0,任何值与 0 异或的结果为其本身。 异或广泛应用于现代信息技术的多个领域,如数据加密、错误检测和纠正、图像处理等,尤其在数字电路设计与密码学中发挥着至关重要的作用。此外,异或运算在代数领域也扮演了关键角色。它所构成的系统是阿贝尔群, 与合取(AND)运算共同构成了著名的两元素域 F2,这是描述布尔函数的代数标准型的重要基础。 定义 异或是一个数学运算符,它应用于逻辑运算与计算机中的位运算。 令 p 和 q 为命题。p 和 q 的异或是这样一个命题:当p 和 q 中恰好只有一个为真时命题为真,否则为假。 p 异或 q 通常记作 p XOR q 或 p⊕ q。在编程语言中通常为 p^q。 如 p、q 两个值不相同,则异或结果为 1。如果 p、q 两个值相同,异或结果为 0,即异或的运算法则为:0 ⊕ 0 = 0,1 ⊕ 0 = 1,0 ⊕ 1 = 1,1 ⊕ 1 = 0(同为 0,异为 1)。这种运算捕捉了输入位的“排他性”,即输入不能同时为真。 异或也叫半加运算,其运算法则相当于不带进位的二进制加法:二进制下用1 表示真,0 表示假,这些法则与加法是相同的,只是不带进位,所以异或常被认作不进位加法。 应用 交换两个变量的值 int a int b a = a^b b = a^b a = a^b console.log(a) console.log(b)

2025年7月23日 · 1 分钟 · 81 字

git工作流

git clone // 到本地 git checkout -b xxx 切换至新分支xxx (相当于复制了remote的仓库到本地的xxx分支上 修改或者添加本地代码(部署在硬盘的源文件上) git diff 查看自己对代码做出的改变 git add 上传更新后的代码至暂存区 git commit 可以将暂存区里更新后的代码更新到本地git git push origin xxx 将本地的xxxgit分支上传至github上的git (如果在写自己的代码过程中发现远端GitHub上代码出现改变) git checkout main 切换回main分支 git pull origin master(main) 将远端修改过的代码再更新到本地 git checkout xxx 回到xxx分支 git rebase main 我在xxx分支上,先把main移过来,然后根据我的commit来修改成新的内容 (中途可能会出现,rebase conflict —–》手动选择保留哪段代码) git push -f origin xxx 把rebase后并且更新过的代码再push到远端github上 (-f —》强行) 原项目主人采用pull request 中的 squash and merge 合并所有不同的commit 远端完成更新后 git branch -d xxx 删除本地的git分支 git pull origin master 再把远端的最新代码拉至本地

2025年7月23日 · 1 分钟 · 72 字

树莓派wifi配置

wpa_supplicant.conf ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 country=CN network={ ssid=“cxy” psk=“cxy12345@2” key_mgmt=WPA-PSK }

2025年7月23日 · 1 分钟 · 10 字

特性和反射

以下是一个示例,展示了如何定义和使用特性,并使用反射来获取特性信息: using System; using System.Reflection; // 自定义特性类 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] class MyCustomAttribute : Attribute { public string Description { get; } public MyCustomAttribute(string description) { Description = description; } } // 带有特性的类 [MyCustom("This is a class attribute")] class MyClass { [MyCustom("This is a method attribute")] public void MyMethod() { Console.WriteLine("Hello from MyMethod"); } } class Program { static void Main() { // 使用反射获取类的特性 Type classType = typeof(MyClass); MyCustomAttribute[] classAttributes = (MyCustomAttribute[])classType.GetCustomAttributes(typeof(MyCustomAttribute), true); foreach (MyCustomAttribute attribute in classAttributes) { Console.WriteLine("Class Attribute: " + attribute.Description); } // 使用反射获取方法的特性 MethodInfo methodInfo = classType.GetMethod("MyMethod"); MyCustomAttribute[] methodAttributes = (MyCustomAttribute[])methodInfo.GetCustomAttributes(typeof(MyCustomAttribute), true); foreach (MyCustomAttribute attribute in methodAttributes) { Console.WriteLine("Method Attribute: " + attribute.Description); } // 等待用户输入,防止控制台窗口关闭 Console.ReadLine(); } } 在这个示例中,我们首先定义了一个自定义特性类 MyCustomAttribute,它继承自 Attribute。然后,我们在 MyClass 类和 MyMethod 方法上应用了 MyCustomAttribute 特性,并传入了相应的描述信息。 ...

2025年7月23日 · 1 分钟 · 136 字

Fetch、Ajax和Axios

Fetch、Ajax和Axios都是用于进行客户端和服务器之间的数据通信的工具,它们有一些区别: 语法和用法:Fetch是浏览器原生提供的API,使用起来相对较为简洁,基于Promise。它使用fetch()函数发送请求,并通过.then()方法处理响应。Ajax是一种基于XMLHttpRequest对象的技术,需要手动编写XHR对象的代码,并处理回调函数。而Axios是一个独立的第三方库,提供了更简洁的API,使用起来更加直观和方便。 跨域请求:Fetch在进行跨域请求时需要设置特定的HTTP头部信息,如Access-Control-Allow-Origin。Ajax在跨域请求时也需要设置相应的HTTP头部信息。Axios在默认情况下支持跨域请求,并且提供了更简单的配置选项来处理跨域请求。 功能和扩展性:Fetch提供了基本的请求和响应功能,但在处理复杂的请求和响应方面相对较为简单。Ajax相对于Fetch来说功能更为丰富,可以更灵活地处理请求和响应,还可以通过设置XHR对象的属性来实现更高级的功能。Axios提供了更丰富的功能,如拦截请求和响应、请求和响应的转换、取消请求等,并且支持Promise API,可以更好地处理异步操作。 浏览器兼容性:Fetch是浏览器原生提供的API,但在一些旧版本的浏览器中可能不支持。Ajax是一个较为传统的技术,几乎所有的浏览器都支持。Axios是一个独立的第三方库,可以在大多数现代浏览器中使用,但需要引入相应的库文件。 综上所述,Fetch是浏览器原生提供的API,语法简洁但功能相对较为基础;Ajax是一种传统的技术,功能丰富但使用稍显复杂;Axios是一个独立的第三方库,提供了简洁的API和丰富的功能,推荐在现代化的前端开发中使用。选择使用哪种工具取决于你的需求和项目的特定情况。

2025年7月23日 · 1 分钟 · 7 字

钩子在Win7下无效

最近工作需要,用到了鼠标钩子,并且还是全局鼠标钩子,也就是说,这个钩子监视系统所有消息,因此启动这个功能后,发现程序性能有点受影响,这也是正常的。 但是,原本在xp上运行好好的,放到win7上进行测试,发现过段时间,钩子会自动无效掉,这个时候去人工卸载钩子会弹出无效句柄错误消息(Error Code: 1404)。 这个问题类似指针,指针开始时分配了内存,但过段时间后,指针与该内存切断了联系,但指针指向的值并不是NULL,这个时候去卸载(delete)操作,则肯定是非法的。 所以,反复在网上查找相关的资料和论坛,发现大家都认为要么是win7下权限问题(UAC,管理员身份运行),或者是全局钩子与dl有关的影响,又或者是新版本.Net不支持全局钩子(因为我使用C#调用API),再或者是钩子句柄应该放在代码段区域(code_seg)等等。 最后在msdn论坛上找到了解答:(Hooking problem in Windows 7) http://social.msdn.microsoft.com/Forums/en-US/windowscompatibility/thread/f6032ca1-31b8-4ad5-be39-f78dd29952da 大概意思就是: Win7移除超时的钩子不是bug,而是win7中为了保护系统而故意的行为,因为安装了全局钩子后,所以消息都要经过这个钩子,并且等待钩子过程执行结束或者钩子达到超时时间才能处理其他的响应,严重影响性能。 其实在vista中已经加入了一些保护措施,但不是很充分,所以在win7加入了当底层钩子多次超时时,就由系统自动卸载掉该钩子。 所以,原因清楚了,方案有两个。 1.在win7系统中加入LowLevelHooksTimeout时间,如[HKEY_CURRENT_USER\Control Panel\Desktop]“LowLevelHooksTimeout”=dword:00002710 2.在安装钩子尽量在一个独立的线程中进行,并且钩子处理过程尽量用较短的时间,其他任何较长时间的处理都放在别的线程中异步处理。(尽量不要写花时间的hook代码) DWORD WINAPI mouseLLHookThreadProc(LPVOID lParam) { MSG msg; _hMouseLLHook = SetWindowsHookEx( WH_MOUSE_LL, .....); while(GetMessage(&msg, NULL, 0, 0) != FALSE) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }

2025年7月23日 · 1 分钟 · 44 字

什么是IntPtr

IntPtr是一种特殊的数据类型,它通常用于在编程语言中表示指针或句柄的整数值。“IntPtr"是"Integer Pointer"的缩写。 在许多编程语言中,指针是一种变量,它存储了内存地址的值,可以用来访问内存中的数据。然而,某些编程语言不直接支持指针,或者在特定的上下文中需要使用整数值来表示指针。这时,可以使用IntPtr类型来存储指针或句柄的整数值。 IntPtr类型的大小和表示方式取决于所使用的编程语言和平台。在一些编程语言中,IntPtr类型的大小与指针的大小相同,通常是与机器的字长相匹配的大小。在其他编程语言中,IntPtr类型可能会有固定的大小,无论平台的字长如何。 使用IntPtr类型时需要小心,因为它涉及到直接操作内存地址,可能引发安全和稳定性问题。在使用IntPtr类型时,应该遵循编程语言和平台的相关规范,并且谨慎处理指针操作,以避免潜在的错误和漏洞。 以下是一个示例,展示了如何使用 IntPtr 来处理指针操作: using System; class Program { static void Main() { // 创建一个 IntPtr 对象 IntPtr ptr; // 分配内存并获取指针 int size = sizeof(int); ptr = Marshal.AllocHGlobal(size); // 将值存储到指针指向的内存位置 int value = 42; Marshal.WriteInt32(ptr, value); // 从指针指向的内存位置读取值 int readValue = Marshal.ReadInt32(ptr); Console.WriteLine("Value read from pointer: " + readValue); // 释放分配的内存 Marshal.FreeHGlobal(ptr); // 等待用户输入,防止控制台窗口关闭 Console.ReadLine(); } } 在这个示例中,我们首先创建了一个 IntPtr 对象 ptr,然后使用 Marshal.AllocHGlobal 方法分配了一块内存,并将其指针存储在 ptr 中。然后,我们使用 Marshal.WriteInt32 方法将一个整数值存储到指针指向的内存位置。接下来,我们使用 Marshal.ReadInt32 方法从指针指向的内存位置读取值,并将其打印到控制台上。最后,我们使用 Marshal.FreeHGlobal 方法释放了分配的内存。 请注意,使用指针操作时需要小心,确保正确处理内存分配和释放,以避免内存泄漏和潜在的安全问题。

2025年7月23日 · 1 分钟 · 76 字

什么是S.O.L.I.D

S.O.L.I.D 是一個面向對象設計(Object-Oriented Design)的原則集合,它由五個原則組成,每個原則都代表著一個特定的設計原則,旨在幫助開發人員設計出易於擴展、可維護和可重用的軟件。 這些原則是: 單一職責原則(Single Responsibility Principle,SRP):一個類別應該只有一個職責,即只有一個引起它變化的原因。這樣可以使類別更加聚焦,易於理解、擴展和維護。 開放封閉原則(Open-Closed Principle,OCP):軟件實體(類別、模塊、函數等)應該對擴展是開放的,對修改是封閉的。這意味著當需求變化時,應該通過擴展現有代碼來實現變化,而不是修改現有代碼。 里氏替換原則(Liskov Substitution Principle,LSP):子類別應該能夠替換父類別,而不會影響程序的正確性。這意味著在使用繼承時,子類別應該遵守父類別的契約(即父類別定義的行為和屬性),並且不應該改變父類別的行為。 接口隔離原則(Interface Segregation Principle,ISP):用戶不應該強迫依賴它們不需要使用的接口。這意味著應該根據客戶端的需要,將大的接口拆分為更小的、特定的接口,從而避免不必要的依賴。 依賴反轉原則(Dependency Inversion Principle,DIP):高層模塊不應該依賴於低層模塊,它們都應該依賴於抽象。這意味著應該通過定義抽象接口或基類,讓高層模塊和低層模塊都依賴於這些抽象,從而實現模塊之間的解耦和可替換性。 遵循 S.O.L.I.D 原則可以幫助開發人員設計出高質量、可擴展和易於維護的軟件。

2025年7月23日 · 1 分钟 · 21 字

id还是code

背景 在系统设计时,经常会出现id,code的属性。这个标准是什么,如何使用,有规律吗? 譬如 下面举个例子仓库,有三个字段,用JSON表达如下 { id:5 code:"SH01" name:"上海昆山仓库" } 现在要建一个库存表,这时库存表里应该设计为增加仓库ID,还是仓库code? 本文结合自己的一些经验,归纳终结一下啊。有不同意见的,欢迎讨论。 生成方式 id 系统底层自动生成。一般是采用数据库自增和雪花算法,或者其他的变种。 而code的生成方式一般是手动输入,也有可能是业务层根据特定上下文维度来生成(譬如条码code = 款号code+颜色code+尺码code) 正因为id时底层内部行为,在创建时是无法指定或者推断的。而code是在外部确定传给该系统的。在分布式系统中通过这个code进行幂等性校验就天生的自然,并容易形成共识和规范。 数据类型 id的类型一般是整型或者长整形。并且大都是具备顺序行,或者类似顺序性。查询速度应该比较快,TODO testing code的类型一般是字符串。因为字符串的字面量的表现力时int无法比拟的。所以String类型的兼容性比id的int要好很多。你的系统的类型是可以确定的,但是你的数据来源有可能来源于外部的其他系统,这个时候使用String类型的code是个明智选择。 长度 id一般都非常长,使用上非常不方便。code 相对非常短。并且一般是有固定长度设定。方便对齐,沟通 可变性 id肯定是不可变的,一旦产生终身跟随,不可修改。 code也应该遵守这个规则。一定不可变。 大多数情况code也是如此,但是也有例外譬如user的code用什么,如果没有用户在注册时都输入了身份证,这个code就很完美,并且永远唯一。但是现实中这个是不现实的。如果可以用手机号码作为code吗,看上去可以。系统各处,系统间都用手机号码来标识用户,用于一旦换手机号码,历史数据就是个大坑。这种情况user就不能用手机号码来作为code。那该用那个字段作为code, 我的理解是没有。如果我们认定一个user是一个自然人,在我们系统没有任何确定的code来标识一个自然人,这个code就没法确定。 具备含义和功能 id是无意义的,当然一般具备一定的顺序性。 而code 时非常具备业务含义的,人看到code就会立即知道他们在具体指哪个东西。可用于交流沟通,文档存储,协议定义。外部系统通过这个code来标识具体要操作那个实体,进行系统间交互。 同时code可以增加校验位,拆解规则等来附带更多信息和功能。 业务稳定性 code具备非常好的业务稳定性,譬如对于外部系统上海昆山仓库编号无论系统如何改造,存储机制时什么,仓库编号都是固定和稳定的,都是SH01。 而id就不是这样。注意id是内部实现细节。 结论 在当前实体的设计时,要尽最大可能性的寻找到那个或者哪些字段可以逻辑上标识一个对象,重要的一点是一定是不可变的。如果有就定义这个字段为code, 或者这些字段计算或拼接产生出一个code。 并且其他实体对实体的关联都使用这个code,而不是id。与其他系统的API也使用code。为什么?因为code具备稳定性,有意义,方便沟通,可预先定义等优点。把这个id作为一个系统内部的实现隐藏起来。 例如库存表的就使用warehouse_code,而不是warehouse_id 如果实在找不到一个不可变的code。就退而求齐是。使用这个id 譬如user表没有code,只有userId, 并且其他系统也通过该userid进行沟通 BTW, 这里的code是个广义上的code,而不是说属性的名就是code, 建议在业务系统自定义个annotation(譬如@Code)来标识那个属性是code。

2025年7月23日 · 1 分钟 · 49 字

关于MQTT

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。 MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。 using MQTTnet; using MQTTnet.Client; private async Task Handle_Received_Application_Message() { var mqttFactory = new MqttFactory(); using (var mqttClient = mqttFactory.CreateMqttClient()) { var mqttClientOptions = new MqttClientOptionsBuilder() .WithTcpServer("192.168.106.76") .Build(); mqttClient.ApplicationMessageReceivedAsync += e => { string payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); HandlePayload(payload); return Task.CompletedTask; }; var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder() .WithTopicFilter(f => { f.WithTopic("fe-prod/sso2_burnin/v1/0c:b2:b7:ce:de:73/SSO2/all-data"); }) .WithTopicFilter(f => { f.WithTopic("fe-prod/sso2_burnin/v1/fc:69:47:b8:3a:54/SSO2/all-data"); }) .WithTopicFilter(f => { f.WithTopic("fe-prod/sso2_burnin/v1/24:76:25:e9:9b:73/SSO2/all-data"); }) .Build(); mqttClient.DisconnectedAsync += async e => { AddLog("Disconnected..."); await Task.Delay(1000); log.Error("连接已断开,尝试重新连接...", e.Exception); for (int i = 9; i > 0; i--) { AddLog($"Reconnect after {i}s..."); await Task.Delay(1000); } await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None); //if (e.ClientWasConnected) //{ // // Use the current options as the new options. // await mqttClient.ConnectAsync(mqttClient.Options); //} //else //{ // await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); // await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None); //} }; await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None); await mqttClient.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None); locks.WaitOne(); } } import paho.mqtt.client as mqtt # Successful Connection Callback def on_connect(client, userdata, flags, rc): print('Connected with result code '+str(rc)) client.subscribe('testtopic/#') # Message delivery callback def on_message(client, userdata, msg): print(msg.topic+" "+str(msg.payload)) client = mqtt.Client() # Set callback handler client.on_connect = on_connect client.on_message = on_message # Set up connection client.connect('broker.emqx.io', 1883, 60) # Publish message client.publish('emqtt',payload='Hello World',qos=0) client.loop_forever()

2025年7月23日 · 1 分钟 · 191 字