大开眼界:Netbios 上古时代如何用一个参数实现一个世界 负面典型

今天的程序员普遍遵循这样的接口设计原则:通过不同的接口名和参数列表准确表达不同的功能。

这似乎是理所当然的,然而上古时代却并非如此,比如Netbios协议整个协议的接口只有一个函数、一个参数!

当初是基于什么原则这样设计不晓得,但它确实真真实实地存在过,最初是在windows 2000上实现的,到了windows vista就被淘汰。

我之所以用到这个东西是为了取得局域网上的机器名,代码如下:

cpp 复制代码
//取得MACHNAME
STATE getmachname(char * ip,char * machname,int machnamelen)
{
	if(machnamelen<16)
	{
		return -1;
	}
	
	//以下使用socket
	hostent * phost;
	unsigned long addr;
	if(INADDR_NONE==(addr=inet_addr(ip)))
		return -1;
	if(NULL!=(phost=gethostbyaddr((char *)&addr,4,PF_INET)))
	{
		if((int)strlen(phost->h_name)>=machnamelen)
			return -1;
		else
		{
			strcpy(machname,phost->h_name);
			return 1;
		}
	}

	//以下使用NetBIOS
	char ncb_buffer[sizeof(ADAPTER_STATUS)+256*sizeof(NAME_BUFFER)];
	UCHAR ret;
	NCB ncb;
	ADAPTER_STATUS * adapter_status;
	NAME_BUFFER * name_buffer;
	int lanacount;

	memset(&ncb,0,sizeof(NCB));
	memset(ncb_buffer,0xa3,sizeof(ADAPTER_STATUS)+256*sizeof(NAME_BUFFER));

	adapter_status=(ADAPTER_STATUS *)ncb_buffer;
	name_buffer=(NAME_BUFFER *)(ncb_buffer+sizeof(ADAPTER_STATUS));
	
	ncb.ncb_lana_num=0;
	ncb.ncb_lsn=0;
	ncb.ncb_num=0;
	ncb.ncb_command=NCBRESET;
//	if(NRC_GOODRET!=(ret=Netbios(&ncb)))
	{
//		return -2;
	}


	for(lanacount=0;lanacount<=0;lanacount++)
	{
		memset(&ncb,0,sizeof(NCB));
		memset(ncb_buffer,0xa3,sizeof(ADAPTER_STATUS)+256*sizeof(NAME_BUFFER));
		//设置输入
		ncb.ncb_command=NCBASTAT;
		ncb.ncb_buffer=(unsigned char *)ncb_buffer;
		ncb.ncb_length=sizeof(ADAPTER_STATUS)+256*sizeof(NAME_BUFFER);
		memset((char *)ncb.ncb_callname,' ',15);
		ncb.ncb_callname[15]='\0';
		memcpy((char *)ncb.ncb_callname,ip,strlen(ip));
	
		//预先设置输出(无意义)
		name_buffer->name[0]='\0';
		
		ncb.ncb_lana_num=(UCHAR)lanacount;
		if(NRC_GOODRET==(ret=Netbios(&ncb)))
		{
			break;
		}
		else
		{
		//	showret(ret);
		}
	}
	if(0<lanacount)
	{
		return -3;
	}

	memcpy(machname,name_buffer[0].name,16);
	return 1;
}

因为取机器名比较困难,所以我同时使用了socket函数和Netbios。具体代码无关紧要了,因为早已经过时,主要目的是看看Netbios接口有多令人震惊。

Netbios接口如下:

cpp 复制代码
UCHAR Netbios(
  PNCB pncb
);

好简洁啊!真是令人赞叹!

只有一个参数,是个指针,指向这个:

cpp 复制代码
typedef struct _NCB {
  UCHAR  ncb_command;
  UCHAR  ncb_retcode;
  UCHAR  ncb_lsn;
  UCHAR  ncb_num;
  PUCHAR ncb_buffer;//这是个指针
  WORD   ncb_length;
  UCHAR  ncb_callname[NCBNAMSZ];
  UCHAR  ncb_name[NCBNAMSZ];
  UCHAR  ncb_rto;
  UCHAR  ncb_sto;
  void()(_NCB *)  * ncb_post;//这里又是一个指针
  UCHAR  ncb_lana_num;
  UCHAR  ncb_cmd_cplt;
#if ...
  UCHAR  ncb_reserve[18];
#else
  UCHAR  ncb_reserve[10];
#endif
  HANDLE ncb_event;
} NCB, *PNCB;

这个结构里面还包括一个指向这种结构的指针,也就是可以无限级联下去。

第一个成员ncb_command是命令,我大概数了一下,有26种命令,也就是这个结构有26种解释。

每种命令仅仅使用其它成员的一小部分。其中ncb_buffer指针指向的结构视命令不同而不同。比如某个命令要求ncb_buffer指向这个结构:

cpp 复制代码
typedef struct _SESSION_HEADER {
  UCHAR sess_name;
  UCHAR num_sess;
  UCHAR rcv_dg_outstanding;
  UCHAR rcv_any_outstanding;
} SESSION_HEADER, *PSESSION_HEADER;

类似的结构体有八个。

虽说按照说明书往下啃是可以理解全部的,但确实有一种啃单片机手册的感觉。

这个东西被淘汰了,该!

(这里是结束)

相关推荐
计算机软件程序设计11 天前
高校失物招领小程序【源码+文档+安装+讲解】
小程序·程序设计·失物招领
茜茜西西CeCe2 个月前
Java程序设计:spring boot(12)——定时调度集成 - Quartz
java·spring boot·intellij-idea·程序设计·quartz·定时调度集成
charlie1145141913 个月前
设计模式小记:构造器
c++·设计模式·程序设计·构造器
蔚蓝星辰mic4 个月前
【C/C++】约瑟夫环问题
c语言·c++·算法·程序设计
蔚蓝星辰mic4 个月前
【C/C++】程序设计基础知识(指针、函数)
c语言·c++·程序设计
Beginner x_u5 个月前
C语言程序设计核心详解 第一章:数制及转换与ASCII码
c语言·开发语言·程序设计
悟道子HD7 个月前
C语言案例-输入任意三个数,按从大到小的顺序输出.
c语言·数据结构·算法·编程·程序设计·排序·最大值
bighu7 个月前
心跳包
程序设计
琛哥的程序8 个月前
【计算机毕业设计】家用电器销售网站产品功能介绍——后附源码
java·学习·毕业设计·课程设计·程序设计
琛哥的程序8 个月前
【计算机毕业设计】游戏售卖网站——后附源码
java·学习·毕业设计·课程设计·程序设计