13.3IC卡应用IC(IntegratedCircuit)卡,也被称作智能卡(SmartCard),具有写入数据和存储数据的功能,IC卡内存储器的内容可以根据需要有条件地供外部读取,完成信息处理和判定。由于其内部具有集成电路,不但可以存储大量信息,具有极强的保密性能,并且还具有抗干扰、无磨损、寿命长等特性。因此在各个领域中得到广泛应用。下面通过两个实例介绍IC卡的简单应用。实例422向IC卡中写入数据实例说明IC卡是携带应用信息和数据的媒体,空白IC卡是不能立即使用的,必须对IC卡应用系统进行初始化,写入系统IC卡和个人密码,个人专用信息和应用数据。下面介绍如何向IC卡中写入数据。运行本例,在“数据”文本框中输入要存入IC卡中的数据,单击“写数据”按钮,即可将输入的数据写入IC卡中。如图13.6所示。技术要点本例使用的是深圳明华生产的明华IC卡读写器,用户在使用时将驱动程序安装完毕后,即可正常使用本系统。本例通过调用Mwic_32.dll链接库,进行IC卡的读写工作。下面介绍与IC卡写操作相关的几个函数。(1)auto_init函数该函数用于初始化IC卡读卡器。语法如下:publicstaticexternintauto_init(intport,intbaud);参数说明如下。lport:标识端口号,Com1对应的端口号为0;Com2对应的端口号为1,依此类推。lbaud:标识波特率。l返回值:如果初始化成功,返回值是IC卡设备句柄;如果初始化失败,返回值小于零。(2)setsc_md函数该函数用于设置设备密码模式。语法如下:publicstaticexternintsetsc_md(inticdev,intmode);参数说明如下。licdev:标识设备句柄,通常是auto_init函数的返回值。lmode:标识设备密码模式,如果为0,设备密码有效,设备在加电时必须验证设备密码才能对设备进行操作。如果为1,设备密码无效。l返回值:如果函数执行成功返回值为零,否则小于零。(3)get_status函数该函数用于获取设备的当前状态。语法如下:publicstaticexternInt16get_status(inticdev,Int16*state);参数说明如下。licdev:标识设备句柄,通常是auto_init函数的返回值。lstate:用于接收函数返回的结果。如果为0表示读卡器中无卡,为1表示读卡器中有卡。l返回值:如果函数执行成功返回值为零,否则小于零。(4)csc_4442函数该函数用于核对IC卡密码。语法如下:publicstaticexternInt16Csc_4442(inticdev,intlen,[MarshalAs(UnmanagedType.LPArray)]byte[]p_string);参数说明如下。licdev:标识设备句柄,通常是auto_init函数的返回值。llen:标识密码长度,其值为3。lp_string:标识设置的密码。l返回值:如果函数执行成功返回值为零,否则小于零。(5)swr_4442函数该函数用于向IC卡中写入数据。语法如下:publicstaticexternintswr_4442(inticdev,intoffset,intlen,char*w_string);参数说明如下。licdev:标识设备句柄,通常是auto_init函数的返回值。loffset:标识地址的偏移量,范围是0~255。llen:标识字符串长度。lw_string:标识写入的数据。(6)ic_exit函数该函数用于关闭设备端口。语法如下:publicstaticexternintic_exit(inticdev);参数说明如下。licdev:标识设备句柄,通常是auto_init函数的返回值。(7)dv_beep函数该函数使读卡器嗡鸣。语法如下:publicstaticexternintdv_beep(inticdev,inttime);参数说明如下。licdev:标识设备句柄,通常是auto_init函数的返回值。ltime:标识嗡鸣持续的时间,单位是10毫秒。实现过程(1)新建一个项目,命名为Ex13_05,默认窗体为Form1。(2)在Form1窗体中,主要添加两个Button控件,用于执行向卡中写入数据和退出程序的操作,添加一个TextBox控件,将TextBox中数据写入IC卡中。(3)主要程序代码。将程序所使用的操作IC卡的函数,封装在类IC中。代码如下:[StructLayout(LayoutKind.Sequential)]publicunsafeclassIC{//对设备进行初始化[DllImport(Mwic_32.dll,EntryPoint=auto_init,SetLastError=true,CharSet=CharSet.Ansi,ExactSpelling=true,CallingConvention=CallingConvention.StdCall)]publicstaticexternintauto_init(intport,intbaud);//设备密码格式[DllImport(Mwic_32.dll,EntryPoint=setsc_md,SetLastError=true,CharSet=CharSet.Ansi,ExactSpelling=true,CallingConvention=CallingConvention.StdCall)]publicstaticexternintsetsc_md(inticdev,intmode);//获取设备当前状态[DllImport(Mwic_32.dll,EntryPoint=get_status,SetLastError=true,CharSet=CharSet.Ansi,ExactSpelling=true,CallingConvention=CallingConvention.StdCall)]publicstaticexternInt16get_status(inticdev,Int16*state);//关闭设备通讯接口[DllImport(Mwic_32.dll,EntryPoint=ic_exit,SetLastError=true,CharSet=CharSet.Ansi,ExactSpelling=true,CallingConvention=CallingConvention.StdCall)]publicstaticexternintic_exit(inticdev);//使设备发出蜂鸣声[DllImport(Mwic_32.dll,EntryPoint=dv_beep,SetLastError=true,CharSet=CharSet.Ansi,ExactSpelling=true,CallingConvention=CallingConvention.StdCall)]publicstaticexternintdv_beep(inticdev,inttime);//向IC卡中写数据[DllImport(Mwic_32.dll,EntryPoint=swr_4442,SetLastError=true,CharSet=CharSet.Ansi,ExactSpelling=true,CallingConvention=CallingConvention.StdCall)]publicstaticexternintswr_4442(inticdev,intoffset,intlen,char*w_string);//核对卡密码[DllImport(Mwic_32.dll,EntryPoint=csc_4442,SetLastError=true,CharSet=CharSet.Auto,ExactSpelling=true,CallingConvention=CallingConvention.Winapi)]publicstaticexternInt16Csc_4442(inticdev,intlen,[MarshalAs(UnmanagedType.LPArray)]byte[]p_string);}下面代码主要用于将TextBox中数据写入到IC卡中。代码如下:privatevoidbutton1_Click(objectsender,EventArgse){//初始化inticdev=IC.auto_init(0,9600);if(icdev0)MessageBox.Show(端口初始化失败,请检查接口线是否连接正确。,错误提示,MessageBoxButtons.OK,MessageBoxIcon.Information);intmd=IC.setsc_md(icdev,1);//设备密码格式unsafe{Int16status=0;Int16result=0;result=IC.get_status(icdev,&status);if(result!=0){MessageBox.Show(设备当前状态错误!);intd1=IC.ic_exit(icdev);//关闭设备return;}if(status!=1){MessageBox.Show(请插入IC卡);intd2=IC.ic_exit(icdev);//关闭设备return;}}unsafe{//卡的密码默认为6个f(密码为:ffffff),1个f的16进制是15,两个f的16进制是255byte[]pwd=newbyte[3]{255,255,255};//byte[]pwd=newbyte[3]{0xff,0xff,0xff};//char[]pass=newch{0xff,0xff,0xff};Int16checkIC_pwd=IC.Csc_4442(icdev,3,pwd);if(checkIC_pwd0){MessageBox.Show(IC卡密码错误!);return;}charstr='a';intwrite=-1;for(intj=0;jtextBox1.Text.Length;j++){str=Convert.ToChar(textBox1.Text.Substring(j,1));write=IC.swr_4442(icdev,33+j,textBox1.Text.Length,&str);}if(write==0){intbeep=IC.dv_beep(icdev,20);//发出蜂鸣声MessageBox.Show(数据已成功写入IC卡中!);}elseMessageBox.Show(数据写入IC卡失败!);}intd=IC.ic_exit(icdev);//关闭设备}举一反三根据本实例,读者可以实现以下功能。在图书借阅中使用IC卡。利用IC卡控制上网。实例423读取IC卡中的数据实例说明向IC卡写入数据后,就可以进行读卡操作了。运行本例,将写入数据的IC卡插入读卡器,单击【读卡】按钮,IC卡中的数据将显示在文本框中。如图13.7所示。技术要点本例中主要调用srd_4442函数读取IC卡中的数据,相关函数介绍请参考实例“向IC卡中写入数据”中的“技术要点”部分。这里只介绍读卡函数。qsrd_4442函数该函数用于读取IC卡中的数据。语法如下:publicstaticexternintsrd_4442(inticdev,intoffset,intlen,char*r_string);参数说明如下。licdev:标识设备句柄,通常是auto_init函数的返回值。loffset:标识地址的偏移量,范围是0~255。llen:标识字符串长度。lr_string:用于存储返回的数据。实现过程(1)新建一个项目,命名为Ex13_06,默认窗体为Form1。(2)在Form1窗体中,主要添加两个Button控件,用于读取卡中的数据和退出程序,添加一个TextBox控件,显示卡中的数据。(3