重点介绍“Netsuite.DLL V1.05”的几个函数
*RSA------------
*注意错误会直接抛出
Local loRSA ;
, lnKeySize;
, xml ;
, pem_pkcs1;
, pem_pkcs8
*从DLL中获取RSA
m.lnKeySize = 512 &&1024
m.loRSA = oFunction.GetRSA( m.lnKeySize )
Clear
?Transform(lnKeySize) + '私钥(xml):'
xml = m.loRSA.ToXML()
??xml
?Transform(lnKeySize) + '私钥(PKCS#1):' &&用于解密(加密需要私钥需要最强大的第三方DLL....)
pem_pkcs1 = m.loRSA.ToPEM().ToPEM_PKCS1()
?pem_pkcs1
?Transform(lnKeySize) + '公钥(PKCS#8):' &&用于加密
pem_pkcs8 = m.loRSA.ToPEM().ToPEM_PKCS8()
?pem_pkcs8
?'RSA待加密字符串:'
m.lcstr = 'Netsuite.Function For ZHZ V1.0'
??m.lcstr
?'RSA加密:'
Local lcenstr
m.lcenstr = m.loRSA.Encode( m.lcstr )
??m.lcenstr
?'RSA解密:'
m.lcdestr = m.loRSA.DecodeOrNull( m.lcenstr)
??m.lcdestr
?'签名SHA1:'
Local lcsign
m.lcsign = m.loRSA.Sign("SHA1", m.lcstr )
??m.lcsign
*m.loRSA.Sign("SHA224", m.lcstr )没有,以后再补
*m.loRSA.Sign("SHA256", m.lcstr )有
*m.loRSA.Sign("SHA384", m.lcstr )没有,以后再补
*m.loRSA.Sign("SHA512", m.lcstr )没有,以后再补
*m.loRSA.Sign("SHA3" , m.lcstr )没有,以后再补
??m.lcsign
?'校验签名:'
??m.loRSA.Verify("SHA1", m.lcsign, m.lcstr)
*用pem文本创建RSA
Local loRSA2
m.loRSA2= oFunction.GetRSA2( pem_pkcs8 )
?'用PEM公钥(PKCS#8)新创建的RSA是否和上面的一致:'
?'XML:'
??m.loRSA2.ToXML() == m.loRSA.ToXML()
?'PKCS1:'
??m.loRSA2.ToPEM().ToPEM_PKCS1() == m.loRSA.ToPEM().ToPEM_PKCS1()
?'PKCS8:'
??m.loRSA2.ToPEM().ToPEM_PKCS8() == m.loRSA.ToPEM().ToPEM_PKCS8()
*用xml文本创建RSA
Local loRSA3
m.loRSA3= oFunction.GetRSA3( xml )
?'用xml文本新创建的RSA是否和上面的一致:'
?'XML:'
??m.loRSA3.ToXML() == m.loRSA.ToXML()
?'PKCS1:'
??m.loRSA3.ToPEM().ToPEM_PKCS1() == m.loRSA.ToPEM().ToPEM_PKCS1()
?'PKCS8:'
??m.loRSA3.ToPEM().ToPEM_PKCS8() == m.loRSA.ToPEM().ToPEM_PKCS8()
*--声音播放函数(异步线程(默认) )
*--载入H文件
#INCLUDE Netsuite.H
Local loDevice ;
, lisTask ;
, lcFileName
m.lcFileName = Getfile("mp3,wav")
m.lisTask = .T.
If Empty( m.lcFileName ) Then
Return
Endif
*--播放声音
*m.oFunction.MmPaly( cFile, lisTask ) &&可以异步,同步
*cFile 必传 文件路径
*lisTask 非必传 默认.T.异步线程|.F. 同步线程
m.loDevice = m.oFunction.MmPaly( m.lcFileName , m.lisTask )
*--判定
?"已停止:" + Transform( m.loDevice.PlaybackState = Stopped )
?"正在播放:" + Transform( m.loDevice.PlaybackState = Playing )
?"暂停中:" + Transform( m.loDevice.PlaybackState = Paused )
*--动作
*!* m.loDevice.Play() &&播放
*!* m.loDevice.Pause()&&暂停
*!* m.loDevice.Stop &&停止
*--文本转语音播报(默认异步线程),其实就是Edge的大声朗读,遗憾C# WebSocket不支持Win7平台
*m.oFunction.Say( string str,string voice,string outfilename ="say.mp3", bool isTask = true)
*str 必传 文本
*voice 非必传 哪个M播音员 默认 "zh-CN-XiaoxiaoNeural"
*OutFileName 非必传 输出音频 默认DLL所在目录下say.mp3
*isTask 非必传 默认.T.异步线程|.F. 同步线程
oSay = m.oFunction.Say("今天天气真他妈热啊!")
*--需要Netsuite.dll V1.05版支持(WebSocketsServer DLL 多线程同步,可高并,VFP 单线程 )
*--不依赖于HttpListener或HTTP.sys意味着他将在Windows 7和Server 2008主机上运行
*--说明:实现了双向通信,可以让服务端向客户端进行主动发起通信;
不仅仅可以实现点对点的通信,;
同时还可以实现群聊的形式。可以通过一定的逻辑;
将用户发出的信息在服务端进行组播,从而实现同一聊天室内的多人通信
*可以使用wss安全协议服务,需要证书
*WebsocketServer事件化且绑定了events.prg 类“WebSocketsEvents”的委托方法,如 OnMessage,祥请查看“events.prg”
*--websocket_html5test.html 用于Web模拟Client端H5测试
*--websocket_htmlJstest 用于Web模拟Client端Js测试
Clear
If _vfp.StartMode = 0 Then
m.lcPath = Justpath( _vfp.ActiveProject.Name )
Else
m.lcPath = Justpath( sys(16,0) )
Endif
Set Default To ( m.lcPath )
*--载入WebSocket事件
Set Procedure To Events.prg , netsuite.reg.prg Additive
Public oWebSocketsServer
m.oWebSocketsServer = Createobjects( "Netsuite.WebSockets")
Local lcUrl ;
, lcpfxFilePath ;
, lcpfxPassword
m.lcUrl = "ws://0.0.0.0:30000" &&"wss://0.0.0.0:30000"
*Start(string cUrl , string pfxFilePath ="", string pfxPassword = "")
* pfxFilePath 非必传 只有Url为Wss使用证书路径
* pfxPassword 非必传 只有Url为Wss使用证书密码
m.oWebSocketsServer.Start( "ws://0.0.0.0:30000" )
public loServer
m.loServer = oWebSocketsServer.Server
With m.loServer
?.Location
?.Port
?.SupportDualStack
?.ListenerSocket.Connected
?.EnabledSslProtocols
?.SupportDualStack
Endwith
With m.oWebSocketsServer
* .Send( String ClientID , String Msg) 发送信息 &&return bool .T. 成功|.F.失败
* .CloseAllConnect() 关闭所有Client连接
* .CloseUserConnect( ClientID) 关闭对应的Client连接 &&return bool .T. 成功|.F.失败
* .GetConnectList() 获取已连接的Client列表 &&return Client1\nClinet2\n......
* .Dispose() 垃圾回收
* .CloseServer() 关闭服务
* oSocket = GetUserSocketInstance( String ClientID ) &&return objects .T.获取用户实例|.F. null
* oSocket IDE支持可以oSocket.查看Socket对象的方法属性
Endwith
Local loWebSocketsEvents
m.loWebSocketsEvents = CREATEOBJECT("WebSocketsEvents")
If !EVENTHANDLER( m.oWebSocketsServer , m.loWebSocketsEvents ) Then
Messagebox('绑定WebSocketsEvents类失败!',16, '绑定')
Return .F.
Endif
*--------WebSocketsEvents----------------------
Define Class WebSocketsEvents AS Custom OLEPUBLIC
Implements WebSocketsEvents IN "Netsuite.WebSockets"
*--连接时
Procedure WebSocketsEvents_OnOpen( ip as String)
?'连接:'+ m.ip
Endproc
*--关闭时
Procedure WebSocketsEvents_OnClose( ip as String)
?'关闭:'+ m.ip
Endproc
*--收到消息
Procedure WebSocketsEvents_OnMessage( cid as string, ip as String , msg as String )
?' 收到消息:' + m.ip
??Space(4) + m.msg
Endproc
*--收到二进制信息
Procedure WebSocketsEvents_OnBinary( Length as Integer , Byte as Byte )
?'收到二进制信息长度:' + Transform( m.Length )
??Space(4) + strconv( m.Byte , 9 )
Endproc
*--异常信息
Procedure WebSocketsEvents_OnError( cid as string ,HResult as Integer , Message as string , Source as string , StackTrace as string )
?'异常信息:' + m.cid
?'Result:' + Transform( m.HResult )
?'Message:' + m.Message
?'Source:' + m.Source
?'StackTrace:' + m.StackTrace
Endproc
EndDefine
*--需要Netsuite.dll V1.05版支持(WebSocketsServer DLL 异步多线程,高并,VFP STA单元 单线程 )
*--不依赖于HttpListener或HTTP.sys意味着他将在Windows 7和Server 2008主机上运行
*--使用安全的网络通讯协议 (wss://)
*--已添加检测设置心跳,Client列表自动维护
*--Websocket_htmljstest.html 用于Web模拟Client端测试
_vfp.AutoYield = .F.
Clear
If _vfp.StartMode = 0 Then
m.lcPath = Justpath( _vfp.ActiveProject.Name )
Else
m.lcPath = Justpath( sys(16,0) )
Endif
Set Default To ( m.lcPath )
Set Procedure To netsuite.reg.prg Additive
Do win_api
*--创建PRG处理器
*--当DLL创建的WebSocketServer服务收到Client的消息时由VFP创建的PRG生成的FXP进行应答;
FXP应答线程模式为:(STA)单元线程,在处理器FXP应答处理VFP信息加工时,它可以被动态执换;
可以按条件去执行不同的函数进行处理,该特性由ProcessorFilename|Cmd 来控制。注意每次函数;
处理都需要Return "处理得到的信息",将视为发送给Client的应答信息,MSG-请求信息,Return-应答信息;
MSg 可以多样形式的字符串如cjson ,credis,那么FXP就需要相应的解析来处理什么的请求信息做怎样的应答。
Erase ( Addbs( Getenv("TEMP") ) + '*.prg' )
Local lcCreateprgFilename;
, lcProcessorFilename;
,lcthrFunction
m.lcCreateprgFilename = Addbs( Getenv("TEMP") ) + Sys(2015) + '.prg'
m.lcProcessorFilename = Forceext( m.lcCreateprgFilename, 'fxp' ) &&线程执行的VFP过程函数*--创建线程函数
Text To m.lcthrFunction Textmerge noShow
Function processor( IP As String ;
, Msg As String )
Do win_api
Local lcReturn
Do Case
Case Alltrim( m.Msg ) =='test1'
Sleep(10*1000)
m.lcReturn = [{"PRG处理器过程processor,自我阻塞3*1000秒"}]
Case Alltrim( m.Msg ) =='test2'
m.lcReturn = [{"PRG处理器过程processor,自我不阻塞"}]
Otherwise
m.lcReturn = [{"] + m.Msg + ["}]
Endcase
Return m.lcReturn
Endfunc
Endtext
strtofile( lcthrFunction , m.lcCreateprgFilename )
Compile ( m.lcCreateprgFilename )
Erase ( m.lcCreateprgFilename )
If !File( m.lcProcessorFilename ) Then
Messagebox('WebSocketServer.prg处理器未创建成功!' ,16 )
Return
Endif
*--实例化oWebSocketsServer2
Public oWebSocketsServer2
m.oWebSocketsServer2 = Createobjects( "Netsuite.WebSockets2" )
Local lcUrl ;
, lcpfxFilePath ;
, lcpfxPassword
m.lcUrl = "ws://0.0.0.0:30000" &&"wss://0.0.0.0:30000"
*Start(string cUrl , string pfxFilePath ="", string pfxPassword = "")
* pfxFilePath 非必传 只有Url为Wss使用证书路径,注意服务也需要配置
* pfxPassword 非必传 只有Url为Wss使用证书密码,注意服务也需要配置
With m.oWebSocketsServer2
.ProcessorFilename = m.lcProcessorFilename &&PRG应答处理器的FXP文件动态载入,中途可换
.Cmd = [processor(IP,Msg)] &&执行PRG应答函数
Endwith
*oWebSocketsServer2是异步多线程池管理,并不是同步线程,这里添加阻塞函数等待它全部启动
*该模块应该与VFP的MTCOMDLL多线程对应,DLl中的Server是线程池,但VFP9R.DLL还单一的线程,需要使用
*VFP9T.DLL的多线程构造你的多线应用。
?"线程池启动WebSocketServer"
m.oWebSocketsServer2.Start( m.lcUrl )
Sleep(1*1000)