Netbios编程(一):服务器端(事件模型)

说明:看Netbios程序过程中,总结的开发服务器程序的步骤,相关代码多来自windows网络编程

Netbios主要应用域小型局域网,服务器端(事件模型)开发的步骤如下:

(1)枚举出本机所有的LANA,然后重设每个LANA。

//枚举所有的LANA

int LanaEnum(LANA_ENUM *lenum)
{
    NCB ncb;
    ZeroMemory(&ncb,sizeof(NCB));
    ncb.ncb_command=NCBENUM;//指定要执行的NetBios命令
    ncb.ncb_buffer=(PUCHAR)lenum;
    ncb.ncb_length=sizeof(LANA_ENUM);
    if(Netbios(&ncb)!=NRC_GOODRET)
    {
        printf("ERROR:NetBios:NCBENUM:%d/n",ncb.ncb_retcode);
        return ncb.ncb_retcode;//指定操作的返回代码,在一个异步操作进行期间,函数将该值设为NRC_PENDING
    }
    return NRC_GOODRET;
}

//重设每个LANA

int ResetAll(LANA_ENUM *lenum,UCHAR ucMaxSession,UCHAR ucMaxName,BOOL bFirstName)
{
    NCB ncb;
    int i;
    ZeroMemory(&ncb,sizeof(NCB));
    ncb.ncb_command=NCBRESET;
    ncb.ncb_callname[0]=ucMaxSession;
    ncb.ncb_callname[2]=ucMaxName;
    ncb.ncb_callname[3]=(UCHAR)bFirstName;

    for(i=0;i<lenum->length;i++)
    {
        ncb.ncb_lana_num=lenum->lana[i];
        if(Netbios(&ncb)!=NRC_GOODRET)
        {
            printf("ERROR:Netbios:NCBRESET[%d]:%d/n",ncb.ncb_lana_num,ncb.ncb_retcode);
            return ncb.ncb_retcode;
        }
    }
    return NRC_GOODRET;
}

(2)为每个LANA分配一个NCB结构,创建相同数量的人工重置事件对象

NCB *nbArray=(PNCB)GlobalAlloc(GMEM_FIXED|GMEM_ZERO,sizeof(NCB)*lenum.length);

HANDLE *hArray=(HANDLE *)GlobalAlloc(GMEM_FIXED|GMEM_ZERO,sizeof(HANDLE)*lenum.length);

for(i=0;i<lenum.length;i++)

{

    hArray[i]=CreateEvent(NULL,TRUE,FALSE,NULL);

    nbArray[i].ncb_event=hArray[i];

}

(3)将服务器进程的名字增加到每个LANA的名字表中(这个名字有点儿类似于socket中的端口号)

//向LANA的名字表中增加名字

int AddName(int lana,char *name,int *num)
{
    NCB ncb;
    ZeroMemory(&ncb,sizeof(NCB));
    ncb.ncb_command=NCBADDNAME;
    ncb.ncb_lana_num=lana;
    memset(ncb.ncb_name,' ',NCBNAMSZ);
    strncpy(ncb.ncb_name,name,strlen(name));
    if(Netbios(&ncb)!=NRC_GOODRET)
    {
        printf("ERROR:Netbios:NCBADDNAME[lana=%d;name=%s]:%d/n",lana,name,ncb.ncb_retcode);
        return ncb.ncb_retcode;
    }
    *num=ncb.ncb_num;
    return NRC_GOODRET;
}

//将服务进程名增加到每个LANA中

for(i=0;i<lenum.length;i++)

AddName(lenum.lana[i],SERVER_NAME,&num);

(4)在每个LANA上进行异步监听

//监听函数

int Listen(PNCB pncb,int lana,char *name)
{
    pncb->ncb_command=NCBLISTEN|ASYNCH;
    pncb->ncb_lana_num=lana;
    //
    //This is the name clients will connect to
    //
    memset(pncb->ncb_name,' ',NCBNAMSZ);
    strncpy((char *)pncb->ncb_name,name,strlen(name));
    //
    //远程应用(即客户端)名字的第一个字符指定为“*”表示我们希望监听所有的

    //客户端连接;如果指定一个客户端名字,则表示我们指监听指定的客户端的链接

   //
    memset(pncb->ncb_callname,' ',NCBNAMSZ);
    pncb->ncb_callname[0]='*';

    if(Netbios(pncb)!=NRC_GOODRET)
    {
        printf("Error:Netbios:NCBLISTEN:%d/n",pncb->ncb_retcode);
        return pncb->ncb_retcode;
    }
    return NRC_GOODRET;
}

//在所有LANA指定的名字上进行监听

for(i=0;i<lenum.length;i++)

Listen(&nbArray[i],lenum.lana[i];SERVER_NAME);

(5)等待客户端连接

while(true)
    {
        //wait until a client connects
        //
        dwRet=WaitForMultipleObjects(lenum.length,hArray,FALSE,INFINITE);
        if(dwRet==WAIT_FAILED)
        {
            printf("Error:WaitForMultipleObjects:%d/n",GetLastError());
            break;
        }
        //
        //Go through all the NCB structures to see whether more than one
        //succeed.if ncb_cmd_plt is not NRC_PENDING,there is a client:create
        //a thread ,and hand off a new NCB structure to thread.We need to reuse the orignal
        //NCB for other client connections
        //
        for(i=0;i<lenum.length;i++)
        {
            if(nbArray[i].ncb_cmd_cplt!=NRC_PENDING)
            {
                pncb=(PNCB)GlobalAlloc(GMEM_FIXED,sizeof(NCB));
                memcpy(pncb,&hArray[i],sizeof(NCB));
                pncb->ncb_event=0;

               //创建一个线程对建立的链接进行处理
                hThread=CreateThread(NULL,0,ClientThread,(LPVOID)pncb,0,&dwThreadId);
                CloseHandle(hThread);
                //
                //将事件对象置为非信号状态,继续监听其他请求
                //
                ResetEvent(hArray[i]);
                Listen(&nbArray[i],lenum.lana[i],SERVER_NAME);
            }
        }
    }

(6)线程函数

//取得远程应用名字
//Format the given NetBIOS name so that it is printable.Any
//unprintable charactors are replaced by a period.The outname
//buffer is the returned string ,which is assumed to be at least
//NCBNAMSZ+1 charactors in length
//
int FormatNetbiosName(char *nbName,char *outname)
{
    int i;
    strncpy(outname,nbName,NCBNAMSZ);
    outname[NCBNAMSZ-1]='/0';
    for(i=0;i<NCBNAMSZ-1;i++)
    {
        //if the charactor isn't printable,replace it with '.'
        if(!((outname[i]>=32)&&(outname[i]<126)))
            outname[i]='.';
    }
    return NRC_GOODRET;
}

//
//线程函数
//
//Description:
//  This  thread takes the NCB structure of a connected session
//  and waits for incoming data,which it then sends back to the
//  client until hte session is closed
//
DWORD WINAPI ClientThread(PVOID lpParam)
{
    PNCB pncb=(PNCB)lpParam;
    NCB ncb;
    char szRecvBuff[MAX_BUFFER],szClientName[NCBNAMSZ+1];
    DWORD dwBufferLen=MAX_BUFFER,dwRetVal=NRC_GOODRET;

    //取得远程应用的名字
    FormatNetbiosName((char *)pncb->ncb_callname,szClientName);
    //
    //Send and receive messages until the session is closed
    //
    while(true)
    {
        dwBufferLen=MAX_BUFFER;

         //接受数据
        dwRetVal=Recv(pncb->ncb_lana_num,pncb->ncb_lsn,szRecvBuff,&dwBufferLen);
        if(dwRetVal!=NRC_GOODRET)
            break;
 

       //将受到的数据原封不动的发送给客户端
        szRecvBuff[dwBufferLen]=0;
        printf("READ [LANA=%d]:'%s'/n",pncb->ncb_lana_num,szRecvBuff);
   
        dwRetVal=Send(pncb->ncb_lana_num,pncb->ncb_lsn,szRecvBuff,dwBufferLen);
        if(dwRetVal!=NRC_GOODRET)
            break;
    }

    printf("Client '%s' on LANA %d disconnected/n",szClientName,pncb->ncb_lana_num);

    //
    //if the error returned from a read or a write is NRC_SCLOSED,
    //all is well;otherwise,some other error occurred,so hang up the
    //connection from this side
    //
    if(dwRetVal!=NRC_SCLOSED)
    {
        ZeroMemory(&ncb,sizeof(NCB));
        ncb.ncb_command=NCBHANGUP;
        ncb.ncb_lsn=pncb->ncb_lsn;
        ncb.ncb_lana_num=pncb->ncb_lana_num;

        if(Netbios(&ncb)!=NRC_GOODRET)
        {
            printf("Error:Netbios:NCBHANGUP:%d/n",ncb.ncb_retcode);
            GlobalFree(pncb);
            dwRetVal=ncb.ncb_retcode;
        }
    }
    //
    //the NCB structure in is dynamically allocated,so
    //delete is before we go.
    //
    GlobalFree(pncb);
    return NRC_GOODRET;
}

 

//其中好几部都可以放在一个循环中,为了拆分步骤,有多个循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值