首页 > C/C++ > c++ 获取计算机名(使用NetBios)
2015
12-08

c++ 获取计算机名(使用NetBios)

因为使用gethostbyaddr 这个API有某些系统下不能正确获取远程计算机名。所以使用NetBios 获取计算机名。

windows 系统有一个小工具使用 nbtstat -a  ip 可以获内网计算机名。

1、使用 Wireshark 2.0 抓取 nbtstat -a 发送的包数据

a) 设置过滤条件为udp 端口 137

捕获->选项 选中你的网卡 ->选择接口的捕获筛选器 输入 port 137 如下图

b) 点击开始 然后在 命令行 运行

C:\Users\John>nbtstat -a 192.168.17.135

然后就捕获到了发送接受的数据了。

c) 提取发送数据

选中发送的数据,右建->追踪流->UDP 流  如下图

设置 显示数据为 ->”C Arrays” 如下图

peer0_0 就是我们需要的数据包了。

 

源码如下:

// netbios.cpp : 定义控制台应用程序的入口点。
//
//  [12/8/2015 cnfreebsd@163.com ]
#include "stdafx.h"
#include <string>
#include <atlconv.h>
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib, "ws2_32.lib")


std::string trim_right(const std::string& str) 
{
	if (str.begin() == str.end()) {
		return str;
	}

	std::string t = str;
	std::string::iterator i;
	for (i = t.end() - 1; ;--i) 
	{
		if (!isspace(*i)) {
			t.erase(i + 1, t.end());
			break;
		}
		if (i == t.begin()) 
		{
			t.clear();
			break;
		}
	}
	return t;
}

int _tmain(int argc, _TCHAR* argv[])
{
	USES_CONVERSION;

	SOCKET hsock;
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2,1),&wsaData))
	{
		WSACleanup();
		return 0;
	}
	struct sockaddr_in sockaddr;
	int len = sizeof(sockaddr);
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons(137);
	sockaddr.sin_addr.s_addr = inet_addr(T2A(argv[1]));
	hsock = socket(AF_INET,SOCK_DGRAM,0);

	struct timeval tv_out;
	tv_out.tv_sec = 10 * 1000;//等待10秒
	tv_out.tv_usec = 0;
	setsockopt(hsock,SOL_SOCKET,SO_RCVTIMEO, (const char*)&tv_out, sizeof(tv_out));

	std::string strHostName;

	char cNBNS[] = { /* Packet 40 */
		0xf6, 0x45, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
		0x00, 0x00, 0x00, 0x00, 0x20, 0x43, 0x4b, 0x41, 
		0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
		0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
		0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
		0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x21, 
		0x00, 0x01 };

		if(sendto(hsock, (const char*)cNBNS, 50, 0, (struct sockaddr*)&sockaddr,len) != SOCKET_ERROR)
		{
			char buf[1024] = "\0";
			if (recvfrom(hsock, buf, sizeof(buf), 0, (struct sockaddr*)&sockaddr, &len) != SOCKET_ERROR)
			{
				std::string strTemp,strHost;

				int nTemp = 0;
				int nNum = 0;
				bool bAdd = true;
				//NBTSTAT 前面的57个字节
				for(int i = 57; i < _countof(buf); i++)
				{
					// 结束
					if(buf[i] == 0xcc)
						break; 

					if(buf[i] == 0x20)
						bAdd = false;

					if(bAdd)
					{
						char tmp[MAX_PATH] = {0};
						sprintf(tmp, "%c", buf[i]);
						strTemp = tmp;

						if(buf[i]>=' ')
						{
							strHost+=strTemp;
						}
					}

					if((++nTemp)%18 == 0)
					{
						strHost = trim_right(strHost);
						if(nNum == 0 && strHost != "" )
						{
							strHostName = strHost;
							nNum++;
						}
					}
				}
			}
		}

		printf("IP: %s 计算机名:%s", T2A(argv[1]), strHostName.c_str());
}

 

 

最后编辑:
作者:dnybz
这个作者貌似有点懒,什么都没有留下。