开始学习(算是复习)网络编程了,第一个就是局域网的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 #include3 #include 4 #include 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 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 else116 continue;117 }118 }119 }120 for(i=0;i
客户端代码参考:
1 //客户端参考代码: 2 // client.cpp : Defines the entry point for the console application. 3 // 4 5 #include6 #include 7 #include 8 #include 9 #include "NetBioscmd.h"10 #define MAX_SESSIONS 25411 #define MAX_NAMES 25412 #define MAX_BUFFER 102413 #define MAX_DATAGRAM_SIZE 51214 #define CLIENT_NAME "client"15 #define SERVER_NAME "server"16 //main fuction17 int main(int argc, char* argv[])18 {19 HANDLE *hEvent;20 NCB *pncb;21 DWORD dwRet,22 Bufferlen,dwIndex;23 UCHAR *dwNum = NULL;24 char Buff[MAX_BUFFER],25 Servername[NCBNAMSZ+1];26 LANA_ENUM lenum;27 int i;28 if(LanaEnum(&lenum)!=NRC_GOODRET)29 return 1;30 if(ResetAll(&lenum,(UCHAR)MAX_SESSIONS,(UCHAR)MAX_NAMES,false)!=NRC_GOODRET)31 return 1;32 hEvent = (HANDLE*)GlobalAlloc(GMEM_FIXED,sizeof(HANDLE)*lenum.length); //分配内存33 pncb = (NCB*)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(NCB)*lenum.length);34 dwNum = (UCHAR*)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(UCHAR)*lenum.length);35 for(i=0;i ncb_callname,Servername);78 printf("Massage from[%s]:%s\n",Servername,Buff);79 }80 81 Hangup(pncb[dwIndex].ncb_lana_num,pncb[dwIndex].ncb_lsn);82 }83 84 85 for(i=0;i
其中需要一个头文件NetBIOScmd.h部分参考代码:
1 //NetBIOScmd.h 部分参考代码: 2 // 3 //Get the status of local or remote adapter 4 // 5 #define MAX_DATAGRAM_SIZE 512 6 int Astatus(ADAPTER_STATUS *astat,int lana,char *name) 7 { 8 NCB ncb; 9 ZeroMemory(&ncb,sizeof(NCB)); 10 ncb.ncb_command = NCBASTAT; 11 ncb.ncb_buffer = (PUCHAR)astat; 12 ncb.ncb_length = sizeof(ADAPTER_STATUS); 13 memset(&ncb.ncb_callname,' ',NCBNAMSZ); 14 strncpy((char *)&ncb.ncb_callname,name,strlen(name)); 15 ncb.ncb_lana_num = lana; 16 if(Netbios(&ncb)!=NRC_GOODRET) 17 { 18 printf("Netbios NCBASTAT ERROR:%0xh\n",ncb.ncb_retcode); 19 return ncb.ncb_retcode; 20 } 21 return NRC_GOODRET; 22 } 23 // 24 //Get the machine's LANA NUM 25 // 26 int LanaEnum(LANA_ENUM *lenum) 27 { 28 NCB ncb; 29 ZeroMemory(&ncb,sizeof(NCB)); 30 ncb.ncb_command = NCBENUM; 31 ncb.ncb_buffer = (PUCHAR)lenum; 32 ncb.ncb_length = sizeof(LANA_ENUM); 33 if(Netbios(&ncb)!=NRC_GOODRET) 34 { 35 printf("Netbios NEBENUM ERROR:%0xh\n",ncb.ncb_retcode); 36 return ncb.ncb_retcode; 37 } 38 return NRC_GOODRET; 39 } 40 // 41 //Reset All LANA NUM 42 // 43 int ResetAll(LANA_ENUM *lenum,UCHAR ucMaxSession,UCHAR unMaxName,BOOL bFirstname) 44 { 45 NCB ncb; 46 ZeroMemory(&ncb,sizeof(NCB)); 47 ncb.ncb_command = NCBRESET; 48 ncb.ncb_callname[0] = ucMaxSession; 49 ncb.ncb_callname[1] = unMaxName; 50 ncb.ncb_callname[2] = (UCHAR)bFirstname; 51 for(int i=0;ilength;i++) 52 { 53 ncb.ncb_lana_num = lenum->lana[i]; 54 if(Netbios(&ncb)!=NRC_GOODRET) 55 { 56 printf("Netbios NCBRESET[%d]ERROR:%0xh\n",ncb.ncb_lana_num,ncb.ncb_retcode); 57 return ncb.ncb_retcode; 58 } 59 } 60 return NRC_GOODRET; 61 } 62 // 63 //Add name of program 64 // 65 int AddName(int lana,char *name,UCHAR *num) 66 { 67 NCB ncb; 68 ZeroMemory(&ncb,sizeof(NCB)); 69 ncb.ncb_command = NCBADDNAME; 70 ncb.ncb_lana_num = lana; 71 memset(ncb.ncb_name,' ',NCBNAMSZ);//add by jinhua 72 strncpy((char *)ncb.ncb_name,name,strlen(name)); 73 if(Netbios(&ncb)!=NRC_GOODRET) 74 { 75 printf("Netbios NCBADDNAME[lana=%d;name=%s]ERROR:%0xh\n",lana,name,ncb.ncb_retcode); 76 return ncb.ncb_retcode; 77 } 78 *num = ncb.ncb_num; 79 return NRC_GOODRET; 80 } 81 // 82 //Cancel NetBios Command 83 // 84 int Cancel(PNCB pncb) 85 { 86 NCB ncb; 87 ZeroMemory(&ncb,sizeof(NCB)); 88 ncb.ncb_command = NCBCANCEL; 89 ncb.ncb_buffer = (PUCHAR)pncb; 90 ncb.ncb_lana_num = pncb->ncb_lana_num; 91 if(Netbios(&ncb)!=NRC_GOODRET) 92 { 93 printf("Netbios NCBCANCEL ERROR:%0xh\n",ncb.ncb_retcode); 94 return ncb.ncb_retcode; 95 } 96 return NRC_GOODRET; 97 } 98 // 99 //Hangup Command100 //101 int Hangup(int lana,int lsn)102 {103 NCB ncb;104 int retcode;105 ZeroMemory(&ncb,sizeof(NCB));106 ncb.ncb_command = NCBHANGUP;107 ncb.ncb_lsn = lsn;108 ncb.ncb_lana_num = lana;109 retcode = Netbios(&ncb);110 return retcode;111 }112 //113 //Delete Name Command114 //115 int DelName(int lana,char *name)116 {117 NCB ncb;118 ZeroMemory(&ncb,sizeof(NCB));119 ncb.ncb_command = NCBDELNAME;120 ncb.ncb_lana_num = lana;121 //memset(ncb.ncb_name,' ',strlen(name));122 memset(ncb.ncb_name,' ',NCBNAMSZ);//add by jinhua123 strncpy((char *)ncb.ncb_name,name,strlen(name));124 if(Netbios(&ncb) != NRC_GOODRET)125 {126 printf("Netbios NCBDELNAME [lana=%d;name=%s] ERROR:%0xh\n",lana,name,ncb.ncb_retcode);127 return ncb.ncb_retcode;128 }129 return NRC_GOODRET;130 }131 //132 //Add the group name to LANA number133 //Retrun the name number for the registered name.134 //135 int AddGroupName(int lana,char *name,UCHAR *num)136 {137 NCB ncb;138 ZeroMemory(&ncb,sizeof(NCB));139 ncb.ncb_command = NCBADDGRNAME;140 ncb.ncb_lana_num = lana;141 memset(ncb.ncb_name,' ',NCBNAMSZ);142 strncpy((char *)ncb.ncb_name,name,strlen(name));143 if(Netbios(&ncb)!=NRC_GOODRET)144 {145 printf("Netbios NCBADDGRPNAME[lana=%d;name=%s] ERROR:%0xh\n",lana,name,ncb.ncb_retcode);146 return ncb.ncb_retcode;147 }148 *num = ncb.ncb_num;149 return NRC_GOODRET;150 }151 //152 //function to realize NCBRECV153 //154 int Recv(int lana,int lsn,char *buffer,DWORD bufferlen)155 {156 NCB ncb;157 ZeroMemory(&ncb,sizeof(NCB));158 ncb.ncb_command =NCBRECV;159 ncb.ncb_buffer =(PUCHAR)buffer;160 ncb.ncb_length =(unsigned short)bufferlen;161 ncb.ncb_lana_num =lana;162 ncb.ncb_lsn =lsn;163 if(Netbios(&ncb)!=NRC_GOODRET)164 {165 bufferlen = -1;166 printf("Netbios NCBRECV ERROR:%0xh.\n",ncb.ncb_retcode);167 return ncb.ncb_retcode;168 }169 bufferlen = ncb.ncb_length;170 return NRC_GOODRET;171 }172 //173 //function to realize NCBSEND174 //175 int Send(int lana,int lsn,char *data,DWORD len)176 {177 NCB ncb;178 int retcode;179 ZeroMemory(&ncb,sizeof(NCB));180 ncb.ncb_command =NCBSEND;181 ncb.ncb_buffer =(PUCHAR)data;182 ncb.ncb_length =(unsigned short)len;183 ncb.ncb_lsn =lsn;184 ncb.ncb_lana_num =lana;185 retcode =Netbios(&ncb);186 return retcode;187 }188 //189 //covert the NetBIOS name from unprintable to printable190 //191 int FormatNetbiosName(char *nbname,char *outname)192 {193 int i;194 strncpy(outname,nbname,NCBNAMSZ);195 outname[NCBNAMSZ-1] = '\0';196 for(i=0;i =32)&&(outname[i]<=126)))199 outname[i] = '.';200 }201 return NRC_GOODRET;202 }203 //204 //Send a broadcast datagram on the specified LANA number205 //206 int DatagramSendBC(int lana,int num,char *buffer,int buflen)207 {208 NCB ncb;209 ZeroMemory(&ncb,sizeof(NCB));210 ncb.ncb_command = NCBDGSENDBC;211 ncb.ncb_lana_num = lana;212 ncb.ncb_num = (UCHAR)num;213 ncb.ncb_buffer = (PUCHAR)(buffer);214 ncb.ncb_length = buflen;215 if(Netbios(&ncb)!=NRC_GOODRET)216 {217 printf("Netbios NCBDGSENDBC ERROR:%0xh\n",ncb.ncb_retcode);218 return ncb.ncb_retcode;219 }220 return NRC_GOODRET;221 }222 //223 //receive a broadcast datagram on the specified LANA number from the registered name224 //225 int DatagramRecvBC(PNCB pncb,int lana,int num,char *buffer,int buflen,HANDLE hEvent)226 {227 ZeroMemory(pncb,sizeof(NCB));228 ZeroMemory(buffer,sizeof(MAX_DATAGRAM_SIZE));229 pncb->ncb_command = NCBDGRECVBC|ASYNCH;230 pncb->ncb_lana_num = lana;231 pncb->ncb_buffer = (PUCHAR)(buffer);232 pncb->ncb_length = buflen;233 pncb->ncb_event = hEvent;234 if(Netbios(pncb)!=NRC_GOODRET)235 {236 printf("Netbios NCBDGRECVBC ERROR:%0xh\n",pncb->ncb_retcode);237 return pncb->ncb_retcode;238 }239 return NRC_GOODRET;240 }241 //242 //Send a directed datagram on the specified LANA number243 //244 int DatagramSend(int lana,int num,char *buffer,int buflen,char *Destname)245 {246 NCB ncb;247 ZeroMemory(&ncb,sizeof(NCB));248 ncb.ncb_command =NCBDGSEND;249 ncb.ncb_lana_num =lana;250 ncb.ncb_num =(UCHAR)num;251 ncb.ncb_buffer =(PUCHAR)buffer;252 ncb.ncb_length =buflen;253 memset(ncb.ncb_name,' ',NCBNAMSZ);254 strncpy((char *)ncb.ncb_callname,Destname,strlen(Destname));255 if(Netbios(&ncb)!=NRC_GOODRET)256 {257 printf("Netbios NCBDGSEND ERROR:%0xh\n",ncb.ncb_retcode);258 return ncb.ncb_retcode;259 }260 return NRC_GOODRET;261 }262 //263 //Recieve a directed datagram on the specified LANA number from registered name264 //265 int DatagramRecv(PNCB pncb,int lana,int num,char *buffer,int buflen,HANDLE hEvent)266 {267 ZeroMemory(pncb,sizeof(NCB));268 ZeroMemory(buffer,sizeof(MAX_DATAGRAM_SIZE));269 pncb->ncb_command =NCBDGRECV|ASYNCH;270 pncb->ncb_lana_num =lana;271 pncb->ncb_num =(UCHAR)num;272 pncb->ncb_buffer =(PUCHAR)buffer;273 pncb->ncb_length =buflen;274 pncb->ncb_event =hEvent;275 if(Netbios(pncb)!=NRC_GOODRET)276 {277 printf("Netbios NCBDGRECV ERROR:%0xh\n",pncb->ncb_retcode);278 return pncb->ncb_retcode;279 }280 return NRC_GOODRET;281 }282 //283 //function to realize NCBLISTEN284 //285 int Listen(PNCB pncb,int lana,char *server,HANDLE hEvent)286 {287 pncb->ncb_command = NCBLISTEN|ASYNCH;288 pncb->ncb_lana_num = lana;289 memset(&pncb->ncb_name,' ',NCBNAMSZ);290 strncpy((char *)&pncb->ncb_name,server,strlen(server));291 memset(&pncb->ncb_callname,' ',NCBNAMSZ);292 pncb->ncb_callname[0] = '*';293 pncb->ncb_event = hEvent;294 //you also can use callback function to providw service to client295 //pncb->ncb_post =listencallback;296 if(Netbios(pncb)!=NRC_GOODRET)297 {298 printf("Netbios NCBLISTEN ERROR:%0xh.\n",pncb->ncb_retcode);299 return pncb->ncb_retcode;300 }301 return NRC_GOODRET;302 }303 //304 //fuction to realize NCBCALL305 //306 int Connect(PNCB pncb,int lana,char *server,char *client,HANDLE hEvent)307 {308 pncb->ncb_command =NCBCALL|ASYNCH;309 pncb->ncb_lana_num =lana;310 memset(&pncb->ncb_name,' ',NCBNAMSZ);311 strncpy((char *)&pncb->ncb_name,client,strlen(client));312 memset(&pncb->ncb_callname,' ',NCBNAMSZ);313 strncpy((char *)&pncb->ncb_callname,server,strlen(server));314 pncb->ncb_event =hEvent;315 if(Netbios(pncb)!=NRC_GOODRET)316 {317 printf("ERROR:Netbios:NCBCONNECT.%0xh\n",pncb->ncb_retcode);318 return pncb->ncb_retcode;319 }320 return NRC_GOODRET;321 }
这两天看的netbios,简单整理了一下,分享给园友,有问题请指正,谢谢。