nodejs调用c++开发windows网络抓包工具

由于node接口有限,一些网络基层操作还得依靠c++来, 可能也是为了避免大家那么卷而选择保护大家吧,不说二话,咱直接上代码。下面会附上node调用c++的教程

node代码

let Pcap = require('./build/Release/Pcap.node')

let Capture = new Pcap.Capture()

Capture.Start({
  OnRecv: function( buffer ) {
    let bytes = []
    for (let index = 0; index < buffer.length; index++) {
      let element = buffer[index]
      if ( buffer[index] < 0 ) {
        element = 256 + element
      }

      bytes.push( element );
    }
  }
}

capture.h

#ifndef CAPTURE_H
#define CAPTURE_H

#include <napi.h>
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mstcpip.h>
#include <comdef.h>

#pragma comment(lib, "ws2_32.lib")

class Capture : public Napi::ObjectWrap<Capture> {
 public:
  static Napi::Object Init(Napi::Env env, Napi::Object exports);
  Capture(const Napi::CallbackInfo& info);

 private:
  void Start(const Napi::CallbackInfo& info);
};

#endif

capture.cc

#include "capture.h"

int log(std::string str) {
	int lastError = WSAGetLastError();
	LPTSTR lpMsgBuf;
	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
		FORMAT_MESSAGE_FROM_SYSTEM |
		FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		lastError,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		(LPTSTR)&lpMsgBuf,
		0, NULL) != 0) {
		// 输出错误信息
		std::cout << str << "[" << lastError << "]" << (char*)_bstr_t(lpMsgBuf) << std::endl;
		LocalFree(lpMsgBuf);
	}
	return lastError;
}

Napi::Object Capture::Init(Napi::Env env, Napi::Object exports) {
  Napi::Function func = DefineClass(env, "Capture", {
    InstanceMethod("Start", &Capture::Start),
  });

  Napi::FunctionReference* constructor = new Napi::FunctionReference();
  *constructor = Napi::Persistent(func);
  env.SetInstanceData(constructor);

  exports.Set("Capture", func);
  return exports;
}



Capture::Capture(const Napi::CallbackInfo& info) : Napi::ObjectWrap<Capture>(info) {
}


void Capture::Start(const Napi::CallbackInfo& info) {
  	WSADATA wsa;
	int errror;
	if (errror = WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
		log("WSAStartup: ");
	}

	char name[100];
	gethostname(name, sizeof(name));

	struct addrinfo *result = NULL, *ptr = NULL, hints;

	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_RAW;
	hints.ai_protocol = IPPROTO_IP;

	if (errror = getaddrinfo(name, 0, &hints, &result) != 0) {
		std::cout << errror << std::endl;
		log("getaddrinfo: ");
		WSACleanup();
	}

	SOCKET rawSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
	if (rawSocket == INVALID_SOCKET) {
		std::cout << rawSocket << std::endl;
		log("socket: ");
		freeaddrinfo(result);
		WSACleanup();
	}

	// struct sockaddr_in6 addr;
	// addr.sin6_family = AF_INET6;
	// addr.sin6_port = 0;
	// addr.sin6_flowinfo = 0;
	// addr.sin6_addr = in6addr_any;
	// addr.sin6_scope_id = 0;

	if (errror = bind(rawSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) {
	// if (errror = bind(rawSocket, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
		std::cout << errror << std::endl;
		log("bind: ");
		freeaddrinfo(result);
		closesocket(rawSocket);
		WSACleanup();
	}

	// BOOL bValue = TRUE;
	// if (errror = setsockopt(rawSocket, result->ai_protocol, IP_HDRINCL, (char*)&bValue, sizeof(bValue)) == SOCKET_ERROR) {
	// 	std::cout << errror << std::endl;
	// 	log("setsockopt: ");
	// 	freeaddrinfo(result);
	// 	closesocket(rawSocket);
	// 	WSACleanup();
	// }

	DWORD dwValue = RCVALL_ON;
	if (errror = ioctlsocket(rawSocket, SIO_RCVALL, &dwValue) != 0) {
		std::cout << errror << std::endl;
		log("ioctlsocket: ");
		freeaddrinfo(result);
		closesocket(rawSocket);
		WSACleanup();
	}


	Napi::Env env = info.Env();
	Napi::Object options = info[0].As<Napi::Object>();

	Napi::Function OnRecv = options.Get(Napi::String::New(env, "OnRecv")).As<Napi::Function>();
  
	char buff[4096];
	int count;
	while (true) {
		count = recv(rawSocket, buff, 4096, 0);
		std::cout << count << std::endl;
		if (count == SOCKET_ERROR) {
			log( "recv: " );
		}
		else {
			Napi::Array jsArray = Napi::Array::New(env, count);
			for (size_t i = 0; i < count; ++i) {
				jsArray.Set(i, Napi::Number::New(env, buff[i]));
			}

			OnRecv.Call(env.Global(), {
				jsArray
			});
		}

	}

  freeaddrinfo(result);
  closesocket(rawSocket);
  WSACleanup();
}


NODE_API_ADDON(Capture)

相信一脸懵逼的你已经看到了这里,那么附上咱们node调用c++的教程哈

1.安装node的头文件api
    npm i node-addon-api

2.新建源码文件:
    hello.cc

#include <napi.h>

class HelloAddon : public Napi::Addon<HelloAddon> {
 public:
  HelloAddon(Napi::Env env, Napi::Object exports) {
    DefineAddon(exports,
                {InstanceMethod("hello", &HelloAddon::Hello, napi_enumerable)});
  }

 private:
  Napi::Value Hello(const Napi::CallbackInfo& info) {
    return Napi::String::New(info.Env(), "world");
  }
};

NODE_API_ADDON(HelloAddon)

3.新建构建与编译的配置文件:
    binding.gyp

{
  "targets": [
    {
      "target_name": "hello",
      "cflags!": [ "-fno-exceptions" ],
      "cflags_cc!": [ "-fno-exceptions" ],
      "sources": [ "hello.cc" ],
      "include_dirs": [
        "<!@(node -p \"require('node-addon-api').include\")"
      ],
      'defines': ['NAPI_DISABLE_CPP_EXCEPTIONS'],
    }
  ]
}

4.安装node-gyp全局命令
    npm -g node-gyp

5.管理员运行cmd, 然后来到这个项目目录 ( node-gyp需要管理员权限还有环境变量 )

6.生成构建文件, 会生成build目录, 里面会根据当前系统生成对应的一些文件, 比如linux会生成Makefile, windows估计会生成vs的sln解决方案
    node-gpy configure

7.开始编译, 使用node-gyp自带的编译即可
    node-gyp build

( 注意:6.7可以合并成一条命令 node-gyp rebuild, 该命令会清除编译缓存并重新生成 )

8.生成的文件在 build/release/helle.node
    在js使用只需要require('build/release/helle')就行

9.新建hello.js

let hello = require( './build/Release/hello' )

console.log(hello.hello())

10.运行hello.js
    node hello.js

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值