• 关于

    编码传输怎么用

    的搜索结果

回答

百度百科中对Base64有一个很好的解释:“Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法”。         什么是“可打印字符”呢?为什么要用它来传输8Bit字节码呢?在回答这两个问题之前我们有必要来思考一下什么情况下需要使用到Base64?Base64一般用于在HTTP协议下传输二进制数据,由于HTTP协议是文本协议,所以在HTTP协议下传输二进制数据需要将二进制数据转换为字符数据。然而直接转换是不行的。因为网络传输只能传输可打印字符。什么是可打印字符?在ASCII码中规定,0~31、127这33个字符属于控制字符,32~126这95个字符属于可打印字符,也就是说网络传输只能传输这95个字符,不在这个范围内的字符无法传输。那么该怎么才能传输其他字符呢?其中一种方式就是使用Base64。         Base64,就是使用64个可打印字符来表示二进制数据的方法。Base64的索引与对应字符的关系如下表所示: 也就是说,如果将索引转换为对应的二进制数据的话需要至多6个Bit。然而ASCII码需要8个Bit来表示,那么怎么使用6个Bit来表示8个Bit的数据呢?6个Bit当然不能存储8个Bit的数据,但是46个Bit可以存储38个Bit的数据啊!如下表所示: 可以看到“Son”通过Base64编码转换成了“U29u”。这是刚刚好的情况,3个ASCII字符刚好转换成对应的4个Base64字符。但是,当需要转换的字符数不是3的倍数的情况下该怎么办呢?Base64规定,当需要转换的字符不是3的倍数时,一律采用补0的方式凑足3的倍数,具体如下表所示: 每6个Bit为一组,第一组转换后为字符“U”,第二组末尾补4个0转换后为字符“w”。剩下的使用“=”替代。即字符“S”通过Base64编码后为“Uw==”。这就是Base64的编码过程。

问问小秘 2020-04-30 16:51:05 0 浏览量 回答数 0

问题

深入分析字符编码之五-常见问题分析

夏天的日子 2019-12-01 21:13:23 4211 浏览量 回答数 0

问题

esp8266如何将需要上传的文字上传到物联网平台如何传输给微信小程序?

游客wxstopqdnull6 2020-08-20 10:46:25 1 浏览量 回答数 0

阿里云试用中心,为您提供0门槛上云实践机会!

0元试用32+款产品,最高免费12个月!拨打95187-1,咨询专业上云建议!

问题

应用程序“QXW”中的服务器错误怎么解决?

江华山 2019-12-01 22:06:23 11827 浏览量 回答数 7

回答

楼主业余菜鸟一个,上次问问题临时用新浪账号注册了这个网,这段时间偶然发现一个朋友加我QQ才知道还有朋友需要详细解答,废话不多说,上代码,支持中文的mybase64.js与修改后的tableExport.js,这个地方篇幅有限制,看博文吧,为了你们第一次写~http://my.oschina.net/MiloFriends/blog/466707###### 已自行解决,经查阅资料了解 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64就是用来将非ASCII字符的数据转换成ASCII字符的一种方法,而且base64特别适合在http,mime协议下快速传输数据。 因此通过修改base64编码可以解决相关问题,至于修改的方法网上很多~ 第一次提问,没想到自己先解决了,看来难度不大,所以才没人提吧,还是先自己研究最靠谱~自问自答了 ######导出excel没有后缀,遇到过这个问题吗######怎么修改的,求助攻。。###### 用这个插件开始是中文没数据,将页面HTML中的要打印的table字符串(这个table是js拼接后插入到div的 )编码换成unicode码后,不在jquery.base64.js中的 _getbyte方法那报 throw "INVALID_CHARACTER_ERR: DOM Exception 5";这个异常了,能出来excel,但是没有数据,求教######怎么修改的,急求啊,我想了很多办法都没实现,就是不能导出中文######急切需要知道,有没有人知道怎么导出中文啊###### 楼主为啥不说啊 ,别卖关子啊 ######我把你修改的两个js引进去之后 ,可以成功导出excel,但是pdf的话 ,就报错: 渲染页面时发生错误。 PDF.js v1.0.1149 (build: bc7a110),楼主好人做到底吧,这个怎么解决啊? ######我把你修改的两个js引进去之后 ,可以成功导出excel,但是pdf的话 ,就报错: 渲染页面时发生错误。 PDF.js v1.0.1149 (build: bc7a110),楼主好人做到底吧,这个怎么解决啊? 很急。。。跪求。。。 ######<button class="btn btn-success" onClick ="$('#tablepnf').tableExport({type: 'pdf', escape: 'false'});">CSV Export</button>  table的边框线条不显示,中文乱码,怎么解决啊 ,跪求大神解答。。。

montos 2020-05-31 10:16:33 0 浏览量 回答数 0

回答

楼主业余菜鸟一个,上次问问题临时用新浪账号注册了这个网,这段时间偶然发现一个朋友加我QQ才知道还有朋友需要详细解答,废话不多说,上代码,支持中文的mybase64.js与修改后的tableExport.js,这个地方篇幅有限制,看博文吧,为了你们第一次写~http://my.oschina.net/MiloFriends/blog/466707###### 已自行解决,经查阅资料了解 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64就是用来将非ASCII字符的数据转换成ASCII字符的一种方法,而且base64特别适合在http,mime协议下快速传输数据。 因此通过修改base64编码可以解决相关问题,至于修改的方法网上很多~ 第一次提问,没想到自己先解决了,看来难度不大,所以才没人提吧,还是先自己研究最靠谱~自问自答了 ######导出excel没有后缀,遇到过这个问题吗######怎么修改的,求助攻。。######用这个插件开始是中文没数据,将页面HTML中的要打印的table字符串(这个table是js拼接后插入到div的 )编码换成unicode码后,不在jquery.base64.js中的 _getbyte方法那报 throw "INVALID_CHARACTER_ERR: DOM Exception 5";这个异常了,能出来excel,但是没有数据,求教######怎么修改的,急求啊,我想了很多办法都没实现,就是不能导出中文######急切需要知道,有没有人知道怎么导出中文啊######楼主为啥不说啊 ,别卖关子啊 ######我把你修改的两个js引进去之后 ,可以成功导出excel,但是pdf的话 ,就报错: 渲染页面时发生错误。 PDF.js v1.0.1149 (build: bc7a110),楼主好人做到底吧,这个怎么解决啊? ######我把你修改的两个js引进去之后 ,可以成功导出excel,但是pdf的话 ,就报错: 渲染页面时发生错误。 PDF.js v1.0.1149 (build: bc7a110),楼主好人做到底吧,这个怎么解决啊? 很急。。。跪求。。。 ######<button class="btn btn-success" onClick ="$('#tablepnf').tableExport({type: 'pdf', escape: 'false'});">CSV Export</button>  table的边框线条不显示,中文乱码,怎么解决啊 ,跪求大神解答。。。

kun坤 2020-05-28 16:14:06 0 浏览量 回答数 0

回答

楼主业余菜鸟一个,上次问问题临时用新浪账号注册了这个网,这段时间偶然发现一个朋友加我QQ才知道还有朋友需要详细解答,废话不多说,上代码,支持中文的mybase64.js与修改后的tableExport.js,这个地方篇幅有限制,看博文吧,为了你们第一次写~http://my.oschina.net/MiloFriends/blog/466707###### 已自行解决,经查阅资料了解 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64就是用来将非ASCII字符的数据转换成ASCII字符的一种方法,而且base64特别适合在http,mime协议下快速传输数据。 因此通过修改base64编码可以解决相关问题,至于修改的方法网上很多~ 第一次提问,没想到自己先解决了,看来难度不大,所以才没人提吧,还是先自己研究最靠谱~自问自答了 ######导出excel没有后缀,遇到过这个问题吗######怎么修改的,求助攻。。###### 用这个插件开始是中文没数据,将页面HTML中的要打印的table字符串(这个table是js拼接后插入到div的 )编码换成unicode码后,不在jquery.base64.js中的 _getbyte方法那报 throw "INVALID_CHARACTER_ERR: DOM Exception 5";这个异常了,能出来excel,但是没有数据,求教######怎么修改的,急求啊,我想了很多办法都没实现,就是不能导出中文######急切需要知道,有没有人知道怎么导出中文啊###### 楼主为啥不说啊 ,别卖关子啊 ######我把你修改的两个js引进去之后 ,可以成功导出excel,但是pdf的话 ,就报错: 渲染页面时发生错误。 PDF.js v1.0.1149 (build: bc7a110),楼主好人做到底吧,这个怎么解决啊? ######我把你修改的两个js引进去之后 ,可以成功导出excel,但是pdf的话 ,就报错: 渲染页面时发生错误。 PDF.js v1.0.1149 (build: bc7a110),楼主好人做到底吧,这个怎么解决啊? 很急。。。跪求。。。 ######<button class="btn btn-success" onClick ="$('#tablepnf').tableExport({type: 'pdf', escape: 'false'});">CSV Export</button>  table的边框线条不显示,中文乱码,怎么解决啊 ,跪求大神解答。。。

kun坤 2020-06-07 00:08:21 0 浏览量 回答数 0

问题

iOS开发, 如何通过HTTP Post发送这个符号"&"到服务器?

a123456678 2019-12-01 19:21:53 941 浏览量 回答数 2

问题

OSS 官方帮助文档 在此归类发布 ,常见问题基本能在这里找到答案。

asky8 2019-12-01 21:21:14 47894 浏览量 回答数 17

问题

【Java学习全家桶】1460道Java热门问题,阿里百位技术专家答疑解惑

管理贝贝 2019-12-01 20:07:15 27612 浏览量 回答数 19

问题

dubbo 支持的通信协议?有哪些序列化协议?说下 Hessian 的数据结构?【Java问答】48

剑曼红尘 2020-07-01 15:18:43 7 浏览量 回答数 1

回答

从channel是判断不出来的, websocket协议在channel中没有体现.  如果用netty, 绑定一个端口来接收socket, websocket的连接, 可以尝试如下: 1. 将它们的inbound,outbound处理类, 都在初始化时加进去, websocket的放在前面. 2. websocket在请求连接后, 会有一个http握手请求, 普通socket连接也可以在websocket 自定义inbound处理类中处理 3. 判断是否为 websocket请求, 是(pipeline中移除socket的处理类), 否(pipeline中移除websocket的处理类), 以后再来的消息, 就只会到各自的处理类中了.    ######回复 @hanzhenchao : 对的, 自定义的inbound处理类要用fireChannelRead传递处理. 有一点要注意HttpServerCodec, 这个在做解析处理时, 如果解析不成功, 不会往后传递######回复 @zb1497041270838 : 您好,请问socket请求在websocket的handler判断后加上socket的hanlder,最后怎么触发执行后续的handler?ctx.fireChannelRead???######不同端口监听###### public class WSProtobufServerInitialzer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new ReadTimeoutHandler(60)); // 长时间不写会断 // ====================== 增加心跳支持 start ====================== // 针对客户端,如果在1分钟时没有向服务端发送读写心跳(ALL),则主动断开 // 如果是读空闲或者写空闲,不处理 pipeline.addLast(new IdleStateHandler(0, 0, 15)); // 自定义的空闲状态检测 //判断是websocket 还是普通socket //如果是websocket 则添加HttpServerCodec()等 否则添加new ProtobufDecoder()等 pipeline.addLast(new SocketChooseHandle()); } } 在SocketChooseHandle()中通过 private String getBufStart(ByteBuf in) { int length = in.readableBytes(); if (length > MAX_LENGTH) { length = MAX_LENGTH; } // 标记读位置 in.markReaderIndex(); byte[] content = new byte[length]; in.readBytes(content); return new String(content); }获取握手的协议前缀 /** * 协议初始化 * <p> * 用来判定实际使用什么协议.</b> / public class SocketChooseHandle extends ByteToMessageDecoder { /* * 默认暗号长度为23 / private static final int MAX_LENGTH = 23; /* * WebSocket握手的协议前缀 */ private static final String WEBSOCKET_PREFIX = "GET /"; @Override protected void decode(ChannelHandlerContext ch, ByteBuf in, List<Object> out) throws Exception { String protocol = getBufStart(in); ChannelPipeline pipeline = ch.pipeline(); if (protocol.startsWith(WEBSOCKET_PREFIX)) { //websocket 基于http协议,所以要有http //如果不是websocket 则删除 pipeline.addLast(new HttpServerCodec()); // 对写大数据流的支持 pipeline.addLast(new ChunkedWriteHandler()); // 对httpMessage进行聚合,聚合成FullHttpRequest或FullHttpResponse // 几乎在netty中的编程,都会使用到此hanler pipeline.addLast(new HttpObjectAggregator(1024 * 64)); pipeline.addLast(new WebSocketServerProtocolHandler("/web")); // 协议包解码 pipeline.addLast(new MessageToMessageDecoder<WebSocketFrame>() { @Override protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List<Object> objs) throws Exception { ByteBuf buf = frame.content(); objs.add(buf); buf.retain(); } }); // 协议包解码时指定Protobuf字节数实例化为CommonProtocol类型 pipeline.addLast(new ProtobufDecoder(MyProbuf.DataContent.getDefaultInstance())); pipeline.addLast(new ProtobufVarint32LengthFieldPrepender()); // 协议包编码 pipeline.addLast(new MessageToMessageEncoder<MessageLiteOrBuilder>() { @Override protected void encode(ChannelHandlerContext ctx, MessageLiteOrBuilder msg, List<Object> out) throws Exception { ByteBuf result = null; if (msg instanceof MessageLite) { result = Unpooled.wrappedBuffer(((MessageLite) msg).toByteArray()); } if (msg instanceof MessageLite.Builder) { result = Unpooled.wrappedBuffer(((MessageLite.Builder) msg).build().toByteArray()); } // ==== 上面代码片段是拷贝自TCP ProtobufEncoder 源码 ==== // 然后下面再转成websocket二进制流,因为客户端不能直接解析protobuf编码生成的 WebSocketFrame frame = new BinaryWebSocketFrame(result); out.add(frame); } }); } else { // 解码和编码,应和客户端一致 //传输的协议 Protobuf pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufDecoder(MyProbuf.DataContent.getDefaultInstance())); pipeline.addLast(new ProtobufVarint32LengthFieldPrepender()); pipeline.addLast(new ProtobufEncoder()); } //添加自定义处理器 pipeline.addLast(new ProtobufHandler()); in.resetReaderIndex(); pipeline.remove(this.getClass()); } private String getBufStart(ByteBuf in) { int length = in.readableBytes(); if (length > MAX_LENGTH) { length = MAX_LENGTH; } // 标记读位置 in.markReaderIndex(); byte[] content = new byte[length]; in.readBytes(content); return new String(content); } }  

kun坤 2020-05-31 22:41:12 0 浏览量 回答数 0

问题

OSS for PHPWIND 8.7 [20121127更新]

enj0y 2019-12-01 20:25:35 50835 浏览量 回答数 31

回答

从channel是判断不出来的, websocket协议在channel中没有体现.  如果用netty, 绑定一个端口来接收socket, websocket的连接, 可以尝试如下: 1. 将它们的inbound,outbound处理类, 都在初始化时加进去, websocket的放在前面. 2. websocket在请求连接后, 会有一个http握手请求, 普通socket连接也可以在websocket 自定义inbound处理类中处理 3. 判断是否为 websocket请求, 是(pipeline中移除socket的处理类), 否(pipeline中移除websocket的处理类), 以后再来的消息, 就只会到各自的处理类中了.    ######回复 @hanzhenchao : 对的, 自定义的inbound处理类要用fireChannelRead传递处理. 有一点要注意HttpServerCodec, 这个在做解析处理时, 如果解析不成功, 不会往后传递######回复 @zb1497041270838 : 您好,请问socket请求在websocket的handler判断后加上socket的hanlder,最后怎么触发执行后续的handler?ctx.fireChannelRead???###### 不同端口监听###### public class WSProtobufServerInitialzer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new ReadTimeoutHandler(60)); // 长时间不写会断 // ====================== 增加心跳支持 start ====================== // 针对客户端,如果在1分钟时没有向服务端发送读写心跳(ALL),则主动断开 // 如果是读空闲或者写空闲,不处理 pipeline.addLast(new IdleStateHandler(0, 0, 15)); // 自定义的空闲状态检测 //判断是websocket 还是普通socket //如果是websocket 则添加HttpServerCodec()等 否则添加new ProtobufDecoder()等 pipeline.addLast(new SocketChooseHandle()); } } 在SocketChooseHandle()中通过 private String getBufStart(ByteBuf in) { int length = in.readableBytes(); if (length > MAX_LENGTH) { length = MAX_LENGTH; } // 标记读位置 in.markReaderIndex(); byte[] content = new byte[length]; in.readBytes(content); return new String(content); }获取握手的协议前缀 /** * 协议初始化 * <p> * 用来判定实际使用什么协议.</b> */ public class SocketChooseHandle extends ByteToMessageDecoder { /** * 默认暗号长度为23 */ private static final int MAX_LENGTH = 23; /** * WebSocket握手的协议前缀 */ private static final String WEBSOCKET_PREFIX = "GET /"; @Override protected void decode(ChannelHandlerContext ch, ByteBuf in, List<Object> out) throws Exception { String protocol = getBufStart(in); ChannelPipeline pipeline = ch.pipeline(); if (protocol.startsWith(WEBSOCKET_PREFIX)) { //websocket 基于http协议,所以要有http //如果不是websocket 则删除 pipeline.addLast(new HttpServerCodec()); // 对写大数据流的支持 pipeline.addLast(new ChunkedWriteHandler()); // 对httpMessage进行聚合,聚合成FullHttpRequest或FullHttpResponse // 几乎在netty中的编程,都会使用到此hanler pipeline.addLast(new HttpObjectAggregator(1024 * 64)); pipeline.addLast(new WebSocketServerProtocolHandler("/web")); // 协议包解码 pipeline.addLast(new MessageToMessageDecoder<WebSocketFrame>() { @Override protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List<Object> objs) throws Exception { ByteBuf buf = frame.content(); objs.add(buf); buf.retain(); } }); // 协议包解码时指定Protobuf字节数实例化为CommonProtocol类型 pipeline.addLast(new ProtobufDecoder(MyProbuf.DataContent.getDefaultInstance())); pipeline.addLast(new ProtobufVarint32LengthFieldPrepender()); // 协议包编码 pipeline.addLast(new MessageToMessageEncoder<MessageLiteOrBuilder>() { @Override protected void encode(ChannelHandlerContext ctx, MessageLiteOrBuilder msg, List<Object> out) throws Exception { ByteBuf result = null; if (msg instanceof MessageLite) { result = Unpooled.wrappedBuffer(((MessageLite) msg).toByteArray()); } if (msg instanceof MessageLite.Builder) { result = Unpooled.wrappedBuffer(((MessageLite.Builder) msg).build().toByteArray()); } // ==== 上面代码片段是拷贝自TCP ProtobufEncoder 源码 ==== // 然后下面再转成websocket二进制流,因为客户端不能直接解析protobuf编码生成的 WebSocketFrame frame = new BinaryWebSocketFrame(result); out.add(frame); } }); } else { // 解码和编码,应和客户端一致 //传输的协议 Protobuf pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufDecoder(MyProbuf.DataContent.getDefaultInstance())); pipeline.addLast(new ProtobufVarint32LengthFieldPrepender()); pipeline.addLast(new ProtobufEncoder()); } //添加自定义处理器 pipeline.addLast(new ProtobufHandler()); in.resetReaderIndex(); pipeline.remove(this.getClass()); } private String getBufStart(ByteBuf in) { int length = in.readableBytes(); if (length > MAX_LENGTH) { length = MAX_LENGTH; } // 标记读位置 in.markReaderIndex(); byte[] content = new byte[length]; in.readBytes(content); return new String(content); } }  

montos 2020-06-02 19:14:32 0 浏览量 回答数 0

回答

从channel是判断不出来的, websocket协议在channel中没有体现.  如果用netty, 绑定一个端口来接收socket, websocket的连接, 可以尝试如下: 1. 将它们的inbound,outbound处理类, 都在初始化时加进去, websocket的放在前面. 2. websocket在请求连接后, 会有一个http握手请求, 普通socket连接也可以在websocket 自定义inbound处理类中处理 3. 判断是否为 websocket请求, 是(pipeline中移除socket的处理类), 否(pipeline中移除websocket的处理类), 以后再来的消息, 就只会到各自的处理类中了.    ######回复 @hanzhenchao : 对的, 自定义的inbound处理类要用fireChannelRead传递处理. 有一点要注意HttpServerCodec, 这个在做解析处理时, 如果解析不成功, 不会往后传递######回复 @zb1497041270838 : 您好,请问socket请求在websocket的handler判断后加上socket的hanlder,最后怎么触发执行后续的handler?ctx.fireChannelRead???###### 不同端口监听###### public class WSProtobufServerInitialzer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new ReadTimeoutHandler(60)); // 长时间不写会断 // ====================== 增加心跳支持 start ====================== // 针对客户端,如果在1分钟时没有向服务端发送读写心跳(ALL),则主动断开 // 如果是读空闲或者写空闲,不处理 pipeline.addLast(new IdleStateHandler(0, 0, 15)); // 自定义的空闲状态检测 //判断是websocket 还是普通socket //如果是websocket 则添加HttpServerCodec()等 否则添加new ProtobufDecoder()等 pipeline.addLast(new SocketChooseHandle()); } } 在SocketChooseHandle()中通过 private String getBufStart(ByteBuf in) { int length = in.readableBytes(); if (length > MAX_LENGTH) { length = MAX_LENGTH; } // 标记读位置 in.markReaderIndex(); byte[] content = new byte[length]; in.readBytes(content); return new String(content); }获取握手的协议前缀 /** * 协议初始化 * <p> * 用来判定实际使用什么协议.</b> */ public class SocketChooseHandle extends ByteToMessageDecoder { /** * 默认暗号长度为23 */ private static final int MAX_LENGTH = 23; /** * WebSocket握手的协议前缀 */ private static final String WEBSOCKET_PREFIX = "GET /"; @Override protected void decode(ChannelHandlerContext ch, ByteBuf in, List<Object> out) throws Exception { String protocol = getBufStart(in); ChannelPipeline pipeline = ch.pipeline(); if (protocol.startsWith(WEBSOCKET_PREFIX)) { //websocket 基于http协议,所以要有http //如果不是websocket 则删除 pipeline.addLast(new HttpServerCodec()); // 对写大数据流的支持 pipeline.addLast(new ChunkedWriteHandler()); // 对httpMessage进行聚合,聚合成FullHttpRequest或FullHttpResponse // 几乎在netty中的编程,都会使用到此hanler pipeline.addLast(new HttpObjectAggregator(1024 * 64)); pipeline.addLast(new WebSocketServerProtocolHandler("/web")); // 协议包解码 pipeline.addLast(new MessageToMessageDecoder<WebSocketFrame>() { @Override protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List<Object> objs) throws Exception { ByteBuf buf = frame.content(); objs.add(buf); buf.retain(); } }); // 协议包解码时指定Protobuf字节数实例化为CommonProtocol类型 pipeline.addLast(new ProtobufDecoder(MyProbuf.DataContent.getDefaultInstance())); pipeline.addLast(new ProtobufVarint32LengthFieldPrepender()); // 协议包编码 pipeline.addLast(new MessageToMessageEncoder<MessageLiteOrBuilder>() { @Override protected void encode(ChannelHandlerContext ctx, MessageLiteOrBuilder msg, List<Object> out) throws Exception { ByteBuf result = null; if (msg instanceof MessageLite) { result = Unpooled.wrappedBuffer(((MessageLite) msg).toByteArray()); } if (msg instanceof MessageLite.Builder) { result = Unpooled.wrappedBuffer(((MessageLite.Builder) msg).build().toByteArray()); } // ==== 上面代码片段是拷贝自TCP ProtobufEncoder 源码 ==== // 然后下面再转成websocket二进制流,因为客户端不能直接解析protobuf编码生成的 WebSocketFrame frame = new BinaryWebSocketFrame(result); out.add(frame); } }); } else { // 解码和编码,应和客户端一致 //传输的协议 Protobuf pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufDecoder(MyProbuf.DataContent.getDefaultInstance())); pipeline.addLast(new ProtobufVarint32LengthFieldPrepender()); pipeline.addLast(new ProtobufEncoder()); } //添加自定义处理器 pipeline.addLast(new ProtobufHandler()); in.resetReaderIndex(); pipeline.remove(this.getClass()); } private String getBufStart(ByteBuf in) { int length = in.readableBytes(); if (length > MAX_LENGTH) { length = MAX_LENGTH; } // 标记读位置 in.markReaderIndex(); byte[] content = new byte[length]; in.readBytes(content); return new String(content); } }  

kun坤 2020-06-14 06:57:41 0 浏览量 回答数 0

问题

【精品问答】python技术1000问(1)

问问小秘 2019-12-01 21:57:48 454222 浏览量 回答数 19

回答

iperf,具体要纤细直接去看文档, 简单给你列条测试:(TCP和UDP知只是两种传输数据的协议) 1)TCP测试    服务器执行:./iperf -s -i 1 -w 1M '这裏是指定windows如果是 iperf -s则windwos默认大小为8kbyte/s    客户端执行:./iperf -c host -i 1 -w 1M   其中-w表示TCP window size,host需替换成服务器地址。    2)UDP测试    服务器执行:./iperf -u -s    客户端执行:./iperf -u -c 10.255.255.251 -b 900M -i 1 -w 1M -t 60   其中-b表示使用多少带宽,1G的线路你可以使用900M进行测试。 不给分不给力 连接速度是个很怪的概念。我们通常用连接带宽和网络延迟来表达网络连接的状态。 带宽可以用一端建立FTP服务器,另一端下载来测试。网络延时可以用PING命令来测试。 希望能帮到你。 行的。 家庭或小型办公室,如果有两台或更多的计算机,很自然地希望将他们组成一个网络。为方便叙述,以下约定将其称为局域网。在家庭环境下,可用这个网络来共享资源、玩那些需要多人参与的游戏、共用一个调制解调器享用Internet连接等等。办公室中,利用这样的网络,主要解决共享外设如打印机等,此外,办公室局域网也是多人协作工作的基础设施。 别看这样小的网络工程,在过去也是需要专业人员来进行组网配置的。那时,大部分操作的都是手工的,一般的用户都不具备相应的知识和经验。正好属于"高不成低不就"的情况,自然限制了它的发展。Windows XP的出现,打破了这种局面,这依赖它内建有强大的网络支持功能和方便的向导。用户完成物理连接后,运行连接向导,可以自己探测出网络硬件、安装相应的驱动程序或协议,并指导用户,完成所有的配置步骤。 本文介绍两种在Windows XP操作系统下的组网方案,并介绍Windows XP用于局域网中的各种很有特色的功能。 一. 目标: 组成家庭局域网:对外,可以连接Internet,允许局域网内的各个计算机共享连接。对内,可以共享网络资源和设备。 二. 采用什么网络形式? 家庭网中的计算机可能有桌面机或便携机,例如掌上电脑或笔记本机等,也可能出现各种传输介质的接口,所以网络形式上,不宜都采用有线网络,无线接口是必须考虑的。但如果可以明确定位在纯粹的有线网上,也可不设无线接口。所以,这里提供两种方案: 1. 有线与无线混合。 2. 有线。 三. 网络硬件选择 网络适配器(网卡)可采用PCI、PC或PCMCIA接口的卡(后两者多用在便携式机或笔记本机上),Windows XP也支持用USB接口的网络适配器。究竟采用那种适配器,取决于接入网络中的计算机。无论那种适配器,都需要注意与现有计算机的接口以及HUB的协调一致,USB接口的适配器可能适应性更强一些,但对于较旧的计算机,又需要注意它是否支持USB接口。 网络连接线,常用的有同轴电缆和双绞线,这都是大家熟悉的东西,不多解释。究竟采用哪一种,就看你怎么想了。 四. 可采用的网络结构和介质 以太结构:这种结构在办公室或商业用户中最为流行,熟悉的人也很多,技术资料和维护人员也容易找到,所以不多赘述。 电话线连接:这种形式主要的特色是成本很低,物理连接也很简单,适用于大部分的家庭用户。 无线电波:利用电磁波信号来传输信号,可以不用任何连线来进行通讯,并可以在移动中使用。但需要在每台计算机上加装无线适配器,成本高是肯定了。在我国,无线形式用在计算机网络通讯的还较少。在美国,用于无线网络的是一个称为IEEE 802.11b的标准协议,用于计算机近距离网络通讯。在该协议支持下,可达到的网速是11 Mbps。 五. 方案之一 这是一个有线、无线混合方案,具体结构可以参看图1。这个例子中,用4台计算机组成了一个混合网络,PC1是主机,它与外部连接有3个通路: 1. 与Internet接连的调制解调器:用于整个网络的各个计算机共享上网之用。 2. 无线适配器:用于和本网络内的无线设备之间的通讯。 3. HUB:用于"带动"本网络内的下游计算机。 该方案中的PC1、PC2机,必须用Windows XP操作系统,有线部分采用的是以太网结构连接。图中的HPNA是home phoneline network adaptor的缩写,表示家庭电话线网络适配器。图中的PC3和移动计算机,并不要求非使用Windows XP操作系统不可,别的windows版本也行。移动计算机和主机之间的网络连接利用的是无线形式。 如果希望建立混合网络,这种方案已经具备典型的功能,并且不需要花费很大就可以扩充网络规模。 关于连通操作: 图1显示的结构只能表示物理连接关系,物理连接完成后,还需要进行连通操作,网络才可真正投入使用。连通操作包括局域网内部各个计算机之间的连通,和局域网与Internet之间的连通。前者连通建立的步骤如下: 1. 鼠标点击 开始,进入控制面板,点击"Network and Internet Connections网络和Internet连接",选择网络连接( Network Connections),进行下一步。 2. 选择进行"两个或多个LAN的连接" 3. 右键点击一个连接. 4. 确定完成连接任务. 局域网之内的连通操作就完成了。 再说局域网与Internet之间的连通,这种情况主要考虑速度与成本两方面的兼顾。多机上网,最省事的办法是每个机器占据一条独立的电话线,但这不是一般用户能承受起的,资源的浪费也太大。另一个办法,可以使用住宅网关,但这样成本需要增加,不是最佳途径。比较好的方法是使用一个计算机作为主机服务器。这不仅技术上可行,还有很多别的优点,如: ①:由于Windows XP有内建的防火墙,主机介于Internet和终端机之间,可以利用主机的防火墙保护局域网中的分机免受来自Internet的攻击。 ②:主机是"隐匿在" Internet和局域网之间的,充当了网关的脚色,在分机上,用户感觉好像自己是直接连在Interne上一样,察觉不到中间还有主机存在。特别是可以使局域网中的每台计算机同时上网。大大减少了设备投资。 ③:除主机必须使用Windows XP操作系统之外,局域网内的计算机可使用早期的windows版本。 ④:如果局域网中需要使用不同的媒体(例如有线和无线混合),可以利用Windows XP作为过渡的网桥。 ⑤:虽然有网络资源和设备的共享功能,但也可以限制别人对私有文件和数据的访问,特别是将文件存放在主机上的时候,更具有这种优势可用。 ⑥:利用"万能即插即用"功能,可以随时扩充局域网的规模。 六. 方案之二 下面是这种方案的结构示意图。该方案适用于小型办公室。与上一个方案比较,主要是去掉了无线部分,主机与分机之间不采用电话线连接,而是采用了电缆或双绞线连接。所有分机都通过一个HUB与主机连接到Internet上,并可以支持打印机共享。这其实就是最常见的那种局域网的结构。 该方案完成物理连接之后,还需要进行下列操作: 1. 打开网络连接文件夹或找到网络连接的图标. 2. 右键点击"connection to the Internet you want to share(共享Internet连接)"然后再右键点击"Properties(属性)" 3. 选择"Advanced(高级)"任务条。 4. 选择"Allow other networkusers to connect through this computer′s Internet connection(允许另外用户通过这个计算机连接到Internet)"检查框,并选定。 5. 点击 OK.结束操作。 启用Windows XP的防火墙,必须进行设置,不设置是不起作用的。设置过程: 1.打开网络连接文件夹或找到网络连接的图标. 2.右键点击"connection to the Internet you want to share(共享Internet连接)"然后再右键点击"Properties(属性)" 3.选择"Advanced(高级)"任务条。 4. 选择"Protect my computer and network by limitingor preventing access to this computer from the Internet(利用这个计算机限制从Internet进入的访问并保护我的计算机和网络" ,在其下面有一个Internet连接防火墙的检查框,鼠标点击选定。 5. 点击 OK.结束操作。 七. 几点说明 A.主机必须采用Windows XP操作系统,局域网内的计算机可以使用早一些的windows版本,如:windows98、windows ME、windows2000等等。 B.这里提供的是典型的情况,想扩充网络规模基本上可以照此叠加。 C.本文是依据英文测试版本进行的试验,不能保证将来的正式版本。特别是中文正式版本的性能与此完全一致。 参考资料: 创建局域网及配置管理 一.概念: (一).局域网的概念: 局域网做为网络的组成部分,发挥了不可忽视的作用。我们可以用Windows 9X把众多的计算机联系在一起,组成一个局域网,在这个局域网中,我们可以在它们之间共享程序、文档等各种资源,而不必再来回传递软盘;还可以通过网络使多台计算机共享同一硬件,如打印机、调制解调器等;同时我们也可以通过网络使用计算机发送和接收传真,方便快捷而且经济。 局域网是一个范围可大可小、简单的只有2台运行着Windows95的计算机连网(以工作组方式工作),也可以是幅员辽阔的高速ATM网和以太网混合使用、运行多种平台的大型企业。 (二).网络的类型: 1、按网络的地理位置分类 a.局域网(LAN):一般限定在较小的区域内,小于10km的范围,通常采用有线的方式连接起来 b.城域网(MAN):规模局限在一座城市的范围内,10~100km的区域。 c.广域网(WAN):网络跨越国界、洲界,甚至全球范围。 目前局域网和广域网是网络的热点。局域网是组成其他两种类型网络的基础,城域网一般都加入了广域网。广域网的典型代表是Internet网。 (二).硬件指南:网络硬件设备 组成小型局域网的主要硬件设备有网卡、集线器等网络传输介质和中继器、网桥、路由器、网关等网络互连设备。以下主要介绍网卡、集线器等网络传输介质和中继器、网桥、路由器、网关等局域网互连设备。 1.网卡 网卡(Network Interface Card,NIC)也叫网络适配器,是连接计算机与网络的硬件设备。网卡插在计算机或服务器扩展槽中,通过网络线(如双绞线、同轴电缆或光纤)与网络交换数据、共享资源。 Realtek 10/100M,这是我们实例中所使用的网卡 二.组网: 返回顶部 (一).硬件配置:服务器:普通PC机,主板:intel 815,硬盘:迈拓40G,CPU:PIII933,内存:512M ,显示器:ACER。 其他:双绞线一箱(300m),16口HUB一个,RJ45头32个,网卡:Realtek 10/100M 16块。。 由于服务器需要安装两块网卡来用SyGate维护管理,两个网卡的设置请参阅如下的动画。 三.网络维护: 返回顶部 SyGate 4.0是一种支持多用户访问因特网的软件,并且是只通过一台计算机,共享因特网帐号,达到上网的目的。使用SyGate 4.0,若干个用户能同时通过一个小型网络(包括您的笔记本电脑),迅速、快捷、经济地访问因特网。SyGate 4.0能在目前诸多流行的操作系统上运行,譬如:Windows95、Windows98、Windows NT, Windows2000等操作系统;同时,SyGate 4.0还支持多数的因特网连接方式,这包括:调制解调器(模拟线路)拨入、ISDN(综合业务数字网)、线缆调制解调器(Cable Modem)、ADSL以及DirectPC等方式。 SyGate 4.0具有以下优势: 易于安装 SyGate在数分钟之内便可以安装完成,并且通常不需要其他外加的设置。和其他代理服务器软件(proxy server)不同的是,SyGate仅安装Server便可以了。 易于使用 SyGate拥有直观的图形化界面,懂得操作Windows的人员均会操作。SyGate启动后便在后台运行,不需要人工的干预。当SyGate检测到局域网内有上网 要求时,它能自动地连接到因特网上,免去了每次需要手工拨号的烦恼。用户可以不间断地、透明地浏览因特网、收发电子邮件、聊天、使用FTP以及操作其他的小程序等等。局域网内非Windows用户,如Macintosh、Solaris和Linux,均能通过TCP/IP协议上网。 四.Windows 对等网创建与维护 返回顶部 (一).建网软件要求 在一个局域网中,Windows 95、98、NT和2000等操作系统可以并存。当然,即使你的电脑是在DOS下面跑的,也可以实现联网。由于Windows操作系统才是广泛应用的系统,本文不准备讨论DOS联网。 建网硬件要求 要组建电脑网络,无疑需要能将电脑连在一起的硬件设备。最简单的办法是,使用特制的电缆,将两台电脑的并口或者串口联接起来,通过Windows的“直接电缆连接”实现联网。这种联接电缆可以自制,也可以到电脑城购买。其缺点是,只能联接两台电脑,联网距离较短、方式古板,实际应用很不方便,通常要求将一台电脑用作服务器,另外一台用作客户端来实现联网。 但更为普遍采用的是网卡加网线的联网方式。从插槽上分,网卡有ISA和PCI两种;从速度上分,网卡又有10MB和100MB甚至传输速度更高的网卡。要求不高的话,一块PCI 10MB网卡就够用了。 五.疑难解答 返回顶部 (一).网卡安装故障检查方法 如果无法安装网卡驱动程序或安装网卡后无法登录网络,请按下述步骤检查处理: 1.选择“控制面板”/“系统”图标,打开“系统属性”窗口; 2.在“系统属性”窗口的“设备管理”标签的“按类型查看设备列表”中,双击“网络适配器”条目前的“ ”号将其展开,其下应当列出当前网卡; 3.如果“设备管理”标签中没有“网络适配器”条目或当前网卡前有一“X”号,说明系统没能识别网卡,可能产生的原因有网卡驱动程序安装不当、网卡硬件安装不当、网卡硬件故障等等; 参考 LAN(局域网)一词指位于同一区域甚至同一建筑物内的中小型计算机网络,字典上的解释是:将计算机和字处理机等电子办公设备连接在一起构成的办公室或建筑物内的网络系统。相信大多数人都在学校里、当地图书馆或朋友家里。接触过局域网。 随着宽带互联网日益流行,许多人家里都有几台计算机,家庭局域网正在形成规范。通过局域网共享宽带互联网访问可降低成本,不需要每台计算机都连接调制解调器和单独的IP地址。但如何构建一个家庭局域网共享宽带互联网访问呢? 网络带宽表示 网络带宽以兆位秒Mbps测量,通常不用兆字节秒MBps表示。一个字节有八个二进制位组成,多数人都熟悉MBps。当前局域网多为10base-T(10Mbps或1.25MBps)和100base-TX(100Mbps或12.5MBps)的以太网,使用类似标准电话线的RJ-45接口,通过网络电缆把集线器(或路由器、交换器)和计算机连接起来就构成了以太网。 网络布线 开始组建家庭局域网之前,应多少了解一些可用网络电缆的区别。这取决你家中PC机需要安排的位置,因为可能需要在墙上打眼,以穿过五类网络电缆。对家里地方不宽敞的人,这可能是令人畏缩的任务,甚至不太可能。如果你想避免穿墙打眼的麻烦,无线局域网也很方便,但应注意,无线局域网通常速度不够快,花费也高的多。另一种选择可考虑10Mbps电话线套件,利用你现成的电话线在计算机之间传送数据,可购买D-Link,Linksys,3Com和Netgear等公司的产品。不想采用无线局域网的人,可选择五类双绞线网络电缆。如果对电缆不熟悉,下面列出了电子工业协会EIA关于电缆分类的解释。根据电缆的速度和质量,可将电缆分为六类: 一、二类电缆:数据传输速度低于10Mbps(普通电话线) 三类电缆:数据传输速度达16 Mbps 四类电缆:数据传输速度达20 Mbps 五类电缆:数据传输速度达100 Mbps 五类电缆增强:数据传输速度达200 Mbps 六类电缆:数据传输速度达600 Mbps 五类电缆十分普通,连接以太网费用也较低。如果你计划穿墙打眼或使用超过50英尺五类电缆,应购买细电缆,自己动手将RJ-45插头接在电缆两端。注意,别忘了电缆穿过墙之后再接RI-45插头。 连接RJ-45插头 五类电缆连接RJ-45插头并不困难,但需要专用连接工具,可从当地五金商店买一把或从朋友处借用。操作时小心剪掉约1/4英寸电缆外塑料皮,露出电缆里面8根彩色线,注意放入RJ-45连接器里面电缆线的次序: 1、白绿 2、绿 3、白橙 4、兰 5、白兰 6、橙 7、白橙 8、棕 应仔细展开8条彩色编码线,放入RJ-45插孔中,用专用工具压紧。有条件时可用RJ-45测试器验证一下是否连接可靠,以免将来麻烦。 需要的硬件 首先确保每台计算机里都安装了网卡,100base-TX或10base-T网卡,型号、尺寸任意。注意,一般选PCI网卡,各网卡速率应一致。100base-TX网卡数据传输率较高,适合于大量数据传输,如数字电影或其它大的多媒体文件。 组建局域网需要使用集线器,交换器或内置集线器的路由器,集线器只不过用于将你所有的计算机连到局域网上。如果你只有2台计算机并且不打算增加数量,可以用一段电缆直接将2台计算机连起来,缺点是你试图共享宽带互联网访问仍然有麻烦。如果你想多台计算机访问宽带互联网,使用路由器是个好主意,可以选购Netgaer,D-Link和Linksys等著名网络公司的产品。 典型的以太网使用集线器或交换器,两种设备都有单独的连接器,用于将每台计算机连接到局域网上。集线器与交换器的主要差别在于吞吐量,集线器在所有在用的端口间分配吞吐量,因此4端口100base-TX集线器每个在用的端口只有25Mbps吞吐量。交换器更贵些,但允许每个端口全速运行。 假如你准备设置一个只有单个宽带互联网连接的局域网,应确保你的DSL或有线电缆供应商给你提供的是外置调制解调器。多数外置调制解调器通过网卡连接到你的计算机,你可把具有调制解调器的那台计算机设置为路由器,虽然这并不推荐。作为一个例子,你将电话插头接入宽带调制解调器,然后经RJ-45(双绞线)电缆连至集线器/交换器/路由器,从此,你的任一台计算机都可连接到互联网上。 设置Windows网络 确保你准备在局域网上使用的每台计算机,都有足够的五类电缆已连到了集线器或路由器。现在你可能已安装了适当的网卡以及相应的驱动程序,右击“网络邻居”,选择“属性”,可以看到当前已经安装的协议和网卡。要设置网络,应确保所用的网卡已安装了TCP/IP协议。如果你使用的微软操作系统是Windows98或更高版本,网络设置相当简单,Windows网络作为操作系统的基本选项之一应该已经安装了。如果你至少在一台计算机上使用的是Windows Me,你可运行家庭网络向导,将一步步引导你完成设置。记住,你需要使用相同的组名设置你网络中的每台计算机。在Windows95/98中,需要进入网络属性,并确保所有设置为缺省。你的互联网服务供应商ISP可能已经告诉你,如何设置TCP/IP,怎样连接到互联网。你可能是静态IP地址,或是动态IP地址,取决于你的ISP。静态IP地址设置需要的时间稍长一点,如果你想给互联网用户提供服务,如FTP,Web服务器或任何其它服务,静态IP地址是不错的。如果你分配的是IP地址,你的TCP/IP协议属性获得的应是自动选择的IP地址。要检查你的计算机是否已被集线器/路由器分配了一个IP地址,可使用Windows TP配置(进入开始 传输大点的东西,用iostat 1 查看io 来源于网络,供您参考

保持可爱mmm 2019-12-02 02:20:25 0 浏览量 回答数 0

回答

1 密码键盘:新国都的 G101银联密码键盘还挺好用。 2 系统对接:密码键盘是和POS机配合使用的,所以间接通过POS机和Web对接。######直接调用银联支付接口就行了,关心密码键盘干什么,从你开始调用支付接口,到支付完成,这中间的所有东西都是银联的接口去负责,不需要你去参与,银联也不会让你参与,支付完成后,银联会给你的服务器发通知,接到通知后处理订单数据就可以了######他应该是要硬件,像银行窗口那个小的密码输入键盘######直接找对应的厂商就可以######居然想接,中国山东找蓝翔.....######我们公司用的是王府井的解决方案,目前还不错。###### 引用来自“泡在妞里的feel”的评论 1 密码键盘:新国都的 G101银联密码键盘还挺好用。 2 系统对接:密码键盘是和POS机配合使用的,所以间接通过POS机和Web对接。 密码键盘我们已经找了几个厂商。 其实我们要的是支持刷卡的POS机。 现在问题是怎么让POS机和Web系统进行对接,应用场景我在问题后面补充说明了,请问有什么解决方案吗?  ######你的意思是:把POS读到的卡号信息和密码键盘读到的密码(密文形式)显示到PC的web上。如果是这样,那也很简单啊,一般POS都会有RS232接口或者USB接口,这个接口就可以将账号和密码(密文形式)传送到PC,继而在web显示。 但是,这其中有个安全问题,一般符合银联规范的POS机,是不会把持卡人的账号和密码等敏感信息,让外界轻易获取到的(如上RS232和USB),除非你的POS机是定制的。###### 引用来自“夜苍狼”的评论直接调用银联支付接口就行了,关心密码键盘干什么,从你开始调用支付接口,到支付完成,这中间的所有东西都是银联的接口去负责,不需要你去参与,银联也不会让你参与,支付完成后,银联会给你的服务器发通知,接到通知后处理订单数据就可以了 不只是银行卡,还有可能是会员卡。 然后希望用户的卡号信息和密码【密文方式】能够在WEB系统的浏览器界面体现出来。######  现在是这样的情况: 我们的应用场景为: 我们自己的WEB系统运行在PC机上,涉及到交易过程,在窗口有一个类似表单的窗口,有账号和密码框。 我们希望这个交易过程通过用户在POS机上刷卡(不仅仅是银行卡,也可能是会员卡),用户刷卡之后,在POS上输入密码,用户的卡号和密码信息会显示在WEB界面的窗口上,其中密码是密文处理的。###### 引用来自“泡在妞里的feel”的评论 1 密码键盘:新国都的 G101银联密码键盘还挺好用。 2 系统对接:密码键盘是和POS机配合使用的,所以间接通过POS机和Web对接。 引用来自“我是林海风”的评论 密码键盘我们已经找了几个厂商。 其实我们要的是支持刷卡的POS机。 现在问题是怎么让POS机和Web系统进行对接,应用场景我在问题后面补充说明了,请问有什么解决方案吗?   嗯嗯,是的,是计划定制POS机。 数据传输会加密处理,我们自己会管理密钥。 这两天也在跟厂商沟通,他们的确要做一些编码工作。 另外,还想跟你请教一下,在浏览器这一块,有没有比较常规的控件支持这类场景?OCX控件?###### 引用来自“夜苍狼”的评论直接调用银联支付接口就行了,关心密码键盘干什么,从你开始调用支付接口,到支付完成,这中间的所有东西都是银联的接口去负责,不需要你去参与,银联也不会让你参与,支付完成后,银联会给你的服务器发通知,接到通知后处理订单数据就可以了 需要带刷卡功能,和银行办业务外设的那种密码键盘还是有区别的。

kun坤 2020-06-04 18:07:20 0 浏览量 回答数 0

问题

阿里云RedHatLinux服务器安装DiscuzX3.0详细笔记适合新手因为我就是个新手

no.9527 2019-12-01 21:24:31 28702 浏览量 回答数 7

问题

应用 AXIS 开始 Web 服务之旅:报错

kun坤 2020-06-08 11:01:46 3 浏览量 回答数 1

回答

Re史上最详细阿里云ECS安装wordpress教程 【Xshell连接阿里云ECS】 准备好连接linux服务器的工具,推荐用xshell和xftp。 xshell 是一个强大的安全终端模拟软件,它支持SSH1, SSH2, 以及Microsoft Windows 平台的TELNET 协议。 下载地址:http://www.newhua.com/soft/36383.htm Xftp 是一个基于 MS windows 平台的功能强大的SFTP、FTP 文件传输软件。 下载地址:http://www.newhua.com/soft/143.htm 一、打开xshell 二、设置云服务器登录信息 三、设置服务器帐号密码 四、设置字符集编码 五、连接后的庐山正面目 阿里云服务器是纯净态的,所以只有看见这样黑黑的面板,软件都是需要自己来安装。------------------------- Re史上最详细阿里云ECS安装wordpress教程 【阿里云ECS(linux)挂载数据盘】 注意:如果是用阿里云一键wep安装的话就不需要挂载数据盘,自动挂载了!首先键入命令查看是否有数据盘 fdisk -l 红框标出的是数据盘大小21.4GB    数据盘进行分区 fdisk  /dev/xvdb    依次输入“m”(查看命令参数)在依次输入“n”,“p”,“1”,”两次回车“,“wq”    格式化新分区 mkfs.ext3 /dev/xvdb1    添加分区信息 echo '/dev/xvdb1  /mnt ext3    defaults    0  0' >> /etc/fstab 命令写入新分区信息。然后使用“cat /etc/fstab”命令查看,出现以下信息就表示写入成功。    挂载新分区使用 mount -a 命令挂载新分区,然后用 df -h 命令查看,出现以下信息就说明挂载成功, 出现(/dev/xvdb1     20G   173M  19G   1%   /mnt)就表示挂载成功了。 ------------------------- Re史上最详细阿里云ECS安装wordpress教程 【阿里云ECS(linux)一键安装web环境】 下载一键安装包 下载一键安装包(ubuntu12.04) 打下面的命令去主目录(/home)看下 cd /home 现在用键盘敲入下面这行命令 cd /home && mkdir tmp && cd tmp 用xftp上传环境安装文件回到shell界面,用ll命令看下情况 ll 是不是多了一个sh目录 接下来按照说明,分步骤敲入安装命令chmod –R 777 sh cd sh ./install.sh出现了一个选择 提示,进入web服务器版本的选择界面这里您可以根据需要选择apache或者nginx服务器,这里是2个服务器的介绍 apache:http://baike.baidu.com/view/28283.htm nginx:http://baike.baidu.com/view/926025.htm这里我们选择nginx,输入n,回车(注意:这样随你喜欢选择没有必要纠结) 到这里,我们就正式进入环境安装环节了。你可以泡杯茶休息下。一般这个过程会持续半个小时的样子。大家有疑问了。那我怎么登录ftp和mysql呢?   在命令行里输入:cat account.log 看到了没? ftp的用户名是:www mysql的用户名是:root 密码就在屏幕上了! 好了。所有配置都已经完成了。是不是很简单! ----------------------------------------------------------------------网站目录:/alidata/www服务器软件目录:/alidata/server Mysql 目录 /alidata/server/mysql Php目录/alidata/server/php   选择了nginx 那么会有一个nginx 目录在 /alidata/server/nginx/   Nginx 配置文件在/alidata/server/nginx/conf   Nginx虚拟主机添加 你可以修改/alidata/server/nginx/conf/vhosts/phpwind.conf  选择了apache那么会有一个httpd 目录在 /alidata/server/httpd   apache 配置文件在/alidata/server/httpd/conf ------------------------- Re史上最详细阿里云ECS安装wordpress教程 【阿里云ECS(linux)安装wordpress程序】 默认安装的是phpwind的论坛程序,当然不是我们想要的程序了,所以就需要删除phpwind程序装上我们自己wordpress程序 用xftp链接服务器(ps:怎么链接上文已经说明),进入alidata/www/phpwind/下面就是程序文件,ctrl A全选删除,上传已经下载好的wordpress,注意的是wordpress程序是你原网站的所有程序,如下图: 服务器ip地址在浏览器中打开112.124.xx.xxx,打开后你会看见wordpress安装键面,需要输入数据库名称、数据库用户名、密码、数据库表前缀。 到这里你会发现提示,数据库密码正确,但无法创建数据库表。这里就需要数据库管理程序phpmyadmin(ps:如果你的服务器配置高手可以直接命令创建数据库表)。首先下载phpmyadmin 上传到/alidata/www/phpwind文件目录下如下图:phpmyadmin文件夹名可自定义(ps:到这里你可能是明白了phpmyadmin其实就是一个网站而已)用:ip地址/phpmyadmin文件夹名,在浏览器中打开进入phpmyadmin网站,输入数据库用户名,密码进入phpmyadmin后台,创建数据库表怎么创建数据库表我想大家应该都会的。 ------------------------- Re史上最详细阿里云ECS安装wordpress教程 【阿里云ECS(linux)安装postfix发送邮件】 其实这里可以使用插件实现,但众所周知wordpress插件一旦装的太多就会造成网站打开速度变慢,为什么要选择安装postfix软件呢,在阿里云论坛有网友说装sendmail,博主刚开始也是折腾sendmail,但群众眼睛是雪亮的,sendmail发件速度太慢了(ps:一个邮件就需要30多秒出去),相对于postfix的秒射那正是爽!我喜欢这只小老鼠! 一、安装postfix如果您安装了sendmail请先卸载它命令: yum remove sendmai 安装: yum install postfix 更改默认MTA为Postfix命令: /usr/sbin/alternatives --set mta /usr/sbin/sendmail.postfix 再次检查下是否将MTA改为Postfix了。命令: alternatives --display mta 二、配置Postfix相关参数 1.找到 #myhostname = host.domain.tld , 修改成:myhostname = mail.yujzw.com (你自己的域名)2.找到 #mydomain = domain.tld ,将等号后面的部分改写为你的域名,修改成:mydomain = yujzw.com(此处设置将成为E-mail地址“@”后面的部分)3.找到 #myorigin = $mydomain ,只需将首行的#号去掉即可,其他无需变动4.找到 inet_interfaces = localhost ,将“localhost”改为“all” ,接受来自所有网络的请求5.找到 mydestination = $myhostname, localhost.$mydomain,localhost,在行尾添加“$mydomain”,修改成:mydestination = $myhostname,localhost.$mydomain, localhost, $mydomain ,指定发给本地邮件的域名6.找到 #relay_domains = $mydestination ,只需要将行首的#去掉,定义允许转发的域名7.找到 #mynetworks = 168.100.189.0/28, 127.0.0.0/8 去掉前面的#号,指定内网和本地的IP地址范围,按照情况修改,一般无需变动8.找到 relay_domains = ,修改成: relay_domains =9.找到 #home_mailbox = Maildir/ ,去掉行首的#,指定用户邮箱目录启动命令 service postfix start 检测是否运行中 master (pid 25579) is running... 设置开机启动 chkconfig postfix on 安装已经结束了,此功能已经实现邮件发送,不需要配置邮件服务器。这里要注意的是!如果你没有设置过php.ini文件的话就需要重新设置一边,否自不能实现发送邮件。 设置php.ini文件 编辑php.ini vi /alidata/server/php-5.2.17/etc/php.ini-zend_optimizer.bakvi /alidata/server/php-5.2.17/etc/php.ini 找到 ;sendmail_path = 按 i 进入编辑,将这行修改为 sendmail_path = /usr/sbin/sendmail -t -i 按 Esc 键退出编辑,输入 :wq 保存退出,重新启动阿里云ecs服务器。 wordpress邮件检测发送功能 WordPress不能发信是不是由博客空间引起的,可以使用以下方法检测。新建一个php文件,命名为mail.php ,打开并填上以下代码: 12345678<?php    $txt = "hello";    // 以下的邮箱地址改成你的    $mail = 'somebody@xxx.com';      // 发送邮件    mail($mail, "My subject", $txt);    echo 'message was sent!';    ?>保存并上传至你的网站根目录,并在浏览器运行:网址: http://你的博客网址/mail.php 邮箱查收邮件,如果收到标题为 My subject 的邮件,说明你的空间支持mail()函数发送邮件,也就是WordPress默认的发信方式。 ------------------------- Re史上最详细阿里云ECS安装wordpress教程 由于阿里云图片上传限制。不能一次性编辑完,日后会上传 ------------------------- 回16楼arens的帖子 下面都是“红字”------------------------- 回24楼水清的帖子 红字------------------------- 回26楼andln的帖子     cd /home && mkdir tmp && cd tmp 应该是没有问题的,有能是阿里一键安装包改了参数,官方教程里面没有出现这句命令。具体http://help.aliyun.com/view/13435438.html------------------------- 回28楼guzheng的帖子 一键wep安装是首次安装时会默认自动挂载数据盘,阿里云的教程说的是后期需要挂载多个数据盘。具体操作了就知道了,刚开始我也是挂载了数据盘在一键wep安装,出现重复挂载信息。------------------------- 回50楼emperorboy的帖子 阿里云ECS数据库名默认是localhost,密码、表前缀都是自己定义------------------------- 回54楼天佑的帖子 慢慢来,我也是新手,花了7天时间搞明白的------------------------- 回83楼星空2012的帖子 没有使用过类似的缓存插件。------------------------- 回85楼sunpro的帖子 帖子已经被管理员倒序,请到最后查看!------------------------- 回134楼wujianmin的帖子 是两个  “LL”------------------------- 回137楼wujianmin的帖子 wdCP也行,如果是个人站长或者打算长期从事技术职业的,还是建议自己捣鼓一下。------------------------- 回148楼stneng的帖子 一般情况下,要使域名能访问到网站需要两步,第一步,将域名解析到网站所在的主机,第二步,在web服务器中将域名与相应的网站绑定。但是,如果通过主机IP能直接访问某网站,那么把域名解析到这个IP也将能访问到该网站,而无需在主机上绑定,也就是说任何人将任何域名解析到这个IP就能访问到这个网站。可能您并不介意通过别人的域名访问到您的网站,但是如果这个域名是未备案域名呢?一旦被查出,封IP、拔线甚至罚款的后果都是需要您来承担的。某些别有用心的人,通过将未备案域名解析到别人的主机上,使其遭受损失,这是一种新兴的攻击手段------------------------- 回150楼stneng的帖子 可以!  设置(程序名.conf)文件------------------------- 回 205楼(冰冰__恋) 的帖子 我装的是阿里云os,不是ubunto,个人没用过ubunto,也无法给你说明------------------------- 回 207楼(学历猫) 的帖子 镜像市场只是安装一个系统,不安装wordpress,wordpress需要自己上传------------------------- 回 216楼(moros) 的帖子 看一看.conf配置文件,设置的目录------------------------- 回 219楼(yangtser) 的帖子 phpmydamin只是一个网站不需要设置------------------------- 回 230楼(啊李晕) 的帖子 http://www.yujzw.com/tag/aliyunecs------------------------- 回 241楼(金枝福) 的帖子 是的,512M的基本搞定不定wordpress,我以前是1G,现在也是2G的

爱映疯wp 2019-12-02 02:49:31 0 浏览量 回答数 0

回答

break; 11 case "0002,0013"://文件生成程序的标题 12 return "SH"; 13 break; 14 case "0008,0005"://文本编码 15 return "CS"; 16 break; 17 case "0008,0008": 18 return "CS"; 19 break; 20 case "0008,1032"://成像时间 21 return "SQ"; 22 break; 23 case "0008,1111": 24 return "SQ"; 25 break; 26 case "0008,0020"://检查日期 27 return "DA"; 28 break; 29 case "0008,0060"://成像仪器 30 return "CS"; 31 break; 32 case "0008,0070"://成像仪厂商 33 return "LO"; 34 break; 35 case "0008,0080": 36 return "LO"; 37 break; 38 case "0010,0010"://病人姓名 39 return "PN"; 40 break; 41 case "0010,0020"://病人id 42 return "LO"; 43 break; 44 case "0010,0030"://病人生日 45 return "DA"; 46 break; 47 case "0018,0060"://电压 48 return "DS"; 49 break; 50 case "0018,1030"://协议名 51 return "LO"; 52 break; 53 case "0018,1151": 54 return "IS"; 55 break; 56 case "0020,0010"://检查ID 57 return "SH"; 58 break; 59 case "0020,0011"://序列 60 return "IS"; 61 break; 62 case "0020,0012"://成像编号 63 return "IS"; 64 break; 65 case "0020,0013"://影像编号 66 return "IS"; 67 break; 68 case "0028,0002"://像素采样1为灰度3为彩色 69 return "US"; 70 break; 71 case "0028,0004"://图像模式MONOCHROME2为灰度 72 return "CS"; 73 break; 74 case "0028,0010"://row高 75 return "US"; 76 break; 77 case "0028,0011"://col宽 78 return "US"; 79 break; 80 case "0028,0100"://单个采样数据长度 81 return "US"; 82 break; 83 case "0028,0101"://实际长度 84 return "US"; 85 break; 86 case "0028,0102"://采样最大值 87 return "US"; 88 break; 89 case "0028,1050"://窗位 90 return "DS"; 91 break; 92 case "0028,1051"://窗宽 93 return "DS"; 94 break; 95 case "0028,1052": 96 return "DS"; 97 break; 98 case "0028,1053": 99 return "DS"; 100 break; 101 case "0040,0008"://文件夹标签 102 return "SQ"; 103 break; 104 case "0040,0260"://文件夹标签 105 return "SQ"; 106 break; 107 case "0040,0275"://文件夹标签 108 return "SQ"; 109 break; 110 case "7fe0,0010"://像素数据开始处 111 return "OW"; 112 break; 113 default: 114 return "UN"; 115 break; 116 } 117 } 复制代码 最关键的两个tag: 0002,0010 普通tag的读取方式 little字节序还是big字节序 隐式VR还是显示VR。由它的值决定 复制代码 1 switch (VFStr) 2 { 3 case "1.2.840.10008.1.2.10"://显示little 4 isLitteEndian = true; 5 isExplicitVR = true; 6 break; 7 case "1.2.840.10008.1.2.20"://显示big 8 isLitteEndian = false; 9 isExplicitVR = true; 10 break; 11 case "1.2.840.10008.1.20"://隐式little 12 isLitteEndian = true; 13 isExplicitVR = false; 14 break; 15 default: 16 break; 17 } 复制代码 7fe0,0010 像素数据开始处 整理 根据以上的分析相信解析一个dicom格式文件的过程已经很清晰了吧 第一步:跳过128字节导言部分,并读取"DICM"4个字符 以确认是dicom格式文件 第二步:读取第一部分 也就是非常重要的文件元dataElement 。读取所有0002开头的tag 并根据0002,0010的值确定传输语法。文件元tag部分的数据元素都是以显示VR的方式表示的 读取它的值 也就是字节码处理 别告诉我说你不会字节码处理哈。传输语法 说得那么官方,你就忽悠吧 其实就确定两个东西而已 1字节序 这个基本上都是little字节序。举个例子吧十进制数 35280 用十六进制表示是0xff00 但是存储到文件中你用十六进制编辑器打开你看到的是这个样子00ff 这就是little字节序。平常我们用的x86PC在windows下都是little字节序 包括AMD的CPU。别太较真 较真的话这个问题又可以写篇博客了。 2确定从0002以后的dataElement的VR是显示还是隐式。说来说去0002,0010的值就 那么固定几个 并且只能是那么几个 这些都在那个北美放射学会定义的dicom标准的第六章 有说明 : 1.2.840.10008.1.2 Implicit VR Little Endian: Default Transfer Syntax for DICOM Transfer Syntax 1.2.840.10008.1.2.1 Explicit VR Little Endian Transfer Syntax 1.2.840.10008.1.2.2 Explicit VR Big Endian Transfer Syntax 上面的那段代码其实就是这个表格的实现,讲到这里你会觉得多么的坑爹啊 是的dicom面向对象的破概念非常烦的。 第三步:读取普通tag 直到搜寻到7fe0,0010 这个最巨体的存储图像数据的 dataElement 它一个顶别人几十个 上百个。我们在前一步已经把VR是显示还是隐式确定 通过前面的图 ,也就是字节码处理而已无任何压力。显示情况下根据VR 和Len 确定数据类型 跟数据长度直接读取就可以了。隐式情况下这破玩艺儿有点烦,只能根据tag 字典确定它是什么VR再才能读取。关于这个字典也在dicom标准的第六章。上面倒数第二段代码已经把重要的字典都列了出来。 第四步:读取灰度像素数据并调窗 以GDI的方式显示出来。 说实话开始我还以为dicom这种号称医学什么影像的专家制定出来的标准 读取像素数据应该有难度吧 结果没想到这么的傻瓜。直接按像素从左到右从上到下 一行行依次扫描。两个字节表示1个像素普通Dicom格式存储的是16位的灰度图像,其实有效数据只有12位,除去0 所以最高值是2047。比如CT值 从-1000到+1000,空气的密度为-1000 水的密度为0 金属的密度为+1000 总共的值为2000 调窗技术: 即把12级灰度的数据 通过调节窗宽窗位并让他在RGB模式下显示出来。还技术呢 说实话这个也是没什么技术含量的所谓的技术,两句代码给你整明白。 调节窗宽窗位到底什么意思,12位的数据那么它总共有2047个等级的灰度 没有显示设备可以体现两千多级的明暗度 就算有我们肉眼也无法分辨更无法诊断。我们要诊断是要提取关键密度值的数据 在医院放射科呆久了你一定经常听医生讲什么骨窗 肺窗 之类的词儿,这就是指的这个“窗”。比如有病人骨折了打了钢板我们想看金属部分来诊断 那么我们应该抓取CT值从800到1000 密度的像素 也就是灰度值 然后把它放到RGB模式下显示,低于800的不论值大小都显示黑色 高于1000的不论值大小都显示白色。 通过以上例子那么这个范围1000-800=200 这个200表示窗宽,800+(200/2)这个表示窗位 一句话,从2047个等级的灰度里选取一个范围放到0~255的灰度环境里显示。 怎样把12位灰度影射到8位灰度显示出来呢,还怎么显示 上面方法都给说明了基本上算半成品了。联想到角度制弧度制,设要求的8位灰度值为x 已知的12位灰度值为y那么:x/255=y/2047 那么x=255y/2047 原理不多讲 等比中项十字相乘法 这个是初中的知识哈。初中没读过的童鞋飘过。。。 原理过程讲完了 代码走起 复制代码 1 class DicomHandler 2 { 3 string fileName = ""; 4 Dictionary tags = new Dictionary();//dicom文件中的标签 5 BinaryReader dicomFile;//dicom文件流 6 7 //文件元信息 8 public Bitmap gdiImg;//转换后的gdi图像 9 UInt32 fileHeadLen;//文件头长度 10 long fileHeadOffset;//文件数据开始位置 11 UInt32 pixDatalen;//像素数据长度 12 long pixDataOffset = 0;//像素数据开始位置 13 bool isLitteEndian = true;//是否小字节序(小端在前 、大端在前) 14 bool isExplicitVR = true;//有无VR 15 16 //像素信息 17 int colors;//颜色数 RGB为3 黑白为1 18 public int windowWith = 2048, windowCenter = 2048 / 2;//窗宽窗位 19 int rows, cols; 20 public void readAndShow(TextBox textBox1) 21 { 22 if (fileName == string.Empty) 23 return; 24 dicomFile = new BinaryReader(File.OpenRead(fileName)); 25 26 //跳过128字节导言部分 27 dicomFile.BaseStream.Seek(128, SeekOrigin.Begin); 28 29 if (new string(dicomFile.ReadChars(4)) != "DICM") 30 { 31 MessageBox.Show("没有dicom标识头,文件格式错误"); 32 return; 33 } 34 35 36 tagRead(); 37 38 IDictionaryEnumerator enor = tags.GetEnumerator(); 39 while (enor.MoveNext()) 40 { 41 if (enor.Key.ToString().Length > 9) 42 { 43 textBox1.Text += enor.Key.ToString() + "rn"; 44 textBox1.Text += enor.Value.ToString().Replace('0', ' '); 45 } 46 else 47 textBox1.Text += enor.Key.ToString() + enor.Value.ToString().Replace('0', ' ') + "rn"; 48 } 49 dicomFile.Close(); 50 } 51 public DicomHandler(string _filename) 52 { 53 fileName = _filename; 54 } 55 56 public void saveAs(string filename) 57 { 58 switch (filename.Substring(filename.LastIndexOf('.'))) 59 { 60 case ".jpg": 61 gdiImg.Save(filename, System.Drawing.Imaging.ImageFormat.Jpeg); 62 break; 63 case ".bmp": 64 gdiImg.Save(filename, System.Drawing.Imaging.ImageFormat.Bmp); 65 break; 66 case ".png": 67 gdiImg.Save(filename, System.Drawing.Imaging.ImageFormat.Png); 68 break; 69 default: 70 break; 71 } 72 } 73 public bool getImg( )//获取图像 在图像数据偏移量已经确定的情况下 74 { 75 if (fileName == string.Empty) 76 return false; 77 78 int dataLen, validLen;//数据长度 有效位 79 int imgNum;//帧数 80 81 rows = int.Parse(tags["0028,0010"].Substring(5)); 82 cols = int.Parse(tags["0028,0011"].Substring(5)); 83 84 colors = int.Parse(tags["0028,0002"].Substring(5)); 85 dataLen = int.Parse(tags["0028,0100"].Substring(5)); 86 validLen = int.Parse(tags["0028,0101"].Substring(5)); 87 88 gdiImg = new Bitmap(cols, rows); 89 90 BinaryReader dicomFile = new BinaryReader(File.OpenRead(fileName)); 91 92 dicomFile.BaseStream.Seek(pixDataOffset, SeekOrigin.Begin); 93 94 long reads = 0; 95 for (int i = 0; i < gdiImg.Height; i++) 96 { 97 for (int j = 0; j < gdiImg.Width; j++) 98 { 99 if (reads >= pixDatalen) 100 break; 101 byte[] pixData = dicomFile.ReadBytes(dataLen / 8 * colors); 102 reads += pixData.Length; 103 104 Color c = Color.Empty; 105 if (colors == 1) 106 { 107 int grayGDI; 108 109 double gray = BitConverter.ToUInt16(pixData, 0); 110 //调窗代码,就这么几句而已 111 //1先确定窗口范围 2映射到8位灰度 112 int grayStart = (windowCenter - windowWith / 2); 113 int grayEnd = (windowCenter + windowWith / 2); 114 115 if (gray < grayStart) 116 grayGDI = 0; 117 else if (gray > grayEnd) 118 grayGDI = 255; 119 else 120 { 121 grayGDI = (int)((gray - grayStart) * 255 / windowWith); 122 } 123 124 if (grayGDI > 255) 125 grayGDI = 255; 126 else if (grayGDI < 0) 127 grayGDI = 0; 128 c = Color.FromArgb(grayGDI, grayGDI, grayGDI); 129 } 130 else if (colors == 3) 131 { 132 c = Color.FromArgb(pixData[0], pixData[1], pixData[2]); 133 } 134 135 gdiImg.SetPixel(j, i, c); 136 } 137 } 138 139 dicomFile.Close(); 140 return true; 141 } 142 void tagRead()//不断读取所有tag 及其值 直到碰到图像数据 (7fe0 0010 ) 143 { 144 bool enDir = false; 145 int leve = 0; 146 StringBuilder folderData = new StringBuilder();//该死的文件夹标签 147 string folderTag = ""; 148 while (dicomFile.BaseStream.Position + 6 < dicomFile.BaseStream.Length) 149 { 150 //读取tag 151 string tag = dicomFile.ReadUInt16().ToString("x4") + "," + 152 dicomFile.ReadUInt16().ToString("x4"); 153 154 string VR = string.Empty; 155 UInt32 Len = 0; 156 //读取VR跟Len 157 //对OB OW SQ 要做特殊处理 先置两个字节0 然后4字节值长度 158 //------------------------------------------------------这些都是在读取VR一步被阻断的情况 159 if (tag.Substring(0, 4) == "0002")//文件头 特殊情况 160 { 161 VR = new string(dicomFile.ReadChars(2)); 162 163 if (VR == "OB" || VR == "OW" || VR == "SQ" || VR == "OF" || VR == "UT" || VR == "UN") 164 { 165 dicomFile.BaseStream.Seek(2, SeekOrigin.Current); 166 Len = dicomFile.ReadUInt32(); 167 } 168 else 169 Len = dicomFile.ReadUInt16(); 170 } 171 else if (tag == "fffe,e000" || tag == "fffe,e00d" || tag == "fffe,e0dd")//文件夹标签 172 { 173 VR = "**"; 174 Len = dicomFile.ReadUInt32(); 175 } 176 else if (isExplicitVR == true)//有无VR的情况 177 { 178 VR = new string(dicomFile.ReadChars(2)); 179 180 if (VR == "OB" || VR == "OW" || VR == "SQ" || VR == "OF" || VR == "UT" || VR == "UN") 181 { 182 dicomFile.BaseStream.Seek(2, SeekOrigin.Current); 183 Len = dicomFile.ReadUInt32(); 184 } 185 else 186 Len = dicomFile.ReadUInt16(); 187 } 188 else if (isExplicitVR == false) 189 { 190 VR = getVR(tag);//无显示VR时根据tag一个一个去找 真烦啊。 191 Len = dicomFile.ReadUInt32(); 192 } 193 //判断是否应该读取VF 以何种方式读取VF 194 //-------------------------------------------------------这些都是在读取VF一步被阻断的情况 195 byte[] VF = { 0x00 }; 196 197 if (tag == "7fe0,0010")//图像数据开始了 198 { 199 pixDatalen = Len; 200 pixDataOffset = dicomFile.BaseStream.Position; 201 dicomFile.BaseStream.Seek(Len, SeekOrigin.Current); 202 VR = "UL"; 203 VF = BitConverter.GetBytes(Len); 204 } 205 else if ((VR == "SQ" && Len == UInt32.MaxValue) || (tag == "fffe,e000" && Len == UInt32.MaxValue))//靠 遇到文件夹开始标签了 206 { 207 if (enDir == false) 208 { 209 enDir = true; 210 folderData.Remove(0, folderData.Length); 211 folderTag = tag; 212 } 213 else 214 { 215 leve++;//VF不赋值 216 } 217 } 218 else if ((tag == "fffe,e00d" && Len == UInt32.MinValue) || (tag == "fffe,e0dd" && Len == UInt32.MinValue))//文件夹结束标签 219 { 220 if (enDir == true) 221 { 222 enDir = false; 223 } 224 else 225 { 226 leve--; 227 } 228 } 229 else 230 VF = dicomFile.ReadBytes((int)Len); 231 232 string VFStr; 233 234 VFStr = getVF(VR, VF); 235 236 //----------------------------------------------------------------针对特殊的tag的值的处理 237 //特别针对文件头信息处理 238 if (tag == "0002,0000") 239 { 240 fileHeadLen = Len; 241 fileHeadOffset = dicomFile.BaseStream.Position; 242 } 243 else if (tag == "0002,0010")//传输语法 关系到后面的数据读取 244 { 245 switch (VFStr) 246 { 247 case "1.2.840.10008.1.2.10"://显示little 248 isLitteEndian = true; 249 isExplicitVR = true; 250 break; 251 case "1.2.840.10008.1.2.20"://显示big 252 isLitteEndian = false; 253 isExplicitVR = true; 254 break; 255 case "1.2.840.10008.1.20"://隐式little 256 isLitteEndian = true; 257 isExplicitVR = false; 258 break; 259 default: 260 break; 261 } 262 } 263 for (int i = 1; i <= leve; i++) 264 tag = "--" + tag; 265 //------------------------------------数据搜集代码 266 if ((VR == "SQ" && Len == UInt32.MaxValue) || (tag == "fffe,e000" && Len == UInt32.MaxValue) || leve > 0)//文件夹标签代码 267 { 268 folderData.AppendLine(tag + "(" + VR + "):" + VFStr); 269 } 270 else if (((tag == "fffe,e00d" && Len == UInt32.MinValue) || (tag == "fffe,e0dd" && Len == UInt32.MinValue)) && leve == 0)//文件夹结束标签 271 { 272 folderData.AppendLine(tag + "(" + VR + "):" + VFStr); 273 tags.Add(folderTag + "SQ", folderData.ToString()); 274 } 275 else 276 tags.Add(tag, "(" + VR + "):" + VFStr); 277 } 278 } 279 } 复制代码 好了收工。 测试下成果 复制代码 1 if (openFileDialog1.ShowDialog() != DialogResult.OK) 2 return; 3 4 string fileName = openFileDialog1.FileName; 5 6 handler = new DicomHandler(fileName); 7 8 handler.readAndShow(textBox1); 9 10 this.Text = "DicomViewer-" + openFileDialog1.FileName; 11 12 13 backgroundWorker1.RunWorkerAsync(); 复制代码 这里处理gdi位图的时候直接用的setPix 处理速度比较慢所以用了backgroundWorker,实际应用中请使用内存缓冲跟指针的方式 否则效率低了是得不到客户的认可的哦,gdi位图操作可使用lockBits加指针的方式 ,12位的灰度像素数据可以第一次读取后缓存到内存中 以方便后面调窗的快速读取 优化这点代码也不难哈 对指针什么的熟点就行了,前几章都有。 这是ezDicom 经过公认测试的软件 我们来跟他对比一下,打开 调窗测试,我们注意到两个东西 在没有窗宽窗位时 默认窗宽是2047+1即2048 窗位是2048/2即1024 直观的感受是调窗宽像在调图像对比度 ,调窗位像在调图像亮度。 窗宽为255的时候图像是最瑞丽的 因为255其实就是8位图像的默认窗宽。 注意窗位那里有小小区别,ez窗位显示的是根据1024那里为0开始偏移 而我的程序是根据窗宽中间值没有偏移 没有偏移的情况稍微符合逻辑点吧。 但是可以看到原理是一样的 结果是一样的。

爵霸 2019-12-02 02:13:35 0 浏览量 回答数 0

回答

Go 的优势在于能够将简单的和经过验证的想法结合起来,同时避免了其他语言中出现的许多问题。本文概述了 Go 背后的一些设计原则和工程智慧,作者认为,Go 语言具备的所有这些优点,将共同推动其成为接替 Java 并主导下一代大型软件开发平台的最有力的编程语言候选。很多优秀的编程语言只是在个别领域比较强大,如果将所有因素都纳入考虑,没有其他语言能够像 Go 语言一样“全面开花”,在大型软件工程方面,尤为如此。 基于现实经验 Go 是由经验丰富的软件行业老手一手创建的,长期以来,他们对现有语言的各种缺点有过切身体会的痛苦经历。几十年前,Rob Pike 和 Ken Thompson 在 Unix、C 和 Unicode 的发明中起到了重要作用。Robert Griensemer 在为 JavaScript 和 Java 开发 V8 和 HotSpot 虚拟机之后,在编译器和垃圾收集方面拥有数十年的经验。有太多次,他们不得不等待 Google 规模的 C++/Java 代码库进行编译。于是,他们开始着手创建新的编程语言,将他们半个世纪以来的编写代码所学到的一切经验包含进去。 专注于大型工程 小型工程项目几乎可以用任何编程语言来成功构建。当成千上万的开发人员在数十年的持续时间压力下,在包含数千万行代码的大型代码库上进行协作时,就会发生真正令人痛苦的问题。这样会导致一些问题,如下: 较长的编译时间导致中断开发。代码库由几个人 / 团队 / 部门 / 公司所拥有,混合了不同的编程风格。公司雇佣了数千名工程师、架构师、测试人员、运营专家、审计员、实习生等,他们需要了解代码库,但也具备广泛的编码经验。依赖于许多外部库或运行时,其中一些不再以原始形式存在。在代码库的生命周期中,每行代码平均被重写 10 次,被弄得千疮百痍,而且还会发生技术偏差。文档不完整。 Go 注重减轻这些大型工程的难题,有时会以使小型工程变得更麻烦为代价,例如,代码中到处都需要几行额外的代码行。 注重可维护性 Go 强调尽可能多地将工作转给自动化的代码维护工具中。Go 工具链提供了最常用的功能,如格式化代码和导入、查找符号的定义和用法、简单的重构以及代码异味的识别。由于标准化的代码格式和单一的惯用方式,机器生成的代码更改看起来非常接近 Go 中人为生成的更改并使用类似的模式,从而允许人机之间更加无缝地协作。 保持简单明了 初级程序员为简单的问题创建简单的解决方案。高级程序员为复杂的问题创建复杂的解决方案。伟大的程序员找到复杂问题的简单解决方案。 ——Charles Connell 让很多人惊讶的一点是,Go 居然不包含他们喜欢的其他语言的概念。Go 确实是一种非常小巧而简单的语言,只包含正交和经过验证的概念的最小选择。这鼓励开发人员用最少的认知开销来编写尽可能简单的代码,以便许多其他人可以理解并使用它。 使事情清晰明了 良好的代码总是显而易见的,避免了那些小聪明、难以理解的语言特性、诡异的控制流和兜圈子。 许多语言都致力提高编写代码的效率。然而,在其生命周期中,人们阅读代码的时间却远远超过最初编写代码所需的时间(100 倍)。例如,审查、理解、调试、更改、重构或重用代码。在查看代码时,往往只能看到并理解其中的一小部分,通常不会有完整的代码库概述。为了解释这一点,Go 将所有内容都明确出来。 错误处理就是一个例子。让异常在各个点中断代码并在调用链上冒泡会更容易。Go 需要手动处理和返回每个错误。这使得它可以准确地显示代码可以被中断的位置以及如何处理或包装错误。总的来说,这使得错误处理编写起来更加繁琐,但是也更容易理解。 简单易学 Go 是如此的小巧而简单,以至于人们可以在短短几天内就能研究通整个语言及其基本概念。根据我们的经验,培训用不了一个星期(相比于掌握其他语言需要几个月),初学者就能够理解 Go 专家编写的代码,并为之做出贡献。为了方便吸引更多的用户,Go 网站提供了所有必要的教程和深入研究的文章。这些教程在浏览器中运行,允许人们在将 Go 安装到本地计算机上之前就能够学习和使用 Go。 解决之道 Go 强调的是团队之间的合作,而不是个人的自我表达。 在 Go(和 Python)中,所有的语言特性都是相互正交和互补的,通常有一种方法可以做一些事情。如果你想让 10 个 Python 或 Go 程序员来解决同一个问题,你将会得到 10 个相对类似的解决方案。不同的程序员在彼此的代码库中感觉更自在。在查看其他人的代码时,国骂会更少,而且人们的工作可以更好地融合在一起,从而形成了一致的整体,人人都为之感到自豪,并乐于工作。这还避免了大型工程的问题,如: 开发人员认为良好的工作代码很“混乱”,并要求在开始工作之前进行重写,因为他们的思维方式与原作者不同。 不同的团队成员使用不同的语言子集来编写相同代码库的部分内容。 ![image.png](https://ucc.alicdn.com/pic/developer-ecology/e64418f1455d46aaacfdd03fa949f16d.png) 简单、内置的并发性 Go 专为现代多核硬件设计。 目前使用的大多数编程语言(Java、JavaScript、Python、Ruby、C、C++)都是 20 世纪 80 年代到 21 世纪初设计的,当时大多数 CPU 只有一个计算内核。这就是为什么它们本质上是单线程的,并将并行化视为边缘情况的马后炮。通过现成和同步点之类的附加组件来实现,而这些附加组件既麻烦又难以正确使用。第三方库虽然提供了更简单的并发形式,如 Actor 模型,但是总有多个可用选项,结果导致了语言生态系统的碎片化。今天的硬件拥有越来越多的计算内核,软件必须并行化才能高效运行。Go 是在多核处理器时代编写的,并且在语言中内置了简单、高级的 CSP 风格并发性。 面向计算的语言原语 就深层而言,计算机系统接收数据,对其进行处理(通常要经过几个步骤),然后输出结果数据。例如,Web 服务器从客户端接收 HTTP 请求,并将其转换为一系列数据库或后端调用。一旦这些调用返回,它就将接收到的数据转换成 HTML 或 JSON 并将其输出给调用者。Go 的内置语言原语直接支持这种范例: 结构表示数据 读和写代表流式 IO 函数过程数据 goroutines 提供(几乎无限的)并发性 在并行处理步骤之间传输管道数据 因为所有的计算原语都是由语言以直接形式提供的,因此 Go 源代码更直接地表达了服务器执行的操作。 OO — 好的部分 更改基类中的某些内容的副作用 面向对象非常有用。过去几十年来,面向对象的使用富有成效,并让我们了解了它的哪些部分比其他部分能够更好地扩展。Go 在面向对象方面采用了一种全新的方法,并记住了这些知识。它保留了好的部分,如封装、消息传递等。Go 还避免了继承,因为它现在被认为是有害的,并为组合提供了一流的支持。 现代标准库 目前使用的许多编程语言(Java、JavaScript、Python、Ruby)都是在互联网成为当今无处不在的计算平台之前设计的。因此,这些语言的标准库只提供了相对通用的网络支持,而这些网络并没有针对现代互联网进行优化。Go 是十年前创建的,当时互联网已全面发展。Go 的标准库允许在没有第三方库的情况下创建更复杂的网络服务。这就避免了第三方库的常见问题: 碎片化:总是有多个选项实现相同的功能。 膨胀:库常常实现的不仅仅是它们的用途。 依赖地狱:库通常依赖于特定版本的其他库。 未知质量:第三方代码的质量和安全性可能存在问题。 未知支持:第三方库的开发可能随时停止支持。 意外更改:第三方库通常不像标准库那样严格地进行版本控制。 关于这方面更多的信息请参考 Russ Cox 提供的资料 标准化格式 Gofmt 的风格没有人会去喜欢,但人人都会喜欢 gofmt。 ——Rob Pike Gofmt 是一种以标准化方式来格式化 Go 代码的程序。它不是最漂亮的格式化方式,但却是最简单、最不令人生厌的格式化方式。标准化的源代码格式具有惊人的积极影响: 集中讨论重要主题: 它消除了围绕制表符和空格、缩进深度、行长、空行、花括号的位置等一系列争论。 开发人员在彼此的代码库中感觉很自在, 因为其他代码看起来很像他们编写的代码。每个人都喜欢自由地按照自己喜欢的方式进行格式化代码,但如果其他人按照自己喜欢的方式格式化了代码,这么做很招人烦。 自动代码更改并不会打乱手写代码的格式,例如引入了意外的空白更改。 许多其他语言社区现在正在开发类似 gofmt 的东西。当作为第三方解决方案构建时,通常会有几个相互竞争的格式标准。例如,JavaScript 提供了 Prettier 和 StandardJS。这两者都可以用,也可以只使用其中的一个。但许多 JS 项目并没有采用它们,因为这是一个额外的决策。Go 的格式化程序内置于该语言的标准工具链中,因此只有一个标准,每个人都在使用它。 快速编译 ![image.png](https://ucc.alicdn.com/pic/developer-ecology/8a76f3f07f484266af42781d9e7b8692.png) 对于大型代码库来说,它们长时间的编译是促使 Go 诞生的原因。Google 主要使用的是 C++ 和 Java,与 Haskell、Scala 或 Rust 等更复杂的语言相比,它们的编译速度相对较快。尽管如此,当编译大型代码库时,即使是少量的缓慢也会加剧编译的延迟,从而激怒开发人员,并干扰流程。Go 的设计初衷是为了提高编译效率,因此它的编译器速度非常快,几乎没有编译延迟的现象。这给 Go 开发人员提供了与脚本类语言类似的即时反馈,还有静态类型检查的额外好处。 交叉编译 由于语言运行时非常简单,因此它被移植到许多平台,如 macOS、Linux、Windows、BSD、ARM 等。Go 可以开箱即用地为所有这些平台编译二进制文件。这使得从一台机器进行部署变得很容易。 快速执行 Go 的运行速度接近于 C。与 JITed 语言(Java、JavaScript、Python 等)不同,Go 二进制文件不需要启动或预热的时间,因为它们是作为编译和完全优化的本地代码的形式发布的。Go 的垃圾收集器仅引入微秒量级的可忽略的停顿。除了快速的单核性能外,Go 还可以轻松利用所有的 CPU 内核。 内存占用小 像 JVM、Python 或 Node 这样的运行时不仅仅在运行时加载程序代码,每次运行程序时,它们还会加载大型且高度复杂的基础架构,以进行编译和优化程序。如此一来,它们的启动时间就变慢了,并且还占用了大量内存(数百兆字节)。而 Go 进程的开销更小,因为它们已经完全编译和优化,只需运行即可。Go 还以非常节省内存的方式来存储数据。在内存有限且昂贵的云环境中,以及在开发过程中,这一点非常重要。我们希望在一台机器上能够快速启动整个堆栈,同时将内存留给其他软件。 部署规模小 Go 的二进制文件大小非常简洁。Go 应用程序的 Docker 镜像通常比用 Java 或 Node 编写的等效镜像要小 10 倍,这是因为它无需包含编译器、JIT,以及更少的运行时基础架构的原因。这些特点,在部署大型应用程序时很重要。想象一下,如果要将一个简单的应用程序部署到 100 个生产服务器上会怎么样?如果使用 Node/JVM 时,我们的 Docker 注册表就必须提供 100 个 docker 镜像,每个镜像 200MB,那么一共就需要 20GB。要完成这些部署就需要一些时间。想象一下,如果我们想每天部署 100 次的话,如果使用 Go 服务,那么 Docker 注册表只需提供 10 个 docker 镜像,每个镜像只有 20MB,共只需 2GB 即可。大型 Go 应用程序可以更快、更频繁地部署,从而使得重要更新能够更快地部署到生产环境中。 独立部署 Go 应用程序部署为一个包含所有依赖项的单个可执行文件,并无需安装特定版本的 JVM、Node 或 Python 运行时;也不必将库下载到生产服务器上,更无须对运行 Go 二进制文件的机器进行任何更改。甚至也不需要讲 Go 二进制文件包装到 Docker 来共享他们。你需要做的是,只是将 Go 二进制文件放到服务器上,它就会在那里运行,而不用关心服务器运行的是什么。前面所提到的那些,唯一的例外是使用net和os/user包时针对对glibc的动态链接。 供应依赖关系 Go 有意识避免使用第三方库的中央存储库。Go 应用程序直接链接到相应的 Git 存储库,并将所有相关代码下载(供应)到自己的代码库中。这样做有很多好处: 在使用第三方代码之前,我们可以对其进行审查、分析和测试。该代码就和我们自己的代码一样,是我们应用程序的一部分,应该遵循相同的质量、安全性和可靠性标准。 无需永久访问存储依赖项的各个位置。从任何地方(包括私有 Git repos)获取第三方库,你就能永久拥有它们。 经过验收后,编译代码库无需进一步下载依赖项。 若互联网某处的代码存储库突然提供不同的代码,这也并不足为奇。 即使软件包存储库速度变慢,或托管包不复存在,部署也不会因此中断。 兼容性保证 Go 团队承诺现有的程序将会继续适用于新一代语言。这使得将大型项目升级到最新版本的编译器会非常容易,并且可从它们带来的许多性能和安全性改进中获益。同时,由于 Go 二进制文件包含了它们需要的所有依赖项,因此可以在同一服务器上并行运行使用不同版本的 Go 编译器编译的二进制文件,而无需进行复杂的多个版本的运行时设置或虚拟化。 文档 在大型工程中,文档对于使软件可访问性和可维护性非常重要。与其他特性类似,Go 中的文档简单实用: 由于它是嵌入到源代码中的,因此两者可以同时维护。 它不需要特殊的语法,文档只是普通的源代码注释。 可运行单元测试通常是最好的文档形式。因此 Go 要求将它们嵌入到文档中。 所有的文档实用程序都内置在工具链中,因此每个人都使用它们。 Go linter 需要导出元素的文档,以防止“文档债务”的积累。 商业支持的开源 当商业实体在开放式环境下开发时,那么一些最流行的、经过彻底设计的软件就会出现。这种设置结合了商业软件开发的优势——一致性和精细化,使系统更为健壮、可靠、高效,并具有开放式开发的优势,如来自许多行业的广泛支持,多个大型实体和许多用户的支持,以及即使商业支持停止的长期支持。Go 就是这样发展起来的。 缺点 当然,Go 也并非完美无缺,每种技术选择都是有利有弊。在决定选择 Go 之前,有几个方面需要进行考虑考虑。 未成熟 虽然 Go 的标准库在支持许多新概念(如 HTTP 2 Server push 等)方面处于行业领先地位,但与 JVM 生态系统中的第三方库相比,用于外部 API 的第三方 Go 库可能不那么成熟。 即将到来的改进 由于清楚几乎不可能改变现有的语言元素,Go 团队非常谨慎,只在新特性完全开发出来后才添加新特性。在经历了 10 年的有意稳定阶段之后,Go 团队正在谋划对语言进行一系列更大的改进,作为 Go 2.0 之旅的一部分。 无硬实时 虽然 Go 的垃圾收集器只引入了非常短暂的停顿,但支持硬实时需要没有垃圾收集的技术,例如 Rust。 结语 本文详细介绍了 Go 语言的一些优秀的设计准则,虽然有的准则的好处平常看起来没有那么明显。但当代码库和团队规模增长几个数量级时,这些准则可能会使大型工程项目免于许多痛苦。总的来说,正是这些设计准则让 Go 语言成为了除 Java 之外的编程语言里,用于大型软件开发项目的绝佳选择。

有只黑白猫 2020-01-07 14:11:38 0 浏览量 回答数 0

问题

Nginx性能为什么如此吊

小柒2012 2019-12-01 21:20:47 15038 浏览量 回答数 3
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站