为方便查看和对比, 做了c++版, 通过c++版搬迁到rust进行改改,实际的原理c++和rust都是运用windows提供的winsock2 api接口进行操作
注意: 需要管理员权限执行
rust版:
use windows::Win32::Networking::WinSock::*;
use windows::core::PCSTR;
fn main() {
println!("Hello, world!");
unsafe {
let mut wsa: WSADATA = WSADATA::default();
let mut error: i32;
error = WSAStartup(514, &mut wsa);
if error != 0 {
println!("{} : {}", "WSAStartup: ", error);
}
let mut hostname: [u8; 24] = [0; 24];
gethostname(&mut hostname);
let hostname_str: Result<_, _> = std::str::from_utf8(&hostname);
match hostname_str {
Ok(s) => {
let string: String = s.to_string();
println!("{}", string);
},
Err(e) => {
println!("Invalid UTF-8: {}", e);
}
}
let mut result_default: ADDRINFOA = ADDRINFOA::default();
let mut result: *mut ADDRINFOA = &mut result_default;
let mut hints: ADDRINFOA = ADDRINFOA::default();
hints.ai_family = AF_INET.0 as i32;
hints.ai_socktype = SOCK_RAW.0;
hints.ai_protocol = IPPROTO_IP.0;
error = getaddrinfo(PCSTR(hostname.as_ptr()), None, Some(&hints), &mut result);
if error != 0 {
println!("{} : {:?}", "getaddrinfo: ", WSAGetLastError());
WSACleanup();
}
let raw_socket: SOCKET = socket( (*result).ai_family, WINSOCK_SOCKET_TYPE((*result).ai_socktype), (*result).ai_protocol);
if raw_socket == INVALID_SOCKET {
println!("{} : {:?}", "socket: ", WSAGetLastError());
freeaddrinfo(Some(result));
WSACleanup();
}
let r_a_l: i32 = (*result).ai_addrlen as i32;
error = bind(raw_socket, (*result).ai_addr, r_a_l);
if error == SOCKET_ERROR {
println!("{} : {:?}", "bind: ", WSAGetLastError());
freeaddrinfo(Some(result));
closesocket(raw_socket);
WSACleanup();
}
let mut dw_value: u32 = RCVALL_ON.0 as u32;
let sio: i32 = SIO_RCVALL as i32;
error = ioctlsocket(raw_socket, sio, &mut dw_value);
if error != 0 {
println!("{} : {:?}", "ioctlsocket: ", WSAGetLastError());
freeaddrinfo(Some(result));
closesocket(raw_socket);
WSACleanup();
}
let mut buff: [u8; 1024] = [0; 1024];
let mut count: i32;
loop {
count = recv(raw_socket, &mut buff, SEND_RECV_FLAGS(0));
if count == SOCKET_ERROR {
println!( "recv: " );
}
else {
println!("{:?}", buff);
}
}
// freeaddrinfo(Some(&result));
// closesocket(raw_socket);
// WSACleanup();
}
}
c++版:
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mstcpip.h>
#include <comdef.h>
#pragma comment(lib, "ws2_32.lib")
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;
}
int main()
{
WSADATA wsa;
int errror;
if (errror = WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
log("WSAStartup: ");
return -1;
}
char name[100];
gethostname(name, sizeof(name));
struct addrinfo *result = NULL, *ptr = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET6;
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();
return 1;
}
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();
return -1;
}
//struct sockaddr_in addr;
//addr.sin_family = AF_INET;
//addr.sin_port = 0;
//addr.sin_addr = in4addr_any;
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();
return -1;
}
//BOOL bValue = TRUE;
//if (errror = setsockopt(rawSocket, result->ai_protocol, IPPROTO_RAW, (char*)&bValue, sizeof(bValue)) == SOCKET_ERROR) {
// std::cout << errror << std::endl;
// log("setsockopt: ");
// freeaddrinfo(result);
// closesocket(rawSocket);
// WSACleanup();
// return -1;
//}
DWORD dwValue = RCVALL_ON;
if (errror = ioctlsocket(rawSocket, SIO_RCVALL, &dwValue) != 0) {
std::cout << errror << std::endl;
log("ioctlsocket: ");
freeaddrinfo(result);
closesocket(rawSocket);
WSACleanup();
return -1;
}
char buff[4096];
int nRet;
struct sockaddr_in6 from;
int fromLen = sizeof(from);
while (true) {
nRet = recv(rawSocket, buff, 4096, 0);
//nRet = recvfrom(rawSocket, buff, sizeof(buff), 0, (struct sockaddr*)&from, &fromLen);
std::cout << nRet << std::endl;
if (nRet == SOCKET_ERROR) {
log("recv: ");
}
}
freeaddrinfo(result);
closesocket(rawSocket);
WSACleanup();
return 0;
}