开始学习(算是复习)网络编程了,第一个就是局域网的netbios协议编程。
首先了解一下什么是netbios:IBM公司为PC-Network开发的一套网络标准。,NetBIOS最广泛的应用之一就是对NetBIOS用户扩展接口(NetBEUI,NetBIOS Extend User Interface)协议的使用。处在表示层与会话层之间,处于参考模型的高层。
优点:短小精练; 良好的网络通信性能; 适合于适时性较高的小型LAN网络环境;
缺点:是一种不可路由的协议;数据包无法跨网段传输。
NetBIOS程序的工作过程:
首先,网络通信程序通过名字的标识区别于其他程序,并将名字注册到LANA中,获得合法的网络身份。
之后,网络通信程序可以使用NetBIOS的数据报或会话服务与驻留在相同或不同主机中的其他应用程序进行通信。通信过程中,用户还可以使用一般命令服务对适配器进行管理和监测。
最后,在通信结束后,通信程序需要删除已注册的名字并释放所占用的网络资源。
编程讲解:
在Win32环境下,使用VS2012进行NetBIOS程序开发时, 需要用到nb30.h文件和netapi32.lib静态链接库。前者定义了NetBIOS的所有函数声明和常数定义,后者定义了NetBIOS应用。Ncb的结构在nb30.h文件中定义。Ncb结构的定义:Ncb有64个字符,分为14个域(或称为字段)和一个10字节的保留域。各字段这里就不详细了,另外一个博客有讲解。
编写NetBios命令函数的步骤:
1. 定义函数原型。
2. 申明NCB结构变量。
3. 对该变量所有域清零。
4. 根据命令填写相关域。
5. 调用NetBios函数提交NCB结构。
6. 判断NetBios函数返回值,作出相应处理。
7. 从NCB中获取输出域。(根据具体命令)
简单的基于NetBios的对话编程,实现了建立会话过程,客户端向服务端发送数据,服务端接受数据并回复数据,客户端成功接受并无限递归(当然程序可以自己修改)。win32,vs2012,C++平台参考代码如下:
服务端代码参考:
1 //服务端参考代码: 2 #include <windows.h> 3 #include <stdio.h> 4 #include <nb30.h> 5 #include "NetBioscmd.h" 6 #define MAX_SESSIONS 254 7 #define MAX_NAMES 254 8 #define MAX_BUFFER 1024 9 #define SERVER_NAME "server" 10 // 11 //Thread to give a simple service to client 12 // 13 DWORD WINAPI ServerThread(PVOID lpParam) 14 { 15 PNCB pncb =(PNCB)lpParam; 16 NCB ncb; 17 char buff[MAX_BUFFER], 18 Clientname[NCBNAMSZ+1]; 19 DWORD Bufferlen,retval =NRC_GOODRET; 20 FormatNetbiosName((char *)&pncb->ncb_callname,Clientname); 21 printf("a connect come\n"); 22 ZeroMemory(buff,MAX_BUFFER); 23 Bufferlen =MAX_BUFFER; 24 25 while (true) 26 { 27 retval =Recv(pncb->ncb_lana_num,pncb->ncb_lsn,buff,Bufferlen); 28 if(retval!=NRC_GOODRET) 29 return pncb->ncb_retcode; 30 printf("Massage from[%s]:%s\n",Clientname,buff); 31 ZeroMemory(buff,MAX_BUFFER); 32 Bufferlen =MAX_BUFFER; 33 strcpy(buff,"welcome you join the NetBIOS club."); 34 retval =Send(pncb->ncb_lana_num,pncb->ncb_lsn,buff,Bufferlen); 35 if(retval!=NRC_GOODRET) 36 return pncb->ncb_retcode; 37 } 38 39 if(retval!=NRC_SCLOSED) 40 { 41 ZeroMemory(&ncb,sizeof(NCB)); 42 ncb.ncb_command =NCBHANGUP; 43 ncb.ncb_lsn =pncb->ncb_lsn; 44 ncb.ncb_lana_num =pncb->ncb_lana_num; 45 if(Netbios(&ncb)!=NRC_GOODRET) 46 { 47 GlobalFree(pncb); 48 retval =ncb.ncb_retcode; 49 } 50 } 51 GlobalFree(pncb); 52 return NRC_GOODRET; 53 } 54 // 55 //Callback function to give a simple service to client, you can use it as another sever model 56 // 57 void CALLBACK listencallback(PNCB pncb) 58 { 59 // 60 //you also can write down code here to communicate to a client 61 // 62 } 63 //main function 64 int main(int argc, char* argv[]) 65 { 66 HANDLE hEvent[64],hThread; 67 NCB *pncb, 68 *workpncb; 69 DWORD ThreadId, 70 dwIndex; 71 UCHAR dwNum = ' '; 72 LANA_ENUM lenum; 73 int i; 74 if(LanaEnum(&lenum)!=NRC_GOODRET) 75 { 76 return 1; 77 } 78 if(ResetAll(&lenum,(UCHAR)MAX_SESSIONS,(UCHAR)MAX_NAMES,false)!=NRC_GOODRET) 79 return 1; 80 pncb = (NCB*)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(NCB)*lenum.length); 81 for(i=0;i<lenum.length;i++) 82 if((AddName((int)lenum.lana[i],SERVER_NAME,&dwNum))==NRC_GOODRET) 83 {printf("add name(%s) to lana[%d]\n",SERVER_NAME,lenum.lana[i]); 84 //printf("name(%s) have the name_num (%d)\n",SERVER_NAME,dwNum); 85 } 86 for(i=0;i<lenum.length;i++) 87 { 88 hEvent[i]=CreateEvent(0,TRUE,FALSE,0); 89 if(Listen(&pncb[i],lenum.lana[i],SERVER_NAME,hEvent[i])==NRC_GOODRET) 90 printf("attempt to listen to lana[%d] succeed!\n",lenum.lana[i]); 91 } 92 printf("Server setup has been finished,now server begin to listen.\n"); 93 while(true) 94 { 95 dwIndex=WaitForMultipleObjects(lenum.length,hEvent,FALSE,INFINITE); 96 if(dwIndex==WAIT_FAILED) 97 { 98 printf("WaitForMultipleObjects ERROR:%0xh\n",GetLastError()); 99 break; 100 } 101 else 102 { 103 for(int i=0;i<lenum.length;i++) 104 { 105 if(pncb[i].ncb_cmd_cplt!=NRC_PENDING) 106 { 107 workpncb = (NCB *)GlobalAlloc(GMEM_FIXED,sizeof(NCB)); 108 memcpy(workpncb,&pncb[i],sizeof(NCB)); 109 workpncb->ncb_event = 0; 110 hThread=CreateThread(NULL,0,ServerThread,(LPVOID)workpncb,0,&ThreadId); 111 CloseHandle(hThread); 112 ResetEvent(hEvent[i]); 113 Listen(&pncb[i],lenum.lana[i],SERVER_NAME,hEvent[i]); 114 } 115 else 116 continue; 117 } 118 } 119 } 120 for(i=0;i<lenum.lana[i];i++) 121 { 122 DelName(lenum.lana[i],SERVER_NAME); 123 CloseHandle(hEvent[i]); 124 } 125 GlobalFree(hEvent); 126 GlobalFree(pncb); 127 return 0; 128 }