IoTserver
源代码开源在gitee上 : IoT netty java gitee server sample
c++ libuv 的IoT tcp server IoT c++ libuv gitee server sample c++的代码也给了一个示例,为了方便调试使用了vs。为了调试方便,java下面有一个nodejs 的测试文件: nodejs 客户端代码
IoTserver的使用最好就是使用固定协议,一种协议写一种接收,这里使用几种语言去接收,如java,c++,nodejs,技巧很多,尤其是使用java的时候,netty的接收协议方式非常方便,下面是主程序message中的定义:
public class Message {
private final Charset charset = Charset.forName("utf-8");
private byte magicType;
private long deviceid; //设备
private byte cmd;//命令
private byte length;
private String body;
public Message(){
}
public Message(byte magicType,long deviceid, byte cmd, byte[] data) {
this.magicType = magicType; //0x69
this.deviceid = deviceid;
this.cmd =cmd;
this.length = (byte)data.length;
this.body = new String(data, charset);
}
public Message(byte magicType, long deviceid, byte cmd, String body) {
this.magicType = magicType;
this.cmd = cmd;
this.deviceid = deviceid;
this.length = (byte)body.getBytes(charset).length;
this.body = body;
}
public String GetBody()
{
return this.body;
}
public byte GetCmd()
{
return this.cmd;
}
}
非常清晰地定义,协议由类型,定义,设备类型,命令字,数据内容长度,最后是内容。下面是主要代码,server启动在多个端口上。
package zhongda.iot.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import redis.clients.jedis.*;
/**
* Netty实现的tcp iotserver 程序
* @author qianbo
*/
public class TcpServer
{
/*端口号*/
static final int PORT1 = 9002;
static final int PORT2 = 9003;
public static void main(String[] args)
{
JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "192.168.1.222", 6379);
Publisher publish = new Publisher(jedisPool);
publish.start();
//publish.join();
EventLoopGroup bossGroup = null;
EventLoopGroup workerGroup = null;
ServerBootstrap b = null;
System.out.println("the server start at 9002 9003");
try{
//1:第一个线程组是用于接收Client连接的
bossGroup = new NioEventLoopGroup();
//2:第二个线程组是用于实际的业务处理操作的
workerGroup = new NioEventLoopGroup();
//3:创建一个启动NIO服务的辅助启动类ServerBootstrap 就是对我们的Server进行一系列的配置
b = new ServerBootstrap();
//4:绑定两个线程组
b.group(bossGroup, workerGroup)
//5:需要指定使用NioServerSocketChannel这种类型的通道
.channel(NioServerSocketChannel.class)//(3) 服务端 -->NioServerSocketChannel
//6:一定要使用childHandler 去绑定具体的事件处理器
.childHandler(new ChannelInitializer() //(4) childHandler
{
@Override
protected void initChannel(SocketChannel sc) throws Exception
{
//7:将自定义的serverHandler加入到管道中去(多个)
ChannelPipeline p = sc.pipeline();
p.addLast(new MessageDecoder(255, 6, 1));
//p.addLast(new MessageEncoder());
p.addLast(new ServerHandler());//handler中实现真正的业务逻辑
}
})
//8:设置TCP连接的缓冲区
.option(ChannelOption.SO_BACKLOG, 200)//(5)
//设置发送缓冲大小 32K发送缓冲
// .option(ChannelOption.SO_SNDBUF, 32*1024)
//设置接收缓冲大小
// .option(ChannelOption.SO_RCVBUF, 32*1024)
//9:保持连接
.childOption(ChannelOption.SO_KEEPALIVE, true);//(6)
//10:绑定指定的端口 进行监听
ChannelFuture cf2= b.bind(PORT1).sync(); // (7)
ChannelFuture cf3= b.bind(PORT2).sync(); // (7) 绑定多个端口
cf2.channel().closeFuture().sync(); //异步等待关闭
cf3.channel().closeFuture().sync(); //异步等待关闭
}catch(Exception e){
e.printStackTrace();
}finally{
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
}