晚上睡不着,想着白天工作上的事,解决一个现场读卡问题就需要出趟差值得吗。想着在公司就能把现场的卡给读写诊断了,能让数据跑路就别让人跑路,说干就干。

本工具是在浏览器中以Lua脚本的形式对CPU卡,M1卡就行读、写等各种操作,配和使用改造过后的E711读卡器。

远端把读卡器接到电脑上,并运行读写卡服务。告知客户端IP地址和端口,并放上卡。客户端调用相关指令,运行脚本,输出结果。
    远程读卡器就是一个普通usb口或串口的读卡器,如E711读卡器。配合一个电脑软件作为tcp读写卡服务。这样可以在公司电脑上运行客户端程序连到服务器上,服务器端操控现场的读卡器。之前做保定公交老卡兼容,让现场寄卡过来,结果拖了好久,卡也没寄过来。说是卡片管理严格,老年卡,学生卡需要从系统上从新办卡。于是让现场同事配合抓下包,读取一下卡上数据,但现场同事连串口助手都没听说过,指望不上了。最后没办法,还是出差跑去一趟,做了些很简单的事。回来想想,其实可以做一个远程读卡器,在公司把现场的卡给操作了。再封装一些读卡的客户端接口,可以实现远程仿真调试程序读卡消费逻辑 ,或者实现一完全软件模拟的pos机。之前用java做过一个读写卡工具,但是只能在本地电脑上读写卡。

交通部卡测试消费成功的lua脚本指令:

--192.168.157.135/test3/runcode.php
--读卡服务地址
ip= "192.168.157.135"
--读卡服务端口
port = 5050--连接到读卡服务
ret = CONNECT(ip,port)                     --建立连接
-------------------------------------------  CPU卡操作
ret,rcv = S_SFI("\x3F\x00",1)              --选择PSAM卡应用3F00
ret,rcv = R_BFile(0x15,0,0,1)              --读取PSAM卡15文件
ret,rcv = R_BFile(0x16,0,0,1)              --读取PSAM卡16文件
if ret == 0x9000 thenPasmTID = string.sub(rcv,1,12)print("pasmTID:"..PasmTID)
endret,rcv = S_AID("\xA0\x00\x00\x06\x32\x01\x01\x05",0x08,0)      --选择交通部应用ret,rcv = R_BFile(0x15,0,0,0)              --读取卡片0x15文件
if ret == 0x9000 thenMakeCardId = string.sub(rcv,1,16)CardASN = string.sub(rcv,25,25+16-1)print(rcv)print("MakeCardId:"..MakeCardId)print("CardASN:"..CardASN)
end
ret,rcv = R_BFile(0x16,0,0,0)ret,rcv = R_BFile(0x17,0,0,0)    ret,rcv = S_SFI("\x80\x11",1)              --选择交通部PSAM卡应用ret,rcv = APDU("805C030204",0)              --读取余额--消费初始化
cmd = '805001020B'
index = '01'
money = '00000001'cmdstr = cmd..index..money..PasmTID
print("xiao fei chu shi hua:")
ret,rcv = APDU(cmdstr,0)   --消费初始化
if ret == 0x9000 thenPullCTC = string.sub(rcv,9,9+4-1)  --脱机交易序号KeyVer = string.sub(rcv,19,19+2-1)KeyDrk = string.sub(rcv,21,21+2-1)Icc =  string.sub(rcv,23,23+8-1)  --随机数print("PullCTC:"..PullCTC)print("KeyVer:"..KeyVer)print("KeyDrk:"..KeyDrk)print("Icc:"..Icc)
endcmd = '8070000024'
time ='20161128170231'
cmdstr = cmd..Icc..PullCTC..money..'06'..time..KeyVer..KeyDrk..CardASN..MakeCardId ret,rcv = APDU(cmdstr,1)   --PSAM卡算MACif ret == 0x9000 thenTTC = string.sub(rcv,1,8)  --脱机交易序号MAC1 = string.sub(rcv,9,9+8-1)print("TTC:"..TTC)print("MAC1:"..MAC1)
endcmd = '805401000F'
cmdstr = cmd..TTC..time..MAC1ret,rcv = APDU(cmdstr,0)DISCONNECT()                --断开连接

要远程读写卡得有个后台服务去操控远程的读卡器。有了后台读写卡服务,客户端不能只是接口,得简单好用,于是有了这个web端。

附截图:

截图1,运行效果

截图2,相关指令介绍:

截图3,后台文件

截图4,后台读写卡服务显示的收发日志:

后台的解析lua脚本的文件lua_test.c

//包含LUA的头文件,用来支持脚本
#include <stdio.h>
#include "lib/lua-5.3.1/lua.h"
#include "lib/lua-5.3.1/lualib.h"
#include "lib/lua-5.3.1/lauxlib.h"   #include "lib/includes.h"#define PICC_ADD                    0xC1            //加
#define PICC_SUB                    0xC0            //减
#define PICC_RESTORE                0xC2            //恢复#define PICC_KEYA                   0x60            //KEY A
#define PICC_KEYB                   0x61            //KEY B#define PICC_NULL                   0x00            //不校验KEYlua_State* L;  U08 gCardSN[8]; //物理卡号U32 ICF_SelectAID( const char *AID, U32 ilen, U32 ich )
{U32 rcode;gCmdBuffer[0] = 0x00;   //CLAgCmdBuffer[1] = 0xA4;   //INSgCmdBuffer[2] = 0x04;   //P1gCmdBuffer[3] = 0x00;   //P2gCmdBuffer[4] = ilen;   //LcCurCalc_DataCpy( gCmdBuffer+5, (U08*)AID, ilen );rcode = ICC_APDU_Exchange( ich, gCmdBuffer, ilen+5, gpRcvBuffer, &Grcv_Len, 260 );if( rcode != 0 ){ return rcode; }if( Grcv_Len < 2 )  { return 2;}rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );return rcode;}
U32 ICF_SelectSFI( const char *SFI, U32 ich )
{U32 rcode;gCmdBuffer[0] = 0x00;   //CLAgCmdBuffer[1] = 0xA4;   //INSgCmdBuffer[2] = 0x00;   //P1gCmdBuffer[3] = 0x00;   //P2gCmdBuffer[4] = 0x02;   //LcCurCalc_DataCpy( gCmdBuffer+5, (U08*)SFI, 2 );rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 2+5, gpRcvBuffer, &Grcv_Len, 260 );if( rcode != 0 ){ return rcode; }if( Grcv_Len < 2 ){ return 2;}rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );return rcode;
}
U32 ICF_ReadBinaryFile( U08 SFI, U08 Offset, U08 BytesToRead, U32 ich )
{unsigned short rcode;gCmdBuffer[0] = 0x00;   //CLAgCmdBuffer[1] = 0xB0;   //INSgCmdBuffer[2] = 0x80 | ( SFI & 0x1F );  //P1gCmdBuffer[3] = Offset; //P2gCmdBuffer[4] = BytesToRead;    //Lercode = ICC_APDU_Exchange( ich, gCmdBuffer, 5, gpRcvBuffer, &Grcv_Len, 260 );if( rcode != 0 ){ return rcode; }if( Grcv_Len < 2 )                                          //长度判断{ return 2;}rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );return rcode;
}int LConnect(lua_State* L)
{int ret = 0;size_t le = 0;printf("Connecting...\n");const char * ipaddr = luaL_checklstring(L,1,&le);//printf("cmd is %s,le is %d\n",aid,le);  //从L栈中取出索引为2的数值,并检查  int port = luaL_checkinteger(L,2); printf("ServerIP:%s,Port:%d\n", ipaddr,port);ret = Connect(ipaddr,port);lua_pushnumber(L,ret); return 1;
}int LDisConnect(lua_State* L)
{printf("Close connect!\n");Com_Dev_Disconnect( 0 );  return 1;
}int LTxData(lua_State* L)
{int ret = 0;unsigned int len = 0;size_t le = 0;unsigned char buf[1024];unsigned char outbuf[2048];memset(buf, 0, 1024);memset(outbuf, 0, 2048);//从L栈中取出索引为1的数值,并检查  const char * txdata = luaL_checklstring(L,1,&le);//printf("tx is %s,le is %d\n",txdata,le);  StrToHex( (char*)txdata, le, buf );ret = Com_Dev_TxData( buf, le/2, 0, 0 );if( ret != 0 ){ DEF_SysCard_Debug; return ret; }ret = Com_Dev_RxData( buf, &len,  1024, 0, 0 ); if( ret != 0 ){ DEF_SysCard_Debug; return ret; }HexToStr(buf,len,(char*)outbuf);lua_pushinteger(L,ret); lua_pushlstring(L,(char*)outbuf,strlen((char*)outbuf));return 2;}int LTxData1(lua_State* L)
{int ret = 0;unsigned int len = 0;size_t le = 0;unsigned char buf[1024];unsigned char outbuf[2048];memset(buf, 0, 1024);memset(outbuf, 0, 2048);//从L栈中取出索引为1的数值,并检查  const char * txdata = luaL_checklstring(L,1,&le);// printf("tx is %s,le is %d\n",txdata,le);  //StrToHex( (char*)txdata, le, buf );ret = Com_Dev_TxData1( (unsigned char*)txdata, le, 0, 0 );if( ret != 0 ){ DEF_SysCard_Debug; return ret; }ret = Com_Dev_RxData1( buf, &len,  1024, 0, 0 ); if( ret != 0 ){ DEF_SysCard_Debug; return ret; }//HexToStr(buf,len,(char*)outbuf);lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf,len);return 2;}
int LAPDU_Exchange(lua_State* L)
{int ret = 0;size_t le = 0;unsigned char buf[520];memset(buf, 0, 520);//从L栈中取出索引为1的数值,并检查  const char * cmd = luaL_checklstring(L,1,&le);//printf("cmd is %s,le is %d\n",aid,le);  //从L栈中取出索引为2的数值,并检查  int ich = luaL_checkinteger(L,2); StrToHex( (char*)cmd, le, gCmdBuffer );ret = ICC_APDU_Exchange( ich, gCmdBuffer, le/2, gpRcvBuffer, &Grcv_Len, 260 );if( Grcv_Len < 2){ return 1;}ret = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );HexToStr(gpRcvBuffer,Grcv_Len,(char*)buf);lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf,strlen((char*)buf));return 2;
}
int LSelectAID(lua_State* L)
{int ret = 0;size_t le = 0;unsigned char buf[520];memset(buf, 0, 520);//从L栈中取出索引为1的数值,并检查  const char * aid = luaL_checklstring(L,1,&le);//printf("aid is %s,le is %d\n",aid,le);  //从L栈中取出索引为2的数值,并检查  int len = luaL_checkinteger(L,2); int ich = luaL_checkinteger(L,3); ret = ICF_SelectAID( aid, len, ich );HexToStr(gpRcvBuffer,Grcv_Len,(char*)buf);lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf,strlen((char*)buf));return 2;}int LSelectSFI(lua_State* L)
{int ret = 0;size_t le = 0;unsigned char buf[520];memset(buf, 0, 520);//从L栈中取出索引为1的数值,并检查  const char * sfi = luaL_checklstring(L,1,&le);//printf("aid is %s,le is %d\n",aid,le);  //从L栈中取出索引为2的数值,并检查  int ich = luaL_checkinteger(L,2); ret = ICF_SelectSFI( sfi, ich );HexToStr(gpRcvBuffer,Grcv_Len,(char*)buf);lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf,strlen((char*)buf));return 2;}
int LReadBinaryFile( lua_State* L )
{int ret = 0;unsigned char buf[520];memset(buf, 0, 520);//从L栈中取出索引为1的数值,并检查  int sfi =  luaL_checkinteger(L,1); int oft =  luaL_checkinteger(L,2);int rlen = luaL_checkinteger(L,3);int ich =  luaL_checkinteger(L,4); ret = ICF_ReadBinaryFile(sfi,oft,rlen,ich);HexToStr(gpRcvBuffer,Grcv_Len,(char*)buf);lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf,strlen((char*)buf));//stackDump(L);return 2;
}
//获取CPU或M1卡的物理卡号
int LGetPhySn( lua_State* L )
{int ret = 0;unsigned char buf[20];unsigned char buf1[20];memset(buf,0,20);memset(buf1,0,20);ret = ICC_MiOne_GetPhySn(buf);memcpy(gCardSN,buf,8);//保存全局物理卡号HexToStr(buf,8,(char*)buf1);lua_pushinteger(L,ret); lua_pushlstring(L,(char*)buf1,strlen((char*)buf1));//stackDump(L);return 2;
}
//M1卡扇区读
int LBlkRead( lua_State* L )
{int ret = 0;size_t le = 0;unsigned char rbuf[50];unsigned char sbuf[50];unsigned char key[16];unsigned char cmd=0;int block   =  luaL_checkinteger(L,1); const char * keys = luaL_checklstring(L,2,&le);int keytype =  luaL_checkinteger(L,3); //密码类型,0,不校验 1,A码,2,B码memset(rbuf,0,50);memset(sbuf,0,50);StrToHex( (char*)keys, le, key );cmd = PICC_KEYA;if(keytype == 1){ cmd = PICC_KEYA; }else if(keytype == 2){ cmd = PICC_KEYB; }ret = ICC_MiOne_BlkRead(block,cmd,key, gCardSN, rbuf );HexToStr(rbuf,16,(char*)sbuf);lua_pushinteger(L,ret); lua_pushlstring(L,(char*)sbuf,strlen((char*)sbuf));//stackDump(L);return 2;
}//M1卡扇区写
int LBlkWrite( lua_State* L )
{int ret = 0;size_t le = 0,le1 =0;unsigned char wbuf[50];unsigned char key[16];unsigned char cmd=0;int block   =  luaL_checkinteger(L,1); const char * wbufs = luaL_checklstring(L,2,&le);const char * keys = luaL_checklstring(L,3,&le1);int keytype =  luaL_checkinteger(L,4); //密码类型,0,不校验 1,A码,2,B码memset(wbuf,0,50);StrToHex( (char*)wbufs, le, wbuf );StrToHex( (char*)keys, le1, key );cmd = PICC_KEYA;if(keytype == 1){ cmd = PICC_KEYA; }else if(keytype == 2){ cmd = PICC_KEYB; }ret = ICC_MiOne_BlkWrite(block,cmd,key, gCardSN, wbuf );lua_pushinteger(L,ret); //stackDump(L);return 1;
}//DES加密
int LDES_Encrypt( lua_State* L )
{// int ret = 0;size_t le = 0,le1 =0;unsigned char inkey[16];unsigned char indata[16];unsigned char outdata[16];unsigned char str_out[50];const char * str_inkey = luaL_checklstring(L,1,&le);const char * str_indata = luaL_checklstring(L,2,&le1);StrToHex( (char*)str_inkey, le, inkey );StrToHex( (char*)str_indata, le1, indata );CurCalc_DES_Encrypt( inkey, indata, outdata );HexToStr(outdata,8,(char*)str_out);//lua_pushinteger(L,ret); lua_pushlstring(L,(char*)str_out,16);//stackDump(L);return 1;
}//DES解密
int LDES_Decrypt( lua_State* L )
{// int ret = 0;size_t le = 0,le1 =0;unsigned char inkey[16];unsigned char indata[16];unsigned char outdata[16];unsigned char str_out[50];const char * str_inkey = luaL_checklstring(L,1,&le);const char * str_indata = luaL_checklstring(L,2,&le1);StrToHex( (char*)str_inkey, le, inkey );StrToHex( (char*)str_indata, le1, indata );CurCalc_DES_Decrypt( inkey, indata, outdata );HexToStr(outdata,8,(char*)str_out);//lua_pushinteger(L,ret); lua_pushlstring(L,(char*)str_out,16);//stackDump(L);return 1;
}//3DES加密
int LDES_3Encrypt( lua_State* L )
{// int ret = 0;size_t le = 0,le1 =0;unsigned char inkey[16];unsigned char indata[16];unsigned char outdata[16];unsigned char str_out[50];const char * str_inkey = luaL_checklstring(L,1,&le);const char * str_indata = luaL_checklstring(L,2,&le1);StrToHex( (char*)str_inkey, le, inkey );StrToHex( (char*)str_indata, le1, indata );CurCalc_3DES_Encrypt( inkey, indata, outdata );HexToStr(outdata,16,(char*)str_out);//lua_pushinteger(L,ret); lua_pushlstring(L,(char*)str_out,32);//stackDump(L);return 1;
}//3DES解密
int LDES_3Decrypt( lua_State* L )
{// int ret = 0;size_t le = 0,le1 =0;unsigned char inkey[16];unsigned char indata[16];unsigned char outdata[16];unsigned char str_out[50];const char * str_inkey = luaL_checklstring(L,1,&le);const char * str_indata = luaL_checklstring(L,2,&le1);StrToHex( (char*)str_inkey, le, inkey );StrToHex( (char*)str_indata, le1, indata );CurCalc_3DES_Decrypt( inkey, indata, outdata );HexToStr(outdata,16,(char*)str_out);//lua_pushinteger(L,ret); lua_pushlstring(L,(char*)str_out,32);//stackDump(L);return 1;
}U32 MathDesMac( U08 *pbuf, U32 length, U08 *key,U08 checktype )
{U32 len ;U08 mac[8], mac1[8];len = length ;if( checktype == 0 ){CurCalc_DES_MAC64( (SINGLE_DES_ENCRYPTION|ZERO_CBC_IV), key, 0, pbuf, len ,  mac );memcpy( pbuf+len, mac, 8 );return 0 ;}else{//暂存源校验码memcpy( mac1, pbuf+len-8, 8 ) ; CurCalc_DES_MAC64( (SINGLE_DES_ENCRYPTION|ZERO_CBC_IV), key, 0, pbuf, len-8 ,  mac) ; if ( memcmp( mac, mac1, 8 ) == 0x00 ){return 0 ;        //校验产生的校验码和原校验码相等, 校验成功}else{return 1 ;     //校验产生的校验码和原校验码不等, 校验失败}}
}int LMathDesMac( lua_State* L )
{int ret = 0;size_t le = 0,le1 =0;unsigned char inkey[16];unsigned char indata[1024];unsigned char str_out[2048];const char * str_indata = luaL_checklstring(L,1,&le);int   inlen   =  luaL_checkinteger(L,2);const char * str_inkey = luaL_checklstring(L,3,&le1);int   type   =   luaL_checkinteger(L,4);StrToHex( (char*)str_indata, le, indata );StrToHex( (char*)str_inkey, le1, inkey );ret = MathDesMac( indata, inlen,inkey,type );memset(str_out,0,2048);HexToStr(indata,inlen+8,(char*)str_out);lua_pushinteger(L,ret); lua_pushlstring(L,(char*)str_out,strlen((char*)str_out));//stackDump(L);return 1;
}
int main( void )
{  //初始化全局L  L = luaL_newstate();  //创建lua的栈 //打开库  luaL_openlibs(L);  //把函数压入栈中  //lua_pushcfunction(L, add);  //设置全局ADD  //lua_setglobal(L, "ADD");  //lua_register(L,"ADD",add);lua_pushcfunction(L, LConnect);  //设置全局ADD  lua_setglobal(L, "CONNECT"); lua_register(L,"DISCONNECT", LDisConnect); lua_register(L,"TxData",LTxData);lua_register(L,"TxData1",LTxData1);lua_register(L,"APDU", LAPDU_Exchange);  lua_register(L,"S_AID",LSelectAID); lua_register(L,"S_SFI",LSelectSFI); lua_register(L,"R_BFile",LReadBinaryFile);lua_register(L,"G_SN",LGetPhySn);lua_register(L,"R_Block",LBlkRead);lua_register(L,"W_Block",LBlkWrite);lua_register(L,"DES_Enc",LDES_Encrypt);lua_register(L,"DES_Dec",LDES_Decrypt);lua_register(L,"DES_3Enc",LDES_3Encrypt);lua_register(L,"DES_3Dec",LDES_3Decrypt);lua_register(L,"MathDesMac",LMathDesMac);//加载我们的lua脚本文件  if(luaL_loadfile(L,"test.lua"))  //载入lua脚本,是通过fopen打开的,{  printf("error,failed to analysis script!\nmaybe syntax error!\n");  }  //安全检查  lua_pcall(L,0,0,0); //这个函数会执行lua脚本 //push进lua函数  // lua_getglobal(L, "mylua1"); // lua_pcall(L,0,0,0);   printf("end my lua script,finish!\n"); lua_close(L); //关闭lua的栈  return 0;
}  

php后台的处理原理:

compile.php

<?php
header('Content-Type:json; charset=UTF-8');
set_time_limit(0);
//var_dump($_POST);
$str= $_POST['code'];
//echo $str;
file_put_contents("test.lua",$str);$flv_cmd="lua_test.exe >out.txt";
exec($flv_cmd);if(file_exists("out.txt"))
{$txt1 = file_get_contents("out.txt");$err ="ok";$txt =iconv("GB2312","UTF-8//IGNORE",$txt1); //将编码从GB2312转成UTF-8//echo $txt;
}
else
{$txt ="output err!\n";$err ="exec err!\n";
}
$json = array("output"=>$txt,"langid"=>"17","code"=>"print(\"Hello World!\")","errors"=>$err,"time"=>"01\n");
//var_dump($json);
$result = json_encode($json);
//var_dump($result);
$output = $result;
echo $output;
?>

后台库文件的makefile:

########################################
#makefile
########################################

#编译主程序
BINARY  := lua_test
OBJ_DIR := 
CC= gcc
LD= ld
CFLAGS= -std=c99 -Wall -g
LDSCRIPT= -lmycom -lws2_32 -liconv -lmyfile  -lmycard -lmyup -lmycalc -lmyblkfile -llua
LDFLAGS= -Llib

SRC  = $(wildcard *.c)
DIR  = $(notdir $(SRC))
OBJS = $(patsubst %.c,$(OBJ_DIR)%.o,$(DIR))
#OBJS=  main.o myutils.o  inirw.o  cmdpboc.o cputest.o bustcp.o ansrec.o m1cmd.o m1api.o m1test.o upcash.o myother.o getsys.o
#CFLAGS=-std=c99
#@echo Building lib...
#$(call make_subdir)
.PHONY: clean lib
all:  prebuild  $(BINARY).exe

prebuild:
@echo Building app...

$(BINARY).exe : $(OBJS)
@echo Generating ...
$(CC) -o $(BINARY).exe $(OBJS) $(LDFLAGS) $(LDSCRIPT) 
@echo OK!

$(OBJ_DIR)%.o : %.c
$(CC) -c $(CFLAGS) $< -o  $@

clean:
rm -f $(OBJ_DIR)*.o
@echo Removed!

我的小工具-远程读卡器web客户端(PHP+LUA)相关推荐

  1. 远程读卡器web客户端(nodejs+websocket实现实时指令交互)

    工具目的:在公司对现场的卡片进行测卡,读写卡测试,远程诊断卡片问题,快速定位和解决现场问题. 之前的那一个版本的小工具,远程读卡器web客户端,实现原理是把读写卡服务装在远程(现场)的电脑上,这样有一 ...

  2. IDEA的好用小工具Test RESTful web Service

    Test RESTful web Service 一.2021版IDEA界面 二.2019版(我安了个插件叫Old REST Client来还原这个样子) 三.代码demo示例 补充 好处: -可以减 ...

  3. websphere使用_使用WebSphere sMash为Google小工具提供动力

    websphere使用 存档日期:2019年5月16日 | 首次发布:2008年6月4日 IBM®WebSphere®sMash提供了多种方法来共享Web 2.0应用程序中的信息. 本文介绍了如何从头 ...

  4. portlet_平台策略:从Portlet到OpenSocial小工具再到渐进式Web应用程序:最新技术

    portlet 介绍 由于世界仍在Java的掌控之中,因此我们经常定义所谓的基于组件的平台 . 我在2000年拥有OpenUSS(开放大学支持系统)的经验. 当时我有一个想法,就是开发一个可以使用组件 ...

  5. 平台策略:从Portlet到OpenSocial小工具再到渐进式Web应用程序:最新技术

    介绍 由于世界仍在Java的掌控之中,因此我们经常定义所谓的基于组件的平台 . 我在2000年的OpenUSS(开放大学支持系统)方面拥有这一经验. 当时我有一个想法,就是开发一个可以使用组件体系结构 ...

  6. 【移动端debug-6】如何做一个App里的web调试小工具

    原文链接:如何做一个App里的web调试小工具 我们知道现在hybrid app非常流行,在这样的app里,h5页面是应用非常广泛的.相对于以往在pc端开发的网页,放在app里的网页由于无法直接使用桌 ...

  7. python写一个ssh工具_用Python写个自动ssh登录远程服务器的小工具

    很多时候我们喜欢在自己电脑的终端直接ssh连接Linux服务器,而不喜欢使用那些有UI界面的工具区连接我们的服务器.可是在终端使用ssh我们每次都需要输入账号和密码,这也是一个烦恼,所以我们可以简单的 ...

  8. PL/SQL 工具远程连接Oracle数据库方法,plsql免安装oracle客户端直接配置oci实战演示

    PL/SQL 工具远程连接 Oracle 数据库 第一章:PL/SQL 工具配置 ① oci 下载 ② oci 配置 ③ PL/SQL 工具配置 ④ PL/SQL 远程连接 Oracle 数据库演示 ...

  9. Python3下Web下载媒体小工具(常用来下B站视频)

    Python3下Web下载媒体小工具(常用来下B站视频) 项目地址:https://github.com/soimort/you-get 使用条件 需要以下依赖项: Python 3.2或以上 FFm ...

最新文章

  1. 认识计算机系统反思,《认识计算机系统》教学反思
  2. 等价类、边界值的概念及划分
  3. Linux系统分析之启动流程
  4. 五、MongoDB的索引
  5. rewrite 伪静态,地址重写
  6. 有趣c语言编程经典例子,C语言简单有趣例子总结ZWF.pdf
  7. 西南科技计算机在线自测,西南科技大学2017春季第一学期高等数学1在线自测答案...
  8. 面试题:如何设计一个高并发的系统?
  9. jodd忽略ssl证书_关于java访问https资源时,忽略证书信任问题
  10. 华为入局 VR 眼镜能让 VR 早普及几年?|CSDN博文精选
  11. Activity详解 Intent显式跳转和隐式跳转, 及多个Activity之间传值 总结
  12. JavaWeb将图片显示在浏览器中
  13. 利用动态图层实现数据的实时显示
  14. 老Java程序员花一天时间写了个飞机大战,很舒服!
  15. 工作感想-软件测试工程师
  16. java 码表_java IO之 编码 (码表 编码 解码 转换流)
  17. Tomcat调优指南
  18. java 架构发展历史_Java架构发展历程与Spring简介
  19. 一份完整的app产品运营推广方案,app推广运营的方法(一)
  20. 导入自定义archetype

热门文章

  1. 月圆夜,又中秋,抽个奖,祝好运。
  2. DELIMA V5R20 64位安装包
  3. Android项目:手机安全卫士(7)—— 手机防盗功能
  4. 【USB接口电涌是什么故障】
  5. 儿童服装(童装)销售网站的设计与实现(ASP,SQLServer)(含录像)
  6. css的background属性连写
  7. Seafile共享网盘搭建
  8. 揭秘智慧工厂技术创新,自动化生产高质高效
  9. 苹果4是android吗,为什么安卓手机只能用两年,而苹果可以用四年?
  10. NFT将成为美妆品牌迈入元宇宙的“发力点”