`
tyytzy
  • 浏览: 38365 次
  • 性别: Icon_minigender_1
  • 来自: 安徽
社区版块
存档分类
最新评论

WinSocket编程——原始套接字[转]

 
阅读更多

 

WinSocket编程——原始套接字[转]

分类: 网络编程技术 4088人阅读 评论(69) 收藏 举报

原始套接字是WINSOCK公开的一个套接字编程接口,它让我们可以在 IP 层对套接字进行编程,控制其行为,常见的应用有抓包 (Sniffer)、分析包、洪水攻击、ICMP ping等,但它不能截取包(所谓的截取包就是把包拦截下来,要做到这种“防火墙”的功能,还需要再低一层的驱动层才可以做到)。但是能把网络上的包复制到本机就已经是一个很有用的功能了。我就曾经试过在一个局域网里打开我的SNIFFER,然后把同事们电脑发出的包都复制过来了。然后如果再对包进行一些分析,哼哼。。。

其实原始套接字最根本的就是可以在IP层构造自己的IP包,然后把这个IP包发送出去。同样,我们可以把从TCP/UDP传输层过来的包抓取过来并进行分析。。。

要写原始套接字的程序其实也很容易,因为WINDOWS已经帮我们定义实现好了这些接口(WINSOCK)。另外我们还要有一些定义,就是IP包头、UDP包头等的那些结构定义,具体请查看下面的代码。

下面是我定义的一个RawSniffer类,这个类是使用了原始套接字来实现一个侦听器,这个类还依赖于MFC(我一直都在WINDOWS平台下开发,用的比较多的也是MFC,所以对MFC有点偏好。。。)。下面是类的代码:

// 头文件

#ifndef RAW_DEF_H
#define RAW_DEF_H

#include <winsock2.h> 
#pragma comment(lib,"ws2_32")

#include <ws2tcpip.h>
#include <mstcpip.h> // 此文件是 Windows platform SDK 的函数,如果找不到,请安装SDK

#define PROTOCOL_STRING_ICMP_TXT "ICMP"
#define PROTOCOL_STRING_TCP_TXT "TCP"
#define PROTOCOL_STRING_UDP_TXT "UDP"
#define PROTOCOL_STRING_SPX_TXT "SPX"
#define PROTOCOL_STRING_NCP_TXT "NCP"
#define PROTOCOL_STRING_UNKNOW_TXT "UNKNOW"

// 定义IP首部 
typedef struct ip_hdr 

 unsigned char h_verlen;   // 4位首部长度,4位IP版本号 
 unsigned char tos;    // 8位服务类型TOS 
 unsigned short total_len;       // 16位总长度(字节) 
 unsigned short ident;      // 16位标识 
 unsigned short frag_and_flags;  // 3位标志位 
 unsigned char ttl;       // 8位生存时间 TTL 
 unsigned char proto;      // 8位协议 (TCP, UDP 或其他) 
 unsigned short checksum;  // 16位IP首部校验和 
 unsigned int sourceIP;   // 32位源IP地址 
 unsigned int destIP;   // 32位目的IP地址 
}IPHEADER;

// 定义TCP伪首部 
typedef struct tsd_hdr 

 unsigned long saddr;    // 源地址 
 unsigned long daddr;    // 目的地址 
 char mbz;                        // 0
 char ptcl;       // 协议类型 UDP的协议类型为17,TCP为6 
 unsigned short tcpl;    // TCP数据包长度 
}PSDHEADER;

// 定义TCP首部 
typedef struct tcp_hdr 

 USHORT th_sport;     // 16位源端口 
 USHORT th_dport;     // 16位目的端口 
 unsigned int th_seq;    // 32位序列号 
 unsigned int th_ack;    // 32位确认号 
 unsigned char th_lenres;   // 4位首部长度/6位保留字 
 unsigned char th_flag;    // 6位标志位 
 USHORT th_win;      // 16位窗口大小 
 USHORT th_sum;      // 16位校验和 
 USHORT th_urp;      // 16位紧急数据偏移量 
}TCPHEADER;

// 定义ICMP首部
typedef struct icmp_hdr
{
 unsigned char  i_type;           // 类型
 unsigned char  i_code;           // 代码
 unsigned short i_cksum;          // 校验码
 unsigned short i_id;             // 非标准的ICMP首部  
 unsigned short i_seq;
 unsigned long  timestamp;
}ICMPHEADER;

// 定义UDP首部
// The UDP packet is lick this. Took from RFC768.
//                  0      7 8     15 16    23 24    31  
//                 +--------+--------+--------+--------+ 
//                 |     Source      |   Destination   | 
//                 |      Port       |      Port       | 
//                 +--------+--------+--------+--------+ 
//                 |                 |                 | 
//                 |     Length      |    Checksum     | 
//                 +--------+--------+--------+--------+ 
//                 |                                     
//                 |          data octets ...            
//                 +---------------- ...      

typedef struct udp_hdr  // 8 Bytes
{
 unsigned short uh_sport;         
 unsigned short uh_dport;
 unsigned short uh_len;
 unsigned short uh_sum;
} UDPHEADER;


/* 
// 函数实现不要放在头文件,否则会导致在不同的地方重复定义
//CheckSum:计算校验和的子函数 
USHORT checksum(USHORT *buffer, int size) 

 unsigned long cksum=0; 
 while(size >1) 
 { 
  cksum+=*buffer++; 
  size -=sizeof(USHORT); 
 } 
 if(size ) 
 { 
  cksum += *(UCHAR*)buffer; 
 } 
 
 cksum = (cksum >> 16) + (cksum & 0xffff); 
 cksum += (cksum >>16); 
 return (USHORT)(~cksum); 
}
*/

USHORT checksum(USHORT *buffer, int size);


// 回调函数

// 抓到一个包就会调用这个回调函数
typedef int (CALLBACK *CaptureDef)(CString  &strMsg);

class YRawSniffer
{
public:
 YRawSniffer();
 ~YRawSniffer();
 BOOL StartAll();
 BOOL ExitAll();
 BOOL Capture(CaptureDef CaptureFunc = NULL);
 BOOL StopCapture();

 static DWORD WINAPI CaptureThread(LPVOID lpParam);
 HANDLE m_hCaptureThread;

 // Filter 过滤条件
 BOOL m_bCapTCP;
 BOOL m_bCapUDP;
 BOOL m_bCapICMP;
 CString m_strSrcIP;
 CString m_strDstIP;
 
 SOCKET m_rawSock;
// CString m_strFilePath;

private:
 CaptureDef m_CaptureFunc;
 BOOL m_bExitCapture;
 
 IPHEADER m_ipHeader; 
 TCPHEADER m_tcpHeader;
 ICMPHEADER m_icmpheader;
 UDPHEADER m_udpheader;
};

#endif

// CPP 文件

#include "stdafx.h"
#include "RawDef.h"

//CheckSum:计算校验和的子函数 
USHORT checksum(USHORT *buffer, int size) 

 unsigned long cksum=0; 
 while(size >1) 
 { 
  cksum+=*buffer++; 
  size -=sizeof(USHORT); 
 } 
 if(size ) 
 { 
  cksum += *(UCHAR*)buffer; 
 } 
 
 cksum = (cksum >> 16) + (cksum & 0xffff); 
 cksum += (cksum >>16); 
 return (USHORT)(~cksum); 
}

char * GetProtocol(int proto)
{
 switch(proto)
 {
     case IPPROTO_ICMP: return PROTOCOL_STRING_ICMP_TXT;
  case IPPROTO_TCP:  return PROTOCOL_STRING_TCP_TXT;
  case IPPROTO_UDP:  return PROTOCOL_STRING_UDP_TXT;
  default:     return PROTOCOL_STRING_UNKNOW_TXT;
 }
}

DWORD WaitForObjectEx( HANDLE hHandle, DWORD dwMilliseconds )
{
 BOOL bRet;
 MSG msg;
 INT iWaitRet;
 DWORD nTimeOut = 0;
 while( (bRet = ::GetMessage( &msg, NULL, 0, 0 )) != 0)
 { 
  if( nTimeOut++ * 100 >= dwMilliseconds )
   break;

  iWaitRet = WaitForSingleObject(hHandle, 100);
  if(iWaitRet != WAIT_TIMEOUT)
  {
   break;
  }
  if (bRet == -1)
  {
   break;
  }
  else
  {
   ::TranslateMessage(&msg); 
   ::DispatchMessage(&msg); 
  }
 }

 return iWaitRet;
}

 


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
YRawSniffer *g_rawSniffer;

YRawSniffer::YRawSniffer()
{
 m_bCapTCP = FALSE;
 m_bCapUDP = FALSE;
 m_bCapICMP = FALSE;
 m_strSrcIP = "";
 m_strDstIP = "";

 m_rawSock = INVALID_SOCKET;
// m_strFilePath = "";

 m_bExitCapture = FALSE;
 m_CaptureFunc = NULL;
 m_hCaptureThread = NULL;

 g_rawSniffer = this;

 WSADATA wsaData;
 if(WSAStartup(MAKEWORD(2, 2), &wsaData)!=0)
 {
  TRACE1("WSAStartup() ERROR! %d", GetLastError());
  return;
 }

}

YRawSniffer::~YRawSniffer()
{
 WSACleanup(); 
}

BOOL YRawSniffer::ExitAll()
{
 m_bExitCapture = TRUE;

 shutdown(m_rawSock, SD_BOTH);
 
 if(m_hCaptureThread != NULL)
 {
  DWORD dwRet = 0;
  dwRet = WaitForObjectEx(m_hCaptureThread, INFINITE);
  if(dwRet == WAIT_OBJECT_0)
  {
   TRACE("CaptureThread exit Success!");
  }
  closesocket(m_rawSock);
  m_rawSock = INVALID_SOCKET;
  CloseHandle(m_hCaptureThread);
  m_hCaptureThread = NULL;
 }

 TRACE("ExitAll OK!");

 return TRUE;
}

BOOL YRawSniffer::StartAll()
{
 m_bExitCapture = FALSE;

 SOCKADDR_IN addr_in;

 if(m_rawSock == INVALID_SOCKET)
  m_rawSock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);

    BOOL flag = TRUE;

 if(setsockopt(m_rawSock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)) != 0)
 {
        TRACE1("setsockopt() ERROR! %d", WSAGetLastError());
  return FALSE;
 }
 
 char  LocalName[16];
 struct hostent *pHost;

 // 获取本机名 
 if (gethostname((char*)LocalName, sizeof(LocalName)-1) == SOCKET_ERROR) 
 {
  TRACE1("gethostname error! %d", WSAGetLastError());
  return FALSE;
 }
 
 // 获取本地 IP 地址 
 if ((pHost = gethostbyname((char*)LocalName)) == NULL) 
 {
  TRACE1("gethostbyname error! %d", WSAGetLastError());
  return FALSE;
 }
 
 // m_strSrcIP = pHost->h_addr_list[0];
 addr_in.sin_addr  = *(in_addr *)pHost->h_addr_list[0]; // IP 
 addr_in.sin_family = AF_INET; 
 addr_in.sin_port  = htons(57274);
 
 if( bind(m_rawSock, (struct sockaddr *)&addr_in, sizeof(addr_in)) != 0)
 {
  TRACE1("bind error! %d", WSAGetLastError());
  return FALSE;
 }
 
 // 设置网卡的I/O行为,接收网络上所有的数据包
 DWORD dwValue = 1; 
 if( ioctlsocket(m_rawSock, SIO_RCVALL, &dwValue) != 0)
 {
  TRACE1("ioctlsocket error! %d", WSAGetLastError());
  return FALSE;
 } 

 return TRUE;
}

DWORD WINAPI YRawSniffer::CaptureThread(LPVOID lpParam)
{
 //CFile fLog;
 //BOOL bLogFile = FALSE;
 // 打开记录文件
 //if(g_rawSniffer->m_strFilePath == "")
 // g_rawSniffer->m_strFilePath = "c://Capture.txt";
 //if(g_rawSniffer->m_strFilePath != "")
// {
//  if( !fLog.Open(g_rawSniffer->m_strFilePath, CFile::modeCreate|CFile::modeReadWrite) )
//   TRACE1("file fLog Open failed! %d", GetLastError());
//  else
//   bLogFile = TRUE;
// }

 const int MAX_RECEIVEBUF = 1000;
 char recvBuf[MAX_RECEIVEBUF] = {0};
 char msg[MAX_RECEIVEBUF] = {0};

 char *ptr = NULL;

 CString strLog, strTmp, strContent;

 DWORD nTCPCnt = 0, nUDPCnt = 0, nICMPCnt = 0;

 while(!g_rawSniffer->m_bExitCapture)
 {
  int ret = recv(g_rawSniffer->m_rawSock, recvBuf, MAX_RECEIVEBUF, 0);
  if(ret == SOCKET_ERROR)
   TRACE1("%d, recv(g_rawSniffer->m_rawSock, recvBuf, MAX_RECEIVEBUF, 0) failed!", GetLastError());
  
  strLog = "";
  strContent = "";

  if(ret > 0)
  {   
   g_rawSniffer->m_ipHeader = *(IPHEADER*)recvBuf;
            
   // 取得正确的IP头长度
   int iIphLen = sizeof(unsigned long) * (g_rawSniffer->m_ipHeader.h_verlen & 0xf);
   int cpysize = 0;

   // 过滤目标IP或者源IP
   //if(g_rawSniffer->m_strSrcIP.Find(".") > 0 
   // || g_rawSniffer->m_strDstIP.Find(".") > 0)
   {
    if(g_rawSniffer->m_strSrcIP != "" 
     || g_rawSniffer->m_strDstIP != "")
    {
     if( inet_ntoa(*(in_addr*)&g_rawSniffer->m_ipHeader.sourceIP) != g_rawSniffer->m_strSrcIP
      && inet_ntoa(*(in_addr*)&g_rawSniffer->m_ipHeader.destIP) != g_rawSniffer->m_strDstIP)
      continue;
    }
   }

   /*
   // 过滤目标IP或者源IP
   if(g_rawSniffer->m_strSrcIP != "")
   {
    if( inet_ntoa(*(in_addr*)&g_rawSniffer->m_ipHeader.sourceIP) != g_rawSniffer->m_strSrcIP)
     continue;
   }

   if(g_rawSniffer->m_strDstIP != "")
   {
    if( inet_ntoa(*(in_addr*)&g_rawSniffer->m_ipHeader.destIP) != g_rawSniffer->m_strDstIP)
     continue;
   }
   */
   
   if(g_rawSniffer->m_ipHeader.proto == IPPROTO_TCP && g_rawSniffer->m_bCapTCP)
   {
    nTCPCnt++;
    g_rawSniffer->m_tcpHeader = *(TCPHEADER*)(recvBuf + iIphLen);
    strTmp.Format("取得 %d TCP包", nTCPCnt); strLog += strTmp;
    strTmp.Format("协议: %s /r/n", GetProtocol(g_rawSniffer->m_ipHeader.proto)); strLog += strTmp;
    strTmp.Format("IP源地址: %s /r/n", inet_ntoa(*(in_addr*)&g_rawSniffer->m_ipHeader.sourceIP)); strLog += strTmp;
    strTmp.Format("IP目标地址: %s /r/n", inet_ntoa(*(in_addr*)&g_rawSniffer->m_ipHeader.destIP)); strLog += strTmp;
    strTmp.Format("TCP源端口号: %d /r/n", g_rawSniffer->m_tcpHeader.th_sport); strLog += strTmp;
    strTmp.Format("TCP目标端口号:%d /r/n", g_rawSniffer->m_tcpHeader.th_dport); strLog += strTmp;
    strTmp.Format("数据包长度: %d /r/n", ntohs(g_rawSniffer->m_ipHeader.total_len)); strLog += strTmp;
    strTmp.Format("TCP数据包的报文内容:/r/n"); strLog += strTmp;
    
    ptr = recvBuf + iIphLen + (4 * ((g_rawSniffer->m_tcpHeader.th_lenres & 0xf0)>>4|0));
    cpysize = ntohs(g_rawSniffer->m_ipHeader.total_len) - (iIphLen + (4 * ((g_rawSniffer->m_tcpHeader.th_lenres & 0xf0)>>4|0)));
    
    // ASCII码
    memcpy(msg, ptr, cpysize);
    for(int i = 0; i < cpysize ; i++)
    {
     if(msg[i] >= 32 && msg[i] < 255)
     {
      strContent.Format("%c", (unsigned char)msg[i]); strLog += strContent;
     }
     else
     {
      strContent.Format("."); strLog += strContent;
     }
    }
    strTmp.Format("/r/n /r/n"); strLog += strTmp;
   }
   
   
   if(g_rawSniffer->m_ipHeader.proto == IPPROTO_ICMP  && g_rawSniffer->m_bCapICMP)
   {
    nICMPCnt++;
    g_rawSniffer->m_icmpheader = *(ICMPHEADER*)(recvBuf + iIphLen);
    strTmp.Format("取得 %d ICMP包", nICMPCnt); strLog += strTmp;
    strTmp.Format("协议: %s/r/n", GetProtocol(g_rawSniffer->m_ipHeader.proto)); strLog += strTmp;
    strTmp.Format("IP源地址: %s/r/n", inet_ntoa(*(in_addr*)&g_rawSniffer->m_ipHeader.sourceIP)); strLog += strTmp;
    strTmp.Format("IP目标地址: %s/r/n", inet_ntoa(*(in_addr*)&g_rawSniffer->m_ipHeader.destIP)); strLog += strTmp;
    strTmp.Format("ICMP返回类型:%d/r/n", g_rawSniffer->m_icmpheader.i_type); strLog += strTmp;
    strTmp.Format("ICMP返回代码:%d/r/n", g_rawSniffer->m_icmpheader.i_code); strLog += strTmp;
    strTmp.Format("数据包长度: %d/r/n/r/n/r/n", ntohs(g_rawSniffer->m_ipHeader.total_len)); strLog += strTmp;    
   }
  
   if(g_rawSniffer->m_ipHeader.proto == IPPROTO_UDP && g_rawSniffer->m_bCapUDP)
   {
    nUDPCnt++;
    g_rawSniffer->m_udpheader = *(UDPHEADER*)(recvBuf + iIphLen);
    strTmp.Format("取得 %d UDP包", nUDPCnt); strLog += strTmp;
    strTmp.Format("协议: %s/r/n", GetProtocol(g_rawSniffer->m_ipHeader.proto)); strLog += strTmp;
    strTmp.Format("IP源地址: %s/r/n", inet_ntoa(*(in_addr*)&g_rawSniffer->m_ipHeader.sourceIP)); strLog += strTmp;
    strTmp.Format("IP目标地址: %s/r/n", inet_ntoa(*(in_addr*)&g_rawSniffer->m_ipHeader.destIP)); strLog += strTmp;
    strTmp.Format("UDP源端口号: %d/r/n", g_rawSniffer->m_udpheader.uh_sport); strLog += strTmp;
    strTmp.Format("UDP目标端口号:%d/r/n", g_rawSniffer->m_udpheader.uh_dport); strLog += strTmp;
    strTmp.Format("数据包长度: %d/r/n", ntohs(g_rawSniffer->m_ipHeader.total_len)); strLog += strTmp;
    strTmp.Format("UDP数据包的报文内容:/r/n"); strLog += strTmp;
    
    ptr = recvBuf + iIphLen + 8;
    cpysize = ntohs(g_rawSniffer->m_ipHeader.total_len) - (iIphLen + 8);
    memcpy(msg, ptr, cpysize);
    
    strTmp.Format("ASCII码格式: /r/n");
    for(int i = 0; i < cpysize; i++)
    {
     if(msg[i] >= 32 && msg[i] < 255)
     {
      strContent.Format("%c",(unsigned char)msg[i]); strLog += strContent;
     }
     else
     {
      strContent.Format("."); strLog += strContent;
     }
    }
    strTmp.Format("/r/n/r/n");  strLog += strTmp;    
    
    strTmp.Format("16进制码格式: /r/n");  strLog += strTmp;
    for(i = 0; i < cpysize; i++)
    {
     strTmp.Format("%2.2X ", (unsigned char)msg[i]);  strLog += strTmp;
    }
    strTmp.Format("/r/n/r/n");  strLog += strTmp;
    
   }

   if(g_rawSniffer->m_CaptureFunc != NULL && strLog.GetLength() > 0 && strContent.GetLength() > 0)
    g_rawSniffer->m_CaptureFunc(strLog);

   Sleep(10);
  }
 }


 // 关闭记录文件
// if(bLogFile)
//  fLog.Close(); 

 return 0;
}

BOOL YRawSniffer::Capture(CaptureDef CaptureFunc /*= NULL*/)
{
 StartAll();

 if(CaptureFunc != NULL)
  m_CaptureFunc = CaptureFunc;

 // 创建线程截取包
 m_bExitCapture = FALSE;
 m_hCaptureThread = CreateThread(NULL, 0, CaptureThread, NULL, 0, NULL);
 if(NULL == m_hCaptureThread)
  TRACE1(" /"m_hCaptureThread = CreateThread(NULL, 0, CaptureThread, NULL, 0, NULL)/" failed! %d ", GetLastError());

 return TRUE;
}

BOOL YRawSniffer::StopCapture()
{
 return ExitAll();
}

这个类的使用很简单,声明一个全局的对象(或者成员变量),使用它的Capture和StopCapture就可以了。记得在程序退出的时候也调用一下StopCapture。

调用Capture 函数的时候,需要把一些过滤条件赋给它:

  // 过滤条件
  g_sniffer.m_bCapTCP = m_bCapTCP; // 抓TCP包,TRUE为抓,FALSE不抓
  g_sniffer.m_bCapUDP = m_bCapUDP; // 抓UDP包,TRUE为抓,FALSE不抓
  g_sniffer.m_bCapICMP = m_bCapICMP; // 抓ICMP包,TRUE为抓,FALSE不抓
  g_sniffer.m_strSrcIP = m_strSrcIP; // 包的源IP串,空为不限制
  g_sniffer.m_strDstIP = m_strDstIP; // 包的目标IP串,空为不限制

  g_sniffer.Capture(CapFunc);

抓到的包会在一个回调函数中把抓到的包格式化好了传给你。

例如我的回调函数是这样的:

int CALLBACK CapFunc(CString &strLog)
{
 g_rawDlg->AddLog(strLog); // 把抓到的包在DLG的一个编辑框里输出
 g_log.WriteLogFileRaw(strLog); // 写进一个LOG文件里

 return 0;
}

有了上面的这些知识就可以使用这个类实现一个SNIFFER了,很简单的3步:1、把类加进工程 2、包含头文件,声明对象 3、使用这个对象的Capture和StopCapture。

上面还可以看出我原来的设计是把记录包的功能放在了类里。但是后面觉得这个类还是不要干那么多的活,让记录包的工作都放在上层吧。所以就用了回调函数。

通过上面代码的研究,你应该很明白原始套接字了吧,这项技术不但可以做SNIFFER,还可以实现洪水攻击等等(因为可以自己构造IP包)。

最后给出我使用这个类实现的一个程序界面,当然界面那块的逻辑需要你自己去处理了,需要的朋友请留下地址,我把例程发给你。

That's all, Happy every day! 

分享到:
评论

相关推荐

    winsocket 聊天程序

    当有客户端连接时,服务器接受连接并为每个客户端创建一个新的套接字进行通信。 4. **客户端实现**:客户端首先需要连接到服务器的指定地址和端口。连接成功后,可以发送消息并接收服务器的回应。 5. **多线程处理...

    易语言Winsocket模块源码-易语言

    Winsock是Windows操作系统上的一个API,它提供了与TCP/IP协议栈的接口,使得程序员可以通过标准的套接字(socket)编程模型进行网络通信。这个模块是易语言为了支持网络编程而设计的,通过它,开发者可以构建客户端...

    hhhhh安卓开发教程大全

    hhhhh安卓开发教程大全

    avem-labs_Avem_1740990015.zip

    avem-labs_Avem_1740990015.zip

    25883-mofangmall.com 微信群管理机器人系统网站.zip

    微信群机器人管理系统源码 微信群机器人管理系统源码 支持同登陆多个微信 源码类型: C/S 开发环境: VS2010 SQL2008R2 菜单功能 1、支持同时登录多个微信 2、支持机器人聊天(笑话,成语接龙、故事会、智力等等) 3、支持签到 4、可自定义回复 5、可自定义红包语 6、支持定期发送公告(如群规,广告)等 1、WeChatRobots后台配置web版 2、数据库在WeiChartGroup.Net/app_data中,附加即可

    https://upload.csdn.net/creation/uploadResources?spm=1003.2018.3001.4314

    https://upload.csdn.net/creation/uploadResources?spm=1003.2018.3001.4314

    名字微控制器_STM32_课程_DeepBlue_1740989720.zip

    名字微控制器_STM32_课程_DeepBlue_1740989720.zip

    S7-200Smart恒压供水程序示例与485通讯实践:操作指南与案例解析,S7-200 Smart可编程控制器恒压供水程序设计与实现,附带485通讯范例,S7-200Smart 恒压供水程序样例+4

    S7-200Smart恒压供水程序示例与485通讯实践:操作指南与案例解析,S7-200 Smart可编程控制器恒压供水程序设计与实现,附带485通讯范例,S7-200Smart 恒压供水程序样例+485通讯样例 ,S7-200Smart; 恒压供水程序样例; 485通讯样例,S7-200Smart程序样例:恒压供水及485通讯应用示例

    Java读写Mifare M1卡IC卡源码

    Java使用JNA、JNI两种不同方式调用DLL、SO动态库方式读写M1卡源码,支持读写M1卡扇区数据、修改IC卡扇区密钥、改写UID卡卡号等功能,支持Windows系统,同时支持龙芯Mips、LoongArch、海思麒麟鲲鹏飞腾Arm、海光兆芯x86_Amd64等架构平台的国产统信、麒麟等Linux系统,内有jna-4.5.0.jar包,vx13822155058 qq954486673

    UDP协议接收和发送数据示例JAVA

    UDP协议接收和发送数据示例JAVA

    VU-DBS项目:深脑刺激器的全程辅助

    本文介绍了范德堡大学深脑刺激器(DBS)项目,该项目旨在开发和临床评估一个系统,以辅助从规划到编程的整个过程。DBS是一种高频刺激治疗,用于治疗运动障碍,如帕金森病。由于目标区域在现有成像技术中可见性差,因此DBS电极的植入和编程过程复杂且耗时。项目涉及使用计算机辅助手术技术,以及一个定制的微定位平台(StarFix),该平台允许在术前进行图像采集和目标规划,提高了手术的精确性和效率。此外,文章还讨论了系统架构和各个模块的功能,以及如何通过中央数据库和网络接口实现信息共享。

    图像识别项目源码资源(Python和C++)

    图像识别”项目源码资源(Python和C++)

    虚拟同步电机与并电网模型的Simulink仿真参数配置与直接使用指南,虚拟同步电机与并电网模型的Simulink仿真:参数齐全,直接使用,同步电机simulink仿真 并电网模型仿真 参数设置好了

    虚拟同步电机与并电网模型的Simulink仿真参数配置与直接使用指南,虚拟同步电机与并电网模型的Simulink仿真:参数齐全,直接使用,同步电机simulink仿真 并电网模型仿真 参数设置好了,可直接使用 ,虚拟同步电机; simulink仿真; 并电网模型仿真; 参数设置; 使用,虚拟同步电机Simulink仿真与并电网模型参数化应用

    三菱FX3U与力士乐VFC-x610变频器通讯案例详解:PLC控制下的变频器操作与设置程序,含接线方式及昆仑通态触摸屏操作指南,三菱FX3U与力士乐VFC-x610变频器通讯案例详解:接线、设置与程序

    三菱FX3U与力士乐VFC-x610变频器通讯案例详解:PLC控制下的变频器操作与设置程序,含接线方式及昆仑通态触摸屏操作指南,三菱FX3U与力士乐VFC-x610变频器通讯案例详解:接线、设置与程序注解,实现频率设定、启停控制与实时数据读取功能。,三菱FX3U与力士乐VFC-x610变频器通讯程序三菱FX3U与力士乐VFC-x610变频器通讯案例程序,有注释。 并附送程序,有接线方式,设置。 器件:三菱FX3U的PLC,力士乐VFCx610变频器,昆仑通态,威纶通触摸屏。 功能:实现频率设定,启停控制,实际频率读取等。 ,三菱FX3U;力士乐VFC-x610变频器;通讯程序;案例程序;注释;接线方式;设置;频率设定;启停控制;实际频率读取;昆仑通态;威纶通触摸屏。,三菱FX3U与力士乐VFC-x610变频器通讯程序及案例:频率控制与读取实践

    xmselect测试用例~~~~~~~~~~~~~~

    xmselect测试用例~~~~~~~~~~~~~~

    Unity-游戏开发-模型资源-科幻武器

    总共包含 32 款 AAA 级科幻武器。四种武器类型,每种有 8 种不同的纹理变化! 所有内容均采用 PBR 材质,可直接用于开发游戏!

    python词云生成器,将txt文本自动分割生成词云图

    python词云生成器,将txt文本自动分割生成词云图

    基于物联网智能化平台的智慧园区解决方案PPT(28页).pptx

    智慧园区,作为现代城市发展的新形态,旨在通过高度集成的信息化系统,实现园区的智能化管理与服务。该方案提出,利用智能手环、定制APP、园区管理系统及物联网技术,将园区的各类设施与设备紧密相连,形成一个高效、便捷、安全的智能网络。从智慧社区到智慧酒店,从智慧景区到智慧康养,再到智慧生态,五大应用板块覆盖了园区的每一个角落,为居民、游客及工作人员提供了全方位、个性化的服务体验。例如,智能手环不仅能实现定位、支付、求助等功能,还能监测用户健康状况,让科技真正服务于生活。而智慧景区的建设,更是通过大数据分析、智能票务、电子围栏等先进技术,提升了游客的游玩体验,确保了景区的安全有序。 尤为值得一提的是,方案中的智慧康养服务,展现了科技对人文关怀的深刻体现。通过智慧手环与传感器,自动感知老人身体状态,及时通知家属或医疗机构,有效解决了“空巢老人”的照护难题。同时,智慧生态管理系统的应用,实现了对大气、水、植被等环境要素的实时监测与智能调控,为园区的绿色发展提供了有力保障。此外,方案还提出了建立全域旅游营销平台,整合区域旅游资源,推动旅游业与其他产业的深度融合,为区域经济的转型升级注入了新的活力。 总而言之,这份智慧园区建设方案以其前瞻性的理念、创新性的技术和人性化的服务设计,为我们展示了一个充满智慧与活力的未来园区图景。它不仅提升了园区的运营效率和服务质量,更让科技真正融入了人们的生活,带来了前所未有的便捷与舒适。对于正在规划或实施智慧园区建设的决策者而言,这份方案无疑提供了一份宝贵的参考与启示,激发了他们对于未来智慧生活的无限遐想与憧憬。

    使用 SignalR 在 .NET Core 8 最小 API 中构建实时通知

    使用 SignalR 在 .NET Core 8 最小 API 中构建实时通知,构建实时应用程序已成为现代 Web 开发中必不可少的部分,尤其是对于通知、聊天系统和实时更新等功能。SignalR 是 ASP.NET 的一个强大库,可实现服务器端代码和客户端 Web 应用程序之间的无缝实时通信。 参考文章:https://blog.csdn.net/hefeng_aspnet/article/details/145990801

    自适应网址导航网站发布页单页网页模板html源码

    自适应网址导航网站发布页单页网页模板html源码,超级好看自适应清新网址导航网站发布页单页网页模板html源码!无论电脑还是手机,这是一个网页单页源码!! 模板无后台模板,无需数据库,上传服务器直接能用。

Global site tag (gtag.js) - Google Analytics