在进行服务器处理的过程中,需要保证数据的正确处理,那么最重要的就是使用不同的数据处理模式进行运算。
在整个过程中,可能很多人对服务器的知识并不了解,那么应该如何进行Java开发服务器的线程处理呢,关于线程处理有哪些知识?下面运城北大青鸟为大家介绍关键服务器线程处理的简单知识。
1、BIO线程模型在JDK1.4中引入JavaNIO之前,所有基于Java的Socket通信都使用了同步阻塞模式(BIO)。
这种请求-响应通信模型简化了上层的应用程序开发上,但在具有性能和可靠性的情况下,存在一个巨大的瓶颈。
在一段时间里面,大型应用程序服务器主要是用C或C++开发的,因为它们可以直接使用操作系统提供的异步I/O或AIO功能。
当流量增加且响应时间延迟增加时,JavaBIO开发的服务器软件只能通过硬件的不断扩展来满足并发性和低延迟的情况,这极大地增加了企业的成本和群集大小。
系统的不断扩展,系统的可维护性也面临着巨大的挑战,只能通过购买性能更高的硬件服务器来解决问题,这将导致恶性循环的产生。
2、异步非阻塞线程模型从JDK1.0到JDK1.3,Java的I/O类库非常原始。
UNIX网络编程中的许多概念或接口未反映在I/O类库中,例如Pipe、Channel、Buffer和Selector等。
在发布JDK1.4的时候,NIO正式发布JDK作为JSR-51。
并且它还添加了一个java.nio包,为异步I/O开发提供了许多API和库。
3、RPC性能三原则影响RPC的性能主要有三大元素,其中主要为I/O模型、协议及线程。
I/O模型:使用什么样的通道传递给另一方,BIO,NIO或AIO发送数据,IO模型在很大程度上能够决定框架的性能。
协议:应该使用什么样的通信协议,Rest+JSON或基于TCP的专用二进制协议。
参加电脑培训的过程中发现,协议的选择不同,性能模型也不同。
内部专用二进制协议的性能通常可以比公共协议更好地设计。
线程:如何读取数据报?在执行读取后的编解码器的哪个线程中,如何分发编码消息,通信线程模型是不同的,并且对性能的影响也非常大。
通常情况下是不可以突破的,端口有限制.单独对外提供请求的服务不用考虑端口数量问题,监听某一个端口即可.但是向提供代理服务器,就不得不考虑端口数量受限问题了.当前的1M并发连接测试,也需要在客户端突破6万可用端口的限制.端口为16进制,那么2的16次方值为65536,在linux系统里面,1024以下端口都是超级管理员用户(如root)才可以使用,普通用户只能使用大于1024的端口值.
服务器是只监听一个端口,所有的客户端连接,都是连接到服务器的同一个端口上的。也就是说服务器只是用了一个端口。就比如Http服务器。默认只用了80端口。
nio 在linux上使用的是epoll ,epoll支持在一个进程中打开的FD是操作系统最大文件句柄数,而不是你所说的16位short表示的文件句柄。 而 select模型 单进程打开的FD是受限的 select模型默认FD是1024 。操作系统最大文件句柄数跟内存有关,1GB内存的机器上,大概是10万个句柄左右。
客户端发送:len+type+command+userid+":"+content+""
例: 32 001 001 10001 : helloworld!
其中32为len为整数 001为type为short,001为command为short,
10001为userid为八字节long, content为变长字符串。“;”和":"分别一字节。
type: 判断type可知道客户端的请求类型,如是聊天还是游戏
command: 判断command类型可知道客户端的请求具体命令,如聊天,表情等
所以,整个数据包头长度为: 4+2+2+8+1+content长+1
content的长度可以算出来;
byte[] stringBytes=content.getBytes()
len= StringBytes.length()
数据包的头部长度为: int headLen=4+2+2+8+1
数据包中数据体的长度为: int datalen= len+1
整个数据包的长度为: headLen+datalen
客户端发送时压成 :
byte[] toSend=new byte[headLen+datalen]
分别用System.arrayCopy命令将内容考入soSend中
copy datalen 到toSend的前两个字节
copy type 到toSend 占两个字节
copy command
copy userid
copy ":"
copy content.getBytes()
copy ""
//行了, tosend中己经有压缩编码好的消息了
outputStream.write(toSend)//发送到服务端
outputStream.flash()//别忘了flash
////////////// 客户端发送完毕
服务端收取
byte[] datas=new byte[len]
inputStream.read(datas)
现在datas中己包含客户端发过来的byte[]
//////////// 下面开始解析
1。从 datas中拿两个字节出来得到len
2。再拿两个字节出来,得到 type
3。得到command
4。得到userid
5。拿一个字节 得到:或者;,如果没有:只有证明客户端就发了个空消息
6。根据len的长度拿len个字节,得到String str=new String(指定长度拿来的byte[],指定编码)
7。 解析str,丢弃; 细分str的具体内容
//////////// 解析结束
另外一种办法,很偷懒,效率低一丁点:
全部用String 不用计算长度,最简单, 各数据项之间用","分割
String toString="len,type,command,userid: targetUserid,chatContent"
这种形式最简单,效率会低点,但你初学可以直接用,以后再改进。
具体如下:
StringBuffer buffer =new StringBuffer()
buffer.append(len)
buffer.append(",")
buffer.append(type)
buffer.append(",")
buffer.append(command)
buffer.append(,)
buffer.append(userid)
buffer.append(":")
buffer.append(对方帐号)
buffer.append(",")
buffer.append(内容)
buffer.append("")
String result=buffer.toString()
outputstream.write(result.getBytes("utf-8"))
flash()
///服务端收到以后,是纯字符串
先按""split得到数个消息包
再按":"得到消息体得消息头
再按","解析具体内容
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)