Hyperledger Fabric 建立一个简单网络

p { margin-bottom: 0.25cm; line-height: 120% }

Building you first network

网络结构:

2个Orgnizations(每个Org包含2个peer节点)+1个solo ordering service

打开fabric-sample下的示例first-network

p { margin-bottom: 0.25cm; line-height: 120% }

其中byfn.sh为启动这个网络的启动脚本,启动脚本中除建立一个包含4个节点和1个Order service的网络外,还会启动一个容器用来执行脚本在channel中加入节点,部署和初始化chaincode,以及在部署的chaincode上执行交易。

启动脚本

第一步,生成必要文件,执行命令:

p { margin-bottom: 0.25cm; line-height: 120% }

p { margin-bottom: 0.25cm; line-height: 120% }
a:link { }

默认channel名称为mychannel

上述是否继续选择y,脚本程序会给网络实例生成数字证书和密钥;生成genesis block用来启动ordering service;一些用来配置channel的配置交易

1、生成数字证书和密钥

p { margin-bottom: 0.25cm; line-height: 120% }

2、生成genesis block

p { margin-bottom: 0.25cm; line-height: 120% }

3、生成channel配置交易

p { margin-bottom: 0.25cm; line-height: 120% }

4、生成anchor peer update for Org1MSP

p { margin-bottom: 0.25cm; line-height: 120% }

5、生成anchor peer update for Org2MSP

p { margin-bottom: 0.25cm; line-height: 120% }

执行上述命令后,查看证书目录:

p { margin-bottom: 0.25cm; line-height: 120% }

2、第二步,启动网络,执行命令./byfn.sh -m up

p { margin-bottom: 0.25cm; line-height: 120% }

上图显示在一个节点上安装chaincode所配置的环境变量,其中配置了节点所拥有的证书信息。

执行结束后,终端显示如下:

p { margin-bottom: 0.25cm; line-height: 120% }

上述命令会启动所有的containers,

p { margin-bottom: 0.25cm; line-height: 120% }

上面通过脚本./byfn.sh生成了一个fabric网络,接下来详细说明脚本中所执行的命令信息:

1、Crypto Generator

cryptogen工具会对网络节点生成证书信息,证书信息可以代表每一个实例节点,用于节点间通信和交易。

cryptogen使用的配置文件为crypto-config.yaml。配置文件中描述了网络的拓扑结构同时会为Orgnizations和Orgnizations下的节点生成一系列的证书。每个Orgnization会有一个根证书ca-cert用来绑定特定节点(peer或者order)到该Orgnization。通过对每个Orgnization颁发一个唯一的数字证书,我们可以模仿典型的区块链网络,每个加入链的成员使用自己的数字证书进行获取授权。交易和通信使用节点的私鈅,验证使用节点的公钥(数字证书)。配置文件里的count参数用来指定每个Orgnization的节点数量,本例子中一个Orgnization下面包含两个节点,所以count的值在本例中设定为2。

在运行这个命令之前,我们快速的看一下crypto-config.yaml里的配置信息。特别关注OrderOrgs header下的Name,Domain和Specs几个参数。

使用命令:

sed ‘s/^[ ]*#.*$//g‘ crypto-config.yaml > crypt.yaml

sed -i ‘/^$/d‘ crypt.yaml

去掉配置文件中的注释部分如下:

p { margin-bottom: 0.25cm; line-height: 120% }

网络节点的命名规则为{Hostname}.{Domain}。以上述配置文件中order节点为例,order节点的命名为orderer.example.com,对应的MSP Id为Orderer。

运行cryptogen命令后,生成的数字证书和密钥信息保存在crypto-config文件夹中。

Configuration
Transaction Generation

配置交易生成工具:configtxgen
用来生成4个配置信息

orderer
genesis block

fabric
channel configuration transaction

2个anchor
peer transaction (每个Peer
Org生成一个)

orderer
block是ordering
service的起始block,channel配置交易文件在channel创建时广播到orderer。anchor
peer交易用来指定channel上每个Org的Anchor
Peer。

configxgen的配置文件为configtx.yaml,其中包含对我们所创建的示例网络的定义。配置文件包含3个角色,一个Orderer
Org(OrderOrg)和两个Peer
Orgs(Org1和Org2)。配置文件也指定了一个组合SampleConsortium,包含2个Peer
Org。打开配置文件,配置文件顶部Profiles部分有两个唯一的headers。其中TwoOrgsOrderedGenesis用来配置orderer
genesis block,TwoOrgChannel用来配置我们的channel。

td p { margin-bottom: 0cm }
pre.ctl { font-family: "Liberation Mono", monospace }
p { margin-bottom: 0.25cm; line-height: 120% }
code.ctl { font-family: "Liberation Mono", monospace }

上述配置文件中还包含两个没有特别意义的指定信息。第一个,我们为每一个Peer Org指定了Anchor Peer(peer0.org1.example.com和peer0.org2.example.com)。第二点,我们指定了每个角色的MSP路径,从而允许我们把每个Org的根证书存储在orderer genesis block中。这是一个重要的概念。现在每个节点和ordering service通信都需要验证通过他们的数字证书。

运行cryptogen和configtxgen命令

可以手动运行上述两个命令生成数字证书/密钥或者生成配置交易。也可以通过修改脚本byfn.sh脚本实现上述目标。

手动生成证书和配置交易

可以参考byfn.sh脚本中的generateCerts函数理解生成网络配置中数字证书的命令。为了便利,这里我们也提供了一种参考方法。

首先运行cryptogen工具。cryptogen命令在first
network子目录的bin目录下,下面运行命令使用了该命令所在位置的相对路径。

../bin/cryptogen
generate --config=./crypto-config.yaml

也许你会遇到提示如下警告,直接忽略就可以

[bccsp]
GetDefault -> WARN 001 Before using BCCSP, please call
InitFactories(). Falling back to bootBCCSP.
接下来,我们需要告诉configtxgen工具引用哪里的配置文件configtx.yaml。这里我们通过设置环境变量来设定配置文件的路径。
export
FABRIC_CFG_PATH=$PWD
../bin/configtxgen
-profile TwoOrgsOrdererGenesis -outputBlock
./channel-artifacts/genesis.block

你可以忽略掉关于intermediate certificates, certificate revocation lists (crls) and MSP configurations的警告信息,在本例中的网络中,我们不会用到上述信息。

接下来,我们创建channel交易。确保替换$CHANNEL_NAME的值或者设置CHANNEL_NAME作为一个环境变量。创建命令如下:

export
CHANNEL_NAME=mychannel

#
this file contains the definitions for our sample channel
../bin/configtxgen
-profile TwoOrgsChannel -outputCreateChannelTx
./channel-artifacts/channel.tx -channelID $CHANNEL_NAME

接下来,在我们创建的channel上定义Org1的Anchor Peer节点。执行命令为:

../bin/configtxgen
-profile TwoOrgsChannel -outputAnchorPeersUpdate
./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg
Org1MSP

在channel上定义Org2的Anchor Peer节点:

../bin/configtxgen
-profile TwoOrgsChannel -outputAnchorPeersUpdate
./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg
Org2MSP

启动网络

我们引用一个docker-compose脚本启动网络,docker-compose文件引用了我们之前下载的镜像文件同时根据之前生成的genesis.block引导orderer。

working_dir:
/opt/gopath/src/github.com/hyperledger/fabric/peer
#
command: /bin/bash -c ‘./scripts/script.sh ${CHANNEL_NAME}; sleep
$TIMEOUT‘
volumes
如果去掉注释部分,网络启动时脚本会执行所有的CLI命令。这里我们手动的执行每一条命令,以便于我们了解命令的语法和功能。
给TIMEOUT参数传递一个相对较大的值(单位为秒);否则CLI容器默认会在60s后退出。
启动网络:
CHANNEL_NAME=$CHANNEL_NAME
TIMEOUT=<pick_a_value>
docker-compose
-f docker-compose-cli.yaml up -d
如果你想实时查看执行上述命令的日志信息,那么去掉上面的-d选项(后台运行)。如果打开了上述日志流,那么你需要另外再打开一个终端用来执行CLI命令。
环境变量
为了在peer0.org1.example.com上执行下面的CLI命令,需要先配置下面4个环境变量。peer0.org1.example.com的这些变量我们已经在CLI容器中配置了,因此我们可以不用传递这些环境变量的值了。但是,如果你想发送命令到其他peer或者orderer,你需要提供这些变量相应的值。检查docker-compose-base.yaml查看那指定的路径。
#
Environment variables for PEER0

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
CORE_PEER_LOCALMSPID="Org1MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
创建和加入channel
执行docker
exec命令进入CLI容器
docker
exec -it cli bash
成功执行后,出现如下提示:
[email protected]:/opt/gopath/src/github.com/hyperledger/fabric/peer#
之前,我们使用configtxgen工具生成了配置交易channel.tx。我们将会传递这个交易到orderer作为创建channel请求的一部分。
注意:--cafile选项是orderer的根证书存放在本地的路径,该信息可以用来验证TLS握手过程。
我们使用-c选项指定channel的名字,使用-f选项指定配置交易。在本例中为channel.tx,你也可以mount配置交易为一个不同的名字。(配置交易通过本地路径mount到容器中)
export
CHANNEL_NAME=mychannel

#
the channel.tx file is mounted in the channel-artifacts directory
within your CLI container
#
as a result, we pass the full path for the file
#
we also pass the path for the orderer ca-cert in order to verify the
TLS handshake
#
be sure to replace the $CHANNEL_NAME variable appropriately

peer
channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f
./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile
/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
这条命令返回一个genesis
block
<channel-ID.block>。该block可以用来加入channel时使用,block中包含了channel.tx中指定的配置信息。
你需要留在CLI容器中执行剩余的手动命令。如果发送命令的目标不是peer0.org1.example.com,那么要重新设置相应的环境变量。现在我们加入peer0.org1.example.com到channel中
#
By default, this joins ``peer0.org1.example.com`` only
#
the <channel-ID>.block was returned by the previous command

 peer
channel join -b <channel-ID.block>
你可以修改上边4个环境变量的值为其他peer节点信息配置加入其他节点到channel中。
安装和实例化chaincode
我们利用一个简单的已写好的chaincode。应用通过chaincode和区块链的账本进行交互,因此我们需要首先在每个peer节点上安装chaincode用来执行交易和背书交易,然后在channel上实例化chaincode。
首先安装例子go代码到4个peer节点中的一个。这个命令会把go源码放在peer节点的文件系统中。
peer
chaincode install -n mycc -v 1.0 -p
github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
接下来,在channel上实例化chaincode。这将会在channel上初始化chaincode,为chaincode设置背书策略,为目标peer启动一个chaincode容器。注意-P参数,这个参数指定了在该chaincode上一个交易被认可需要的背书级别。
接下来的命令中,我们设置-P参数为
-P
"OR (‘Org0MSP.member‘,‘Org1MSP.member‘)"
。这表示我们需要Org1或者Org2中一个peer节点的背书。如果改变语法为AND,那么就需要两个背书。#
be sure to replace the $CHANNEL_NAME environment variable
#
if you did not install your chaincode with a name of mycc, then
modify that argument as well

peer
chaincode instantiate -o orderer.example.com:7050 --tls
$CORE_PEER_TLS_ENABLED --cafile
/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
-C $CHANNEL_NAME -n mycc -v 1.0 -c ‘{"Args":["init","a",
"100", "b","200"]}‘ -P "OR
(‘Org1MSP.member‘,‘Org2MSP.member‘)"
上述命令中的mycc为上文中peer上安装的chaincode的名称。
下面查询a的值,确认chaincode被正确的实例化,stateDB正常的运行。查询的语法如下:
#
be sure to set the -C and -n flags appropriately

peer
chaincode query -C $CHANNEL_NAME -n mycc -c ‘{"Args":["query","a"]}‘
现在从a转移10到b。这个交易会产生一个新的区块并更新stateDB。调用的语法是:
#
be sure to set the -C and -n flags appropriately

peer
chaincode invoke -o orderer.example.com:7050  --tls
$CORE_PEER_TLS_ENABLED --cafile
/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
 -C $CHANNEL_NAME -n mycc -c ‘{"Args":["invoke","a","b","10"]}‘
现在再次查询,查看上述转移10的命令是否已经成功执行,执行的命令是:
#
be sure to set the -C and -n flags appropriately

peer
chaincode query -C $CHANNEL_NAME -n mycc -c ‘{"Args":["query","a"]}‘
正常执行,会输出如下提示:
Query
Result: 90
下面描述docker-compose-cli.yaml文件中没有注释script.sh时的执行情况。去掉包含script.sh脚本执行的注释,然后使用docker-compose命令再次启动网络。
1、Script.sh脚本在CLI容器里已经备份过,脚本执行createChannel命令根据设定的channel名字,使用channel.tx文件作为channel配置交易。
2、createChannel执行的输出是一个genesis
block-<your channel
name>.block。输出存储在peer节点的文件系统上包含了channel.tx所指定的channel配置信息。
3、joinChannel命令被执行(4个peer节点),joinChannel命令使用上文生成的genesis
block作为参数,该命令引导peer节点加入到<your
channel name>并且建立一个以<your
channel name>.block为起始的链。
4、目前我们建立了一个包含4个节点的channel,channel包含两个orgnizations。类似TwoOrgsChannel文件的配置。
5、peer0.org1.example.com和peer1.org1.example.com属于Org1;peer0.org2.example.com和peer1.org2.example.com属于Org2
6、这些关系在crypto-config.yaml里定义,MSP的路径在docker
compose中指定
7、Org1MSP的Anchor
Peer(peer0.org1.example.com)和Org2MSP的Anchor
peer(peer0.org2.example.com)被更新。我们通过传递Org1MSPanchor.tx和Org2MSPanchor.tx以及channel的名字到ordering
service来实现这一步。
8、将编写好的chaincode_example02安装在peer0.org1.example.com和peer0.org2.example.com上(这里并没有安装在所有peer上,而是仅安装在anchor
peer节点上,anchor
peer节点之前每个Org设置了一个)
9、chaincode在peer0.org2.example.com上实例化。实例化过程添加chaincode到channel中,为目标peer启动容器,同时初始化与chaincode相关的key-value键值对。本例中初始化的值为[“a”,”100”
“b”,”200”]。实例化后会启动一个容器dev-peer0.org2.example.com-mycc-1.0。(实例化过程发送至peer0.org2.example.com上执行
10、实例化过程也传递了一个背书策略的参数。背书策略类似形式:-P
"OR   
(‘Org1MSP.member‘,‘Org2MSP.member‘)",代表任何交易必须被Org1Org2的一个peer背书。
11、在peer0.org1.example.com上执行查询a的值。chaincode之前已经安装在peer0.org1.example.com上了,因此查询操作会为Org1peer0节点启动一个容器dev-peer0.org1.example.com-mycc-1.0。查询结果也会返回回来,这个过程中没有任何写操作发生,所以a的值还是100
12、发送一个转移账户金额的调用到peer0.org1.example.com,从a账户转移10单位至b账户
13chaincode然后安装在peer1.org2.example.com
14、发送查询a账户操作至peer1.org2.example.com。这将启动第三个chaincode容器dev-peer1.org2.example.com-mycc-1.0。返回金额90,说明之前帐号金额的转移操作成功执行。
这说明了什么
为了在账本上成功的执行读写操作,chaincode必须安装在peer上。另外,chaincode容器直到实例化或者传统交易-读写执行的时候(例:查询a账户的值),chaincode容器才会启动。channel中的每个节点都维护了账本的完全复制,存储了不可改变的、序列化的记录区块以及state
database用于保存当前的fabric状态。即便是那些没有安装chaincode的节点(例如peer1.org1.example.com)也会同步账本。最终chaincode在安装到peer1.org1.example.com后就可以被调用了,因为chaincode已经完成了实例化。
怎样查看交易信息
查看CLI
docker容器的日志信息
docker
logs -f cli
可以看到交易的详细过程
怎样查看chaincode的日志
在每个chaincode
container上可以查看当前container里所执行过的交易。具体查看命令如下:
docker
logs dev-peer0.org2.example.com-mycc-1.0
docker
logs dev-peer0.org1.example.com-mycc-1.0
docker
logs dev-peer1.org2.example.com-mycc-1.0
理解docker-compose拓扑结构
BYFN例子提供了两种docker-compose文件配置,每一种都是由docker-compose-base.yaml(文件存放在base文件夹中)文件拓展而来。第一个配置文件是docker-compose-cli.yaml,该配置文件配置了一个CLI容器,一个orderer4peer节点。使用该配置文件启动可以实现本文中的所有操作指令。第二种配置文件docker-compose-e2e.yaml是配置启动一个使用Node.js
SDK的点对点测试。这个配置文件的主要区别是包含了fabric-ca-servers容器。因此,我们可以使用REST接口实现向CA组织注册和登记用户。
如果你想使用docker-compose-e2e.yaml并且不先运行byfn.sh脚本,那么我们需要做4个微改动。我们需要设定Organization
CA的私鈅。你可以设定这些值为你的crypto-config文件夹。例如设置Org1的私鈅路径为:crypto-config/peerOrganizations/org1.example.com/ca/。私鈅文件是一个长hash值加上_sk组成。设定Org2的私鈅为crypto-config/peerOrganizations/org2.example.com/ca/
另外2出改动是修改docker-compose-e2e.yamlca0ca1配置中的FABRIC_CA_SERVER_TLS_KEYFILE变量对应的值。需要指定tls证书所在的路径。
按照一个简单区块链网络的生成过程,制作执行过程如下:

执行步骤


执行命令和前置条件


生成必要信息


1、网路节点的证书文件

../bin/cryptogen
			generate --config=./crypto-config.yaml

2、生成gensis block

export
			FABRIC_CFG_PATH=$PWD
../bin/configtxgen
			-profile TwoOrgsOrdererGenesis -outputBlock
			./channel-artifacts/genesis.block

3、生成channel.tx

../bin/configtxgen
			-profile TwoOrgsChannel -outputCreateChannelTx
			./channel-artifacts/channel.tx -channelID $CHANNEL_NAME

4、生成anchor peer

../bin/configtxgen
			-profile TwoOrgsChannel -outputAnchorPeersUpdate
			./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME
			-asOrg Org1MSP

创建channel


peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx

创建channel的命令由peer节点发起,使用上文生成的channel.tx,上述命令生成<channel_name>.block在当前文件夹中,该block中保存了channel.tx的信息。节点加入channel后,该区块作为节点区块链的第一个区块。


加入peer节点到channel中


peer channel join -b $CHANNEL_NAME.block

peer加入channel时使用创建channel时生成的block文件

加入哪个peer节点到channel中,需要通过在CLI容器中设置如下环境变量指定:

CORE_PEER_LOCALMSPID="Org1MSP"

CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp

CORE_PEER_ADDRESS=peer0.org1.example.com:7051

设置上述环境变量,加入peer0节点到channel中


更新Anchor
peer


peer
channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f
./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx

使用configtxgen生成的anchor.tx文件


安装chaincode


peer
chaincode install -n mycc -v 1.0 -p
github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02

在CLI容器中设置环境变量指定在哪个peer节点上安装chaincode


在channel上实例化chaincode


peer
chaincode instantiate -o orderer.example.com:7050 --tls
$CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n
mycc -v 1.0 -c ‘{"Args":["init","a","100","b","200"]}‘
-P "OR (‘Org1MSP.member‘,‘Org2MSP.member‘)"

需要设定环境变量指定在哪个peer节点上执行实例化chaincode命令


执行chaincode调用

				
时间: 2024-10-12 22:57:19

Hyperledger Fabric 建立一个简单网络的相关文章

TCP学习之建立一个简单的客户/服务器系统--回射系统

TCP学习之建立一个简单的客户/服务器系统--回射系统 相关的资料可以参考Unix网络编程,这个只是修改版,不需要依赖任何文件,可以独立编译通过,而且是在两台不同的主机上进行的. fggets和fputs这两个函数来自标准I/O函数库,writen和readline见my_unp.h头文件 //my_unp.h #include<stdarg.h> #include<syslog.h> #include<stdio.h> #include<netinet/in.h

Hibernate学习——建立一个简单的Hibernate项目

最近老师让做个web小应用,大三的时候学习过一点J2EE的东西,也做过一些web相关的XXX管理系统,都是用servlet,jsp这些完成的,虽然勉强能够完成任务,但其中各种代码掺杂在一起,不好看而且维护起来也很麻烦,出了一点问题要调试好久才能解决.这次打算让自己多学一点东西,在项目的架构上我使用了struts2实现了多层代码的分离,在数据库方面,因为以往的经历都需要对连接数据库进行一个封装,里面包含有数据库的连接,记录的添加,查询,修改和删除等操作,每次使用的过程中都需要先实现一个连接对象然后

【Java编程】建立一个简单的JDBC连接-Drivers, Connection, Statement and PreparedStatement

本blog提供了一个简单的通过JDBC驱动建立JDBC连接例程,并分别通过Statement和PreparedStatement实现对数据库的查询.在下一篇blog中将重点比较Statement与PreparedStatement的差异. 1.为项目添加JDBC驱动 1)JDBC驱动下载 官方下载地址:mysql-connector-java-5.0.8.zip CSDN资料下载地址:mysql-connector-java-5.0.8.zip 2)为项目添加JDBC驱动 建立项目Java项目J

Ogre: 建立一个简单的框架——关于场景节点

[转载请保证内容的完整性和正确性] 建立一个简单的框架——关于场景节点 如果我们要做一个类似于<跑跑卡丁车>的游戏,人物模型是需要随着卡丁车模型一起进行各种变换的(平移.旋转等),我们需要分别计算两个关联的模型的位置吗?这样能解决问题,但是太麻烦了,利用Ogre的场景节点可以很方便地解决这种问题. 添加一个新的模型 之前添加的模型都是由3DMAX等软件导出的模型,接下来我们利用Ogre生成一个Cube模型. 1 //DemoManager.cpp 2 Ogre::ManualObject* c

Ogre: 建立一个简单的框架——响应键盘事件

[转载请保证内容的完整性和正确性] 建立一个简单的框架——响应键盘事件 上一节我们在场景中添加了一个机器人,这一节我们将建立一个FrameListener类(顾名思义,这是一个侦听类),来控制模型进行移动. 创建FrameListener类 FrameListener类主要负责事件的侦听,如帧结束.键盘输入等事件.它继承自ExampleFrameListener类,如果需要的话还可以继承KeyListener(键盘事件).MouseListener(鼠标事件)和JoyStickListener(

WebADI_建立一个简单的WebADI实现日记账上传(案例)

2014-06-01 BaoXinjian 一.摘要 WebADI原本固定资产导入和日记账导入的一些工具发展而来,因为财务部门人员大多非常熟悉Excel,希望竟可能尽量多的使用Excel工具去进行财务操作 而WebADI提供了这样一种可能性通过excel,将资料建立客制化的API或Interface处理,导入至EBS中 在11i中,WebADI可能还不够完善,还需要很多代码操作和注册 在R12中,WebADI的功能有进一步的加强 个人觉得,如果资料导入API或Interface不是太过频繁,数据

学习用node.js建立一个简单的web服务器

一.建立简单的Web服务器涉及到Node.js的一些基本知识点: 1.请求模块 在Node.js中,系统提供了许多有用的模块(当然你也可以用JavaScript编写自己的模块,以后的章节我们将详细讲解),如http.url等.模块封装特定的功能,提供相应的方法或属性,要使用这些模块,需要先请求模块获得其操作对象. 例如要使用系统的http模块,可以这样写: var libHttp = require('http'); //请求HTTP协议模块 这样,以后的程序将可以通过变量libHttp访问ht

一个简单网络爬虫示例(转载)

在学生时期,可能听到网络爬虫这个词会觉得很高大上,但是它的简单实现可能学生都不难懂. 网络爬虫应用,就是把整个互联网真的就当做一张网,像蜘蛛网那样,应用就像一个虫子,在网上面按照一定的规则爬动. 现在互联网应用最广的就是http(s)协议了,本文例子就是基于使用http(s)协议的,只作为示例,不涉及复杂的算法(实际上是最重要的). 设计思路: 程序入口从一个或多个url开始,通过http(s)获取url的内容,对获取到内容处理,获取内容中需要爬取的信息,获取到内容中的url链接,再重复以上步骤

一个简单网络服务器类的实现

网络服务器,顾名思义是一个可以接受连接的host,我们要实现的网络服务器类是一个 1.能够实现多个连接 2.仅仅通过继承或实现网络服务器类(或接口)的处理就能实现不同的连接功能 3.当服务器关闭时,已有建立的私有连接不被中断,但服务器不在接受新的连接 针对以上功能我们分解一下要实现的模块: 1.多线程实现多个连接,当serverSocket accept到一个连接请求时,开启一个独立的线程 2.实现这个,要求上面新建线程能被网络服务器锁管理 3.服务器不接受其他连接,可以用线程中断做,私有连接能