nu_bridge是新唐的牛桥,借助该USB工具,pc端可以方便的调试外部的SPI, I2C设备。
新唐提供的驱动包中已经包含了winusb的驱动。
在测试下面的程序之前需要安装驱动。

这里是用vs2013 开发一个简单的winUSB控制台测试程序,帮助入门winUSB的API。
新建一个控制台工程:nu_bridge_simple

点击完成

添加文件:

文件:device.cpp

#include "pch.h"#include <SetupAPI.h>HRESULT
RetrieveDevicePath(_Out_bytecap_(BufLen) LPTSTR DevicePath,_In_                  ULONG  BufLen,_Out_opt_             PBOOL  FailureDeviceNotFound);HRESULT
OpenDevice(_Out_     PDEVICE_DATA DeviceData,_Out_opt_ PBOOL        FailureDeviceNotFound)
/*++Routine description:Open all needed handles to interact with the device.If the device has multiple USB interfaces, this function grants access toonly the first interface.If multiple devices have the same device interface GUID, there is noguarantee of which one will be returned.Arguments:DeviceData - Struct filled in by this function. The caller should use theWinusbHandle to interact with the device, and must pass the struct toCloseDevice when finished.FailureDeviceNotFound - TRUE when failure is returned due to no devicesfound with the correct device interface (device not connected, drivernot installed, or device is disabled in Device Manager); FALSEotherwise.Return value:HRESULT--*/
{HRESULT hr = S_OK;BOOL    bResult;DeviceData->HandlesOpen = FALSE;hr = RetrieveDevicePath(DeviceData->DevicePath,sizeof(DeviceData->DevicePath),FailureDeviceNotFound);if (FAILED(hr)) {return hr;}DeviceData->DeviceHandle = CreateFile(DeviceData->DevicePath,GENERIC_WRITE | GENERIC_READ,FILE_SHARE_WRITE | FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL);if (INVALID_HANDLE_VALUE == DeviceData->DeviceHandle) {hr = HRESULT_FROM_WIN32(GetLastError());return hr;}bResult = WinUsb_Initialize(DeviceData->DeviceHandle,&DeviceData->WinusbHandle);if (FALSE == bResult) {hr = HRESULT_FROM_WIN32(GetLastError());CloseHandle(DeviceData->DeviceHandle);return hr;}DeviceData->HandlesOpen = TRUE;return hr;
}VOID
CloseDevice(_Inout_ PDEVICE_DATA DeviceData)
/*++Routine description:Perform required cleanup when the device is no longer needed.If OpenDevice failed, do nothing.Arguments:DeviceData - Struct filled in by OpenDeviceReturn value:None--*/
{if (FALSE == DeviceData->HandlesOpen) {//// Called on an uninitialized DeviceData//return;}WinUsb_Free(DeviceData->WinusbHandle);CloseHandle(DeviceData->DeviceHandle);DeviceData->HandlesOpen = FALSE;return;
}
//下面的OSR_DEVICE_INTERFACE是从牛桥的pc端软件copy过来的
static const GUID OSR_DEVICE_INTERFACE ={ 0x1f4911f2, 0xc55d, 0x4561, { 0x98, 0x7a, 0xbc, 0xfa, 0x74, 0xd5, 0xbb, 0x6d } };HRESULT
RetrieveDevicePath(_Out_bytecap_(BufLen) LPTSTR DevicePath,_In_                  ULONG  BufLen,_Out_opt_             PBOOL  FailureDeviceNotFound)
/*++Routine description:Retrieve the device path that can be used to open the WinUSB-based device.If multiple devices have the same device interface GUID, there is noguarantee of which one will be returned.Arguments:DevicePath - On successful return, the path of the device (use with CreateFile).BufLen - The size of DevicePath's buffer, in bytesFailureDeviceNotFound - TRUE when failure is returned due to no devicesfound with the correct device interface (device not connected, drivernot installed, or device is disabled in Device Manager); FALSEotherwise.Return value:HRESULT--*/
{BOOL                             bResult = FALSE;HDEVINFO                         deviceInfo;SP_DEVICE_INTERFACE_DATA         interfaceData;PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;ULONG                            length;ULONG                            requiredLength=0;HRESULT                          hr;if (NULL != FailureDeviceNotFound) {*FailureDeviceNotFound = FALSE;}printf("RetrieveDevicePath \n");//// Enumerate all devices exposing the interface///*deviceInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBApplication1,NULL,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);*/deviceInfo = SetupDiGetClassDevs(&OSR_DEVICE_INTERFACE,NULL,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);if (deviceInfo == INVALID_HANDLE_VALUE) {hr = HRESULT_FROM_WIN32(GetLastError());return hr;}interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);//// Get the first interface (index 0) in the result set//bResult = SetupDiEnumDeviceInterfaces(deviceInfo,NULL,&OSR_DEVICE_INTERFACE,0,&interfaceData);if (FALSE == bResult) {//// We would see this error if no devices were found//if (ERROR_NO_MORE_ITEMS == GetLastError() &&NULL != FailureDeviceNotFound) {*FailureDeviceNotFound = TRUE;}hr = HRESULT_FROM_WIN32(GetLastError());SetupDiDestroyDeviceInfoList(deviceInfo);return hr;}//// Get the size of the path string// We expect to get a failure with insufficient buffer//bResult = SetupDiGetDeviceInterfaceDetail(deviceInfo,&interfaceData,NULL,0,&requiredLength,NULL);if (FALSE == bResult && ERROR_INSUFFICIENT_BUFFER != GetLastError()) {hr = HRESULT_FROM_WIN32(GetLastError());SetupDiDestroyDeviceInfoList(deviceInfo);return hr;}//// Allocate temporary space for SetupDi structure//detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LMEM_FIXED, requiredLength);if (NULL == detailData){hr = E_OUTOFMEMORY;SetupDiDestroyDeviceInfoList(deviceInfo);return hr;}detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);length = requiredLength;//// Get the interface's path string//bResult = SetupDiGetDeviceInterfaceDetail(deviceInfo,&interfaceData,detailData,length,&requiredLength,NULL);if(FALSE == bResult){hr = HRESULT_FROM_WIN32(GetLastError());LocalFree(detailData);SetupDiDestroyDeviceInfoList(deviceInfo);return hr;}//// Give path to the caller. SetupDiGetDeviceInterfaceDetail ensured// DevicePath is NULL-terminated.//hr = StringCbCopy(DevicePath,BufLen,detailData->DevicePath);LocalFree(detailData);SetupDiDestroyDeviceInfoList(deviceInfo);return hr;
}

其中下面这句话比较关键是和驱动配合使用的:

//下面的OSR_DEVICE_INTERFACE是从牛桥的pc端软件copy过来的
static const GUID OSR_DEVICE_INTERFACE ={ 0x1f4911f2, 0xc55d, 0x4561, { 0x98, 0x7a, 0xbc, 0xfa, 0x74, 0xd5, 0xbb, 0x6d } };

文件:device.h

//
// Define below GUIDs
//
#include <initguid.h>//
// Device Interface GUID.
// Used by all WinUsb devices that this application talks to.
// Must match "DeviceInterfaceGUIDs" registry value specified in the INF file.
// cce59234-f9f6-43c8-9007-a61e760fb59f
////DEFINE_GUID(GUID_DEVINTERFACE_USBApplication1,
//    0xcce59234,0xf9f6,0x43c8,0x90,0x07,0xa6,0x1e,0x76,0x0f,0xb5,0x9f);//下面这句话没有用到
DEFINE_GUID(GUID_DEVINTERFACE_USBApplication1,0x1f4911f2, 0xc55d, 0x4561, 0x98, 0x7a, 0xbc, 0xfa, 0x74, 0xd5, 0xbb, 0x6d);typedef struct _DEVICE_DATA {BOOL                    HandlesOpen;WINUSB_INTERFACE_HANDLE WinusbHandle;HANDLE                  DeviceHandle;TCHAR                   DevicePath[MAX_PATH];} DEVICE_DATA, *PDEVICE_DATA;HRESULT
OpenDevice(_Out_     PDEVICE_DATA DeviceData,_Out_opt_ PBOOL        FailureDeviceNotFound);VOID
CloseDevice(_Inout_ PDEVICE_DATA DeviceData);

文件:pch.h

#include <Windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <winusb.h>
#include <usb.h>#include "device.h"

将nu_bridge_simple.cpp中的所有内容删掉:
替换为如下内容:

// nu_bridge_simple.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"#include "pch.h"#include <stdio.h>LONG __cdecl
_tmain(
LONG     Argc,
LPTSTR * Argv
)
/*++Routine description:Sample program that communicates with a USB device using WinUSB--*/
{DEVICE_DATA           deviceData;HRESULT               hr;USB_DEVICE_DESCRIPTOR deviceDesc;BOOL                  bResult;BOOL                  noDevice;ULONG                 lengthReceived;UNREFERENCED_PARAMETER(Argc);UNREFERENCED_PARAMETER(Argv);//// Find a device connected to the system that has WinUSB installed using our// INF//hr = OpenDevice(&deviceData, &noDevice);if (FAILED(hr)) {if (noDevice) {printf("Device not connected or driver not installed\n");}else {printf("Failed looking for device, HRESULT 0x%x\n", hr);}return 0;}//// Get device descriptor//bResult = WinUsb_GetDescriptor(deviceData.WinusbHandle,USB_DEVICE_DESCRIPTOR_TYPE,0,0,(PBYTE)&deviceDesc,sizeof(deviceDesc),&lengthReceived);if (FALSE == bResult || lengthReceived != sizeof(deviceDesc)) {printf("Error among LastError %d or lengthReceived %d\n",FALSE == bResult ? GetLastError() : 0,lengthReceived);CloseDevice(&deviceData);return 0;}//// Print a few parts of the device descriptor//printf("Device found: VID_%04X&PID_%04X; bcdUsb %04X\n",deviceDesc.idVendor,deviceDesc.idProduct,deviceDesc.bcdUSB);getchar();CloseDevice(&deviceData);return 0;
}

添加完文件之后,需要添加库:

添加的库的名称是:
winusb.lib
setupapi.lib

将牛桥插入PC 的usb端口,然后编译程序,然后执行

运行效果如下:

RetrieveDevicePath
Device found: VID_0416&PID_3101; bcdUsb 0110

然后按下键盘任意键,退出程序。

参考内容:
1.How to Access a USB Device by Using WinUSB Functions
https://docs.microsoft.com/zh-cn/windows-hardware/drivers/usbcon/using-winusb-api-to-communicate-with-a-usb-device

2.Write a Windows desktop app based on the WinUSB template
https://docs.microsoft.com/zh-cn/windows-hardware/drivers/usbcon/how-to-write-a-windows-desktop-app-that-communicates-with-a-usb-device

3.How to Access a USB Device by Using WinUSB Functions
https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/using-winusb-api-to-communicate-with-a-usb-device

参考软件:

[0508] NuBridge SW/NuBridge.exe 源码 vs2008 MFC

继续:
将nu_bridge_simple.cpp中的所有内容删掉:
替换为如下内容:

// nu_bridge_simple.cpp : 定义控制台应用程序的入口点。
//
//#include "stdafx.h"#include "pch.h"#include <stdio.h>int NU_SetDeviceSpiMasteMode(_In_  WINUSB_INTERFACE_HANDLE InterfaceHandle)
{WINUSB_SETUP_PACKET SetupPacket;SetupPacket.RequestType = 0x42;SetupPacket.Request = 1;SetupPacket.Value = 0;SetupPacket.Index = 0;SetupPacket.Length = 0;WinUsb_ControlTransfer(InterfaceHandle, SetupPacket, 0, 0, NULL, 0);return 0;
}int NU_SetDeviceLED(_In_  WINUSB_INTERFACE_HANDLE InterfaceHandle)
{WINUSB_SETUP_PACKET SetupPacket;SetupPacket.RequestType = 0x40;SetupPacket.Request = 0;SetupPacket.Value = 0;SetupPacket.Index = 0;SetupPacket.Length = 0;printf("NU_SetDeviceLED\n");WinUsb_ControlTransfer(InterfaceHandle, SetupPacket, 0, 0, NULL, 0);return TRUE;
}BOOL GetUSBDeviceSpeed(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pDeviceSpeed)
{if (!pDeviceSpeed || hDeviceHandle == INVALID_HANDLE_VALUE){return FALSE;}BOOL bResult = TRUE;ULONG length = sizeof(UCHAR);bResult = WinUsb_QueryDeviceInformation(hDeviceHandle, DEVICE_SPEED, &length, pDeviceSpeed);if (!bResult){printf("Error getting device speed: %d.\n", GetLastError());goto done;}if (*pDeviceSpeed == LowSpeed){printf("Device speed: %d (Low speed).\n", *pDeviceSpeed);goto done;}if (*pDeviceSpeed == FullSpeed){printf("Device speed: %d (Full speed).\n", *pDeviceSpeed);goto done;}if (*pDeviceSpeed == HighSpeed){printf("Device speed: %d (High speed).\n", *pDeviceSpeed);goto done;}done:return bResult;
}struct PIPE_ID
{UCHAR  PipeInId;UCHAR  PipeOutId;
};BOOL QueryDeviceEndpoints(WINUSB_INTERFACE_HANDLE hDeviceHandle, PIPE_ID* pipeid)
{if (hDeviceHandle == INVALID_HANDLE_VALUE){return FALSE;}BOOL bResult = TRUE;USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;ZeroMemory(&InterfaceDescriptor, sizeof(USB_INTERFACE_DESCRIPTOR));WINUSB_PIPE_INFORMATION  Pipe;ZeroMemory(&Pipe, sizeof(WINUSB_PIPE_INFORMATION));bResult = WinUsb_QueryInterfaceSettings(hDeviceHandle, 0, &InterfaceDescriptor);if (bResult){for (int index = 0; index < InterfaceDescriptor.bNumEndpoints; index++){bResult = WinUsb_QueryPipe(hDeviceHandle, 0, index, &Pipe);if (bResult){if (Pipe.PipeType == UsbdPipeTypeControl){printf("Endpoint index: %d Pipe type: Control Pipe ID: %d.\n", index, Pipe.PipeType, Pipe.PipeId);}if (Pipe.PipeType == UsbdPipeTypeIsochronous){printf("Endpoint index: %d Pipe type: Isochronous Pipe ID: %d.\n", index, Pipe.PipeType, Pipe.PipeId);}if (Pipe.PipeType == UsbdPipeTypeBulk){if (USB_ENDPOINT_DIRECTION_IN(Pipe.PipeId)){printf("Endpoint index: %d Pipe type: Bulk Pipe ID: %c.\n", index, Pipe.PipeType, Pipe.PipeId);pipeid->PipeInId = Pipe.PipeId;}if (USB_ENDPOINT_DIRECTION_OUT(Pipe.PipeId)){printf("Endpoint index: %d Pipe type: Bulk Pipe ID: %c.\n", index, Pipe.PipeType, Pipe.PipeId);pipeid->PipeOutId = Pipe.PipeId;}}if (Pipe.PipeType == UsbdPipeTypeInterrupt){printf("Endpoint index: %d Pipe type: Interrupt Pipe ID: %d.\n", index, Pipe.PipeType, Pipe.PipeId);}}else{continue;}}}done:return bResult;
}BOOL SendDatatoDefaultEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle)
{if (hDeviceHandle == INVALID_HANDLE_VALUE){return FALSE;}BOOL bResult = TRUE;UCHAR bars = 0;WINUSB_SETUP_PACKET SetupPacket;ZeroMemory(&SetupPacket, sizeof(WINUSB_SETUP_PACKET));ULONG cbSent = 0;//Set bits to light alternate barsfor (short i = 0; i < 7; i += 2){bars += 1 << i;}//Create the setup packetSetupPacket.RequestType = 0;SetupPacket.Request = 0xD8;SetupPacket.Value = 0;SetupPacket.Index = 0;SetupPacket.Length = sizeof(UCHAR);bResult = WinUsb_ControlTransfer(hDeviceHandle, SetupPacket, &bars, sizeof(UCHAR), &cbSent, 0);if (!bResult){goto done;}printf("Data sent: %d \nActual data transferred: %d.\n", sizeof(bars), cbSent);done:return bResult;}BOOL NU_WritePipe(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID,UCHAR *buf, ULONG len)
{printf("NU_WritePipe\n");ULONG nBytesSent = 0;if (hDeviceHandle == INVALID_HANDLE_VALUE || !pID ){return FALSE;}nBytesSent = 0;WinUsb_WritePipe(hDeviceHandle, *pID, buf, len, &nBytesSent, 0);if (nBytesSent != len){return FALSE;}return TRUE;
}BOOL Nu_WriteCmd(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID)
{UCHAR data[] = { 0x01,0x01,0x53 ,0x01  ,0x00 ,0x00 ,0x08 ,0x06  ,0x90 ,0x00 ,0x00 ,0x00  ,0x00 ,0x00 ,0x50 };NU_WritePipe(hDeviceHandle, pID,data,15);UCHAR tag[] = { 0x00, 0x01 };NU_WritePipe(hDeviceHandle, pID, tag, 2);return TRUE;
}ULONG NU_ReadPipe(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID, UCHAR *buf, ULONG len)
{ULONG nBytesRead = 0;printf("NU_ReadPipe\n");WinUsb_ReadPipe(hDeviceHandle, *pID, (unsigned char*)buf, len, &nBytesRead, 0);return nBytesRead;
}BOOL Nu_ReadCmd(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID)
{   UCHAR data[64];int len;int i;memset(data, 0, 64);len = NU_ReadPipe(hDeviceHandle, pID, data,64);printf("Nu_ReadCmd len= %d\n", len);for (i = 0; i < len; i++){printf("%x,", data[i]);}printf("\n");return TRUE;
}BOOL NuWriteToBulkEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID, ULONG* pcbWritten)
{if (hDeviceHandle == INVALID_HANDLE_VALUE || !pID || !pcbWritten){return FALSE;}BOOL bResult = TRUE;UCHAR szBuffer[] = "Hello World";ULONG cbSize = strlen((const char *)szBuffer);ULONG cbSent = 0;bResult = WinUsb_WritePipe(hDeviceHandle, *pID, szBuffer, cbSize, &cbSent, 0);if (!bResult){goto done;}printf("Wrote to pipe %d: %s \nActual data transferred: %d.\n", *pID, szBuffer, cbSent);*pcbWritten = cbSent;done:return bResult;}BOOL WriteToBulkEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID, ULONG* pcbWritten)
{if (hDeviceHandle == INVALID_HANDLE_VALUE || !pID || !pcbWritten){return FALSE;}BOOL bResult = TRUE;UCHAR szBuffer[] = "Hello World";ULONG cbSize = strlen((const char *)szBuffer);ULONG cbSent = 0;bResult = WinUsb_WritePipe(hDeviceHandle, *pID, szBuffer, cbSize, &cbSent, 0);if (!bResult){goto done;}printf("Wrote to pipe %d: %s \nActual data transferred: %d.\n", *pID, szBuffer, cbSent);*pcbWritten = cbSent;done:return bResult;}BOOL ReadFromBulkEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID, ULONG cbSize)
{if (hDeviceHandle == INVALID_HANDLE_VALUE){return FALSE;}BOOL bResult = TRUE;UCHAR* szBuffer = (UCHAR*)LocalAlloc(LPTR, sizeof(UCHAR)*cbSize);ULONG cbRead = 0;bResult = WinUsb_ReadPipe(hDeviceHandle, *pID, szBuffer, cbSize, &cbRead, 0);if (!bResult){goto done;}printf("Read from pipe %d: %s \nActual data read: %d.\n", *pID, szBuffer, cbRead);done:LocalFree(szBuffer);return bResult;}int _tmain(int argc, _TCHAR* argv[])
{DEVICE_DATA           deviceData;HRESULT               hr;USB_DEVICE_DESCRIPTOR deviceDesc;BOOL                  noDevice;ULONG                 lengthReceived;BOOL bResult = TRUE;PIPE_ID PipeID;HANDLE hDeviceHandle = INVALID_HANDLE_VALUE;WINUSB_INTERFACE_HANDLE hWinUSBHandle = INVALID_HANDLE_VALUE;UCHAR DeviceSpeed;ULONG cbSize = 0;UNREFERENCED_PARAMETER(argc);UNREFERENCED_PARAMETER(argv);//// Find a device connected to the system that has WinUSB installed using our// INF//hr = OpenDevice(&deviceData, &noDevice);if (FAILED(hr)) {if (noDevice) {printf("Device not connected or driver not installed\n");}else {printf("Failed looking for device, HRESULT 0x%x\n", hr);}return 0;}hWinUSBHandle = deviceData.WinusbHandle;hDeviceHandle = deviceData.DeviceHandle;bResult = GetUSBDeviceSpeed(hWinUSBHandle, &DeviceSpeed);if(!bResult){goto done;}bResult = QueryDeviceEndpoints(hWinUSBHandle, &PipeID);if(!bResult){goto done;}#if 0bResult = NU_SetDeviceLED(hWinUSBHandle);if(!bResult){goto done;}
#endifprintf("PipeID.PipeInId  = %d\n", PipeID.PipeInId);printf("PipeID.PipeOutId = %d\n", PipeID.PipeOutId);NU_SetDeviceSpiMasteMode(hWinUSBHandle);Nu_WriteCmd(hWinUSBHandle, &PipeID.PipeOutId);Nu_ReadCmd(hWinUSBHandle, &PipeID.PipeInId);system("PAUSE");done:CloseHandle(hDeviceHandle);WinUsb_Free(hWinUSBHandle);return 0;
}

运行效果:

RetrieveDevicePath
Device speed: 1 (Low speed).
Endpoint index: 0 Pipe type: Bulk Pipe ID:
Endpoint index: 1 Pipe type: Bulk Pipe ID:
PipeID.PipeInId  = 132
PipeID.PipeOutId = 5
NU_WritePipe
NU_WritePipe
NU_ReadPipe
Nu_ReadCmd len= 10
1,0,6,0,ff,ff,ff,ff,51,14,
请按任意键继续. . .

End

vc2013 开发 winusb 简单测试程序 基于 nu_bridge相关推荐

  1. 一个基于Android开发的简单的音乐播放器

    一个基于Android开发的简单的音乐播放器 记得当时老师让我们写因为播放器时,脑子一头雾水,网上杂七杂八的资料也很少有用,因此索性就自己写一篇,希望对有缘人有用. 因为有好多人问我要源码,所以附上g ...

  2. 最简单DIY基于ESP8266的智能彩灯⑥(Android开发通过WIFI控制彩灯实现表白神器)

    ESP8266和ESP32智能彩灯开发系列文章目录 第一篇:最简单DIY基于ESP8266的智能彩灯①(在网页用按钮点亮普通RGB灯) 第二篇:最简单DIY基于ESP8266的智能彩灯②(在网页用按键 ...

  3. 基于JAVAvue开发一个简单音乐播放器计算机毕业设计源码+数据库+lw文档+系统+部署

    基于JAVAvue开发一个简单音乐播放器计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVAvue开发一个简单音乐播放器计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈: 项目 ...

  4. 通过Dapr实现一个简单的基于.net的微服务电商系统(十六)——dapr+sentinel中间件实现服务保护...

    dapr目前更新到了1.2版本,在之前4月份的时候来自阿里的开发工程师发起了一个dapr集成Alibaba Sentinel的提案,很快被社区加入到了1.2的里程碑中并且在1.2 release 相关 ...

  5. 主流WEB开发语言简单对比(转)

    主流WEB开发语言简单对比  原文链接:http://www.uml.org.cn/site/201401091.asp   随着时间的飞逝,随着岁月的流失.从世界上第一台计算机ENIAC诞生至今,已 ...

  6. 云如何让App开发更简单?

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 互联网"下半场",移动App开发对于质量.速度的要求更加苛刻.4月初,腾讯云正式上线移动开发平台MobileLine,借 ...

  7. Android开发环境简单配置

    为什么80%的码农都做不了架构师?>>>    ·         Android开发环境简单配置 写这个系列的原因也是因为自己对android比较感兴趣,而网上多数教程都是直接参照 ...

  8. 云开发太简单了吧!「72变的云开发」有奖征文领三重好礼!

    简介:想让你的应用成为几万个开发者的开发模版吗?云开发平台向腾云驾雾的程序员征集Serverless云开发的最佳实践,优秀的应用案例将成为云开发平台实验室的模版供大家体验,一键部署成为TA的应用.同时 ...

  9. 最简单的基于FFMPEG的视频编码器(YUV编码为H.264)

    ===================================================== 最简单的基于FFmpeg的视频编码器文章列表: 最简单的基于FFMPEG的视频编码器(YUV ...

  10. 通过Dapr实现一个简单的基于.net的微服务电商系统(十九)——分布式事务之Saga模式...

    目录: 一.通过Dapr实现一个简单的基于.net的微服务电商系统 二.通过Dapr实现一个简单的基于.net的微服务电商系统(二)--通讯框架讲解 三.通过Dapr实现一个简单的基于.net的微服务 ...

最新文章

  1. [深入学习C#]C#实现多线程的方式:使用Parallel类
  2. tradingview Vue
  3. Node.js进击基础一(5-5http知识填坑)
  4. 亚马逊ec2 实例删除_亚马逊免费使用套餐:在EC2 Linux实例上安装Tomcat 7
  5. violinplot如何看懂_一张图告诉你如何看懂个股大趋势
  6. SQL Identity自增列清零方法
  7. 循环控制-链表删除结点
  8. Element UI 官网以及其他技术文档
  9. 斐讯K1、K2、K2P 刷机、刷入Breed@重庆网吧电竞酒店维护小哥
  10. 2020-09-20
  11. c语言fprintf报错,C语言中printf,sprintf和fprintf的区别是什么
  12. 芒果tv官网服务器维护,芒果tv看不了【解决方案】
  13. Unity接入心知天气,获取当前城市天气状况
  14. 2009 中国七夕情人节 --期待
  15. SQL修改表信息规则-alter用法
  16. CCMP之播放列表(高仿千千静听)
  17. 怎么用计算机改变声音的音调,男声变女声用什么软件?能电脑语音说话变声吗?...
  18. struct 基本应用方法 及 题目常用使用形式详解
  19. 项目管理:如何制作项目进度计划表?
  20. yslow3.1.2_YSlow 2.0:最初的草图

热门文章

  1. 数学建模之数据比较与影响因素分析
  2. 规则引擎实现生产调度系统
  3. 数学建模:排队论模型
  4. win11配置jdk环境变量
  5. java中ejb项目_创建EJB项目
  6. linux mencoder 安装,Mencoder与X264安装
  7. php读取excel 报错_php读取excel文件
  8. mysql 查询分析器_MYSQL查询分析器工具
  9. 华中科技大学计算机作业试题,华中科技大学2009大学计算机基础考试试题A
  10. 怎么解决计算机键盘驱动,解决键盘失灵、安装更新键盘驱动方法