This commit is contained in:
yidao620
2018-02-26 19:05:53 +08:00
commit 4d57c022c6
534 changed files with 96924 additions and 0 deletions

View File

@ -0,0 +1,15 @@
package com.enzhico.jwt;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 测试密码加密
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {
}

View File

@ -0,0 +1,74 @@
package com.enzhico.jwt;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPListParseEngine;
import org.apache.commons.net.ftp.FTPReply;
import org.junit.Test;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
/**
* FTPClientTest
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/24
*/
public class FTPClientTest {
@Test
public void connect() throws Exception {
FTPClient f = new FTPClient();
String server = "119.29.12.177";
f.setControlEncoding("UTF-8");
f.connect(server);
boolean login = f.login("ftpuser1", "123456");
System.out.println("login = " + login);
f.setDefaultPort(11024);
System.out.println("reply = " + f.getReplyString());
int replyCode = f.getReplyCode();
System.out.println("replyCode = " + replyCode);
if (!FTPReply.isPositiveCompletion(replyCode)) {
f.disconnect();
System.err.println("FTP server refused connection.");
}
f.enterLocalPassiveMode();
//f.enterLocalActiveMode();
FTPListParseEngine engine = f.initiateListParsing("");
while (engine.hasNext()) {
FTPFile[] files = engine.getNext(25); // "page size" you want
System.out.println("当前目录的文件数量 = " + files.length);
for (FTPFile ftpFile : files) {
System.out.println("文件名:" + ftpFile.getName());
}
//do whatever you want with these files, display them, etc.
//expensive FTPFile objects not created until needed.
}
f.disconnect();
}
@Test
public void upload() throws Exception {
FTPClient ftpClient = new FTPClient();
String server = "119.29.12.177";
ftpClient.connect(server);
ftpClient.login("ftpuser1", "123456");
InputStream sourceStream = null;
try {
sourceStream = new FileInputStream(new File(""));
//设置上传目录
ftpClient.changeWorkingDirectory("");
ftpClient.setBufferSize(1024);
ftpClient.setControlEncoding("UTF-8");
//设置文件类型(二进制)
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.storeFile("hero.txt", sourceStream);
} finally {
sourceStream.close();
ftpClient.disconnect();
}
}
}

View File

@ -0,0 +1,47 @@
package com.enzhico.jwt;
import com.enzhico.jwt.api.model.VersionParam;
import com.enzhico.jwt.shiro.ShiroKit;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.Language;
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import org.junit.Test;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* SimpleTest
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/4
*/
public class SimpleTest {
@Test
public void testMd5() {
//盐(用户名+随机数)
String username = "admin";
String salt = ShiroKit.getRandomSalt(16);
//原密码
String password = "12345678";
String encodedPassword = ShiroKit.md5(password, username + salt);
System.out.println("这个是保存进数据库的密码:" + encodedPassword);
System.out.println("这个是保存进数据库的盐:" + salt);
}
@Test
public void testJackson() throws JsonProcessingException {
VersionParam req = new VersionParam();
String reqBody = new ObjectMapper().writeValueAsString(req);
System.out.println(reqBody);
}
}

View File

@ -0,0 +1,112 @@
package com.enzhico.jwt;
import io.github.swagger2markup.GroupBy;
import io.github.swagger2markup.Language;
import io.github.swagger2markup.Swagger2MarkupConfig;
import io.github.swagger2markup.Swagger2MarkupConverter;
import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder;
import io.github.swagger2markup.markup.builder.MarkupLanguage;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import java.io.BufferedWriter;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* Swagger2MarkupTest
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/26
*/
@AutoConfigureMockMvc
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Swagger2MarkupTest {
@Autowired
private MockMvc mockMvc;
private static final Logger LOG = LoggerFactory.getLogger(Swagger2MarkupTest.class);
/**
* 自动生成adoc文件
* @throws Exception e
*
* 执行完成后生成PDF文件方法
*
* 首先在`build/swagger.adoc`的顶部加入:
```
:toclevels: 3
:numbered:
```
注意有个空行分割目的是左边导航菜单是3级并且自动加序号。
为了美化显示,还要将`swagger.adoc`中全局替换一下,将
```
cols=".^2,.^3,.^9,.^4,.^2"
```
替换成:
```
cols=".^2,.^3,.^6,.^4,.^5"
```
然后在/resources目录下面执行
```
asciidoctor-pdf -r asciidoctor-pdf-cjk-kai_gen_gothic -a pdf-style=KaiGenGothicCN swagger/swagger.adoc
```
会在`swagger.adoc`的同级目录生成`swagger.pdf`文件。
*/
@Test
public void createSpringFoxSwaggerJson() throws Exception {
// String outputDir = System.getProperty("swaggerOutputDir"); // mvn test
MvcResult mvcResult = this.mockMvc.perform(get("/v2/api-docs")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andReturn();
MockHttpServletResponse response = mvcResult.getResponse();
String swaggerJson = response.getContentAsString();
// Files.createDirectories(Paths.get(outputDir));
// try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputDir, "swagger.json"), StandardCharsets.UTF_8)){
// writer.write(swaggerJson);
// }
LOG.info("--------------------swaggerJson create --------------------");
convertAsciidoc(swaggerJson);
LOG.info("--------------------swagon.json to asciiDoc finished --------------------");
}
/**
* 将swagger.yaml或swagger.json转换成漂亮的 AsciiDoc
* 访问http://localhost:9095/v2/api-docs
* 将页面结果保存为src/main/resources/swagger.json
*/
private void convertAsciidoc(String swaggerStr) {
// Path localSwaggerFile = Paths.get(System.getProperty("swaggerOutputDir"), "swagger.json");
Path outputFile = Paths.get(System.getProperty("asciiDocOutputDir"));
Swagger2MarkupConfig config = new Swagger2MarkupConfigBuilder()
.withMarkupLanguage(MarkupLanguage.ASCIIDOC)
.withOutputLanguage(Language.ZH)
.withPathsGroupedBy(GroupBy.TAGS)
.withGeneratedExamples()
.withoutInlineSchema()
.build();
Swagger2MarkupConverter converter = Swagger2MarkupConverter.from(swaggerStr)
.withConfig(config)
.build();
converter.toFile(outputFile);
}
}

View File

@ -0,0 +1,24 @@
package com.enzhico.jwt.common.util;
import org.junit.Test;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class CommonUtilTest {
@Test
public void isNewer() {
assertThat(CommonUtil.isNewer("1.2.1", "1.2.0"), is(true));
assertThat(CommonUtil.isNewer("1.2", "1.2.0"), is(false));
assertThat(CommonUtil.isNewer("2.1.9", "1.2.0"), is(true));
assertThat(CommonUtil.isNewer("adfa.1.3", "1.2.0"), is(false));
}
@Test
public void testTimestamp() {
// 1516072088813
// 1441594722
System.out.println(System.currentTimeMillis());
}
}

View File

@ -0,0 +1,87 @@
package com.enzhico.jwt.socket.client;
import com.enzhico.jwt.common.util.JsonConverter;
import com.enzhico.jwt.socket.model.LoginRequest;
import io.socket.client.Ack;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
* SocketClient
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/18
*/
public class SocketClient {
private static Socket socket;
private static final Logger logger = LoggerFactory.getLogger(SocketClient.class);
public static void main(String[] args) throws URISyntaxException {
IO.Options options = new IO.Options();
options.transports = new String[]{"websocket"};
options.reconnectionAttempts = 2;
options.reconnectionDelay = 1000; // 失败重连的时间间隔(ms)
options.timeout = 20000; // 连接超时时间(ms)
options.forceNew = true;
options.query = "username=test1&password=test1&appid=com.enzhico.apay2";
socket = IO.socket("http://localhost:9099/", options);
// socket = IO.socket("http://123.207.66.156:9099/", options);
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
// 客户端一旦连接成功,开始发起登录请求
LoginRequest message = new LoginRequest(12, "这是客户端消息体");
socket.emit("login", JsonConverter.objectToJSONObject(message), (Ack) args1 -> {
logger.info("回执消息=" + Arrays.stream(args1).map(Object::toString).collect(Collectors.joining(",")));
});
}
}).on("login", new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("接受到服务器房间广播的登录消息:" + Arrays.toString(args));
}
}).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("Socket.EVENT_CONNECT_ERROR");
socket.disconnect();
}
}).on(Socket.EVENT_CONNECT_TIMEOUT, new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("Socket.EVENT_CONNECT_TIMEOUT");
socket.disconnect();
}
}).on(Socket.EVENT_PING, new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("Socket.EVENT_PING");
}
}).on(Socket.EVENT_PONG, new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("Socket.EVENT_PONG");
}
}).on(Socket.EVENT_MESSAGE, new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("-----------接受到消息啦--------" + Arrays.toString(args));
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("客户端断开连接啦。。。");
// socket.disconnect();
}
});
socket.connect();
}
}

View File

@ -0,0 +1,85 @@
package com.enzhico.jwt.socket.client;
import com.enzhico.jwt.api.model.BaseResponse;
import com.enzhico.jwt.api.model.JoinBindResponse;
import com.enzhico.jwt.api.model.PosParam;
import com.enzhico.jwt.common.util.JsonConverter;
import io.socket.client.Ack;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URISyntaxException;
/**
* 这个客户端和SpringBoot服务器连接测试
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/18
*/
public class SocketClient2 {
private static Socket socket;
private static final Logger logger = LoggerFactory.getLogger(SocketClient2.class);
public static void main(String[] args) throws URISyntaxException {
IO.Options options = new IO.Options();
options.transports = new String[]{"websocket"};
options.reconnectionAttempts = 2;
options.reconnectionDelay = 1000; // 失败重连的时间间隔(ms)
options.timeout = 6000; // 连接超时时间(ms)
options.forceNew = true;
options.query = "token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhcHBpZCI6ImNvbS5lbnpoaWNvLmFkbWlucGF5IiwiaW1laSI6Ijg2NjAzMzAzMDkwNjAwMCIsImV4cCI6MTUxNjc5OTM5MCwidXNlcm5hbWUiOiJhZG1pbiJ9.tmw6Ac46Wjad9hR-xT6RWHHwfviEqML5_2iK9zI1HeY";
socket = IO.socket("https://test.enzhico.net/", options);
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("我连接成功啦啦啦,开始进行入网查询....");
// 客户端一旦连接成功,开始发起查询入网请求
String imei = "313123123123123";
socket.emit("askJoin", imei, (Ack) args1 -> {
JoinBindResponse r = JsonConverter.jsonObjectToObject(args1[0], JoinBindResponse.class);
logger.info("入网查询结果=" + r.getCode());
});
// 然后测试一下入网请求接口
PosParam posParam = new PosParam();
posParam.setImei("2222222222222222");
socket.emit("doJoin", JsonConverter.objectToJSONObject(posParam), (Ack) args1 -> {
BaseResponse r = JsonConverter.jsonObjectToObject(args1[0], JoinBindResponse.class);
logger.info("执行POS机入网结果=" + r.isSuccess() + ",msg=" + r.getMsg());
});
}
}).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("Socket.EVENT_CONNECT_ERROR");
socket.disconnect();
}
}).on(Socket.EVENT_CONNECT_TIMEOUT, new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("Socket.EVENT_CONNECT_TIMEOUT");
socket.disconnect();
}
}).on(Socket.EVENT_PING, new Emitter.Listener() {
@Override
public void call(Object... args) {
//logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + ": Socket.EVENT_PING");
}
}).on(Socket.EVENT_PONG, new Emitter.Listener() {
@Override
public void call(Object... args) {
//logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + ": Socket.EVENT_PONG");
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
logger.info("客户端断开连接啦。。。");
socket.disconnect();
}
});
socket.connect();
}
}

View File

@ -0,0 +1,130 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Demo Chat</title>
<link href="bootstrap.css" rel="stylesheet">
<style>
body {
padding: 20px;
}
#console {
height: 400px;
overflow: auto;
}
.username-msg {
color: orange;
}
.connect-msg {
color: green;
}
.disconnect-msg {
color: red;
}
.send-msg {
color: #888
}
</style>
<script src="js/socket.io/socket.io.js"></script>
<script src="js/moment.min.js"></script>
<script src="js/jquery-1.7.2.min.js"></script>
<script>
var userName = 'user' + Math.floor((Math.random() * 1000) + 1);
var token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhcHBpZCI6ImNvbS5lbnpoaWNvLmFkbWlucGF5IiwiaW1laSI6Ijg2NjAzMzAzMDkwNjAwMCIsImV4cCI6MTUxNjg3MDY2OCwidXNlcm5hbWUiOiJhZG1pbiJ9._9GSZFjXapHLXewrUdq8sExPuR3KPIZ2V2AoyF2J96M";
var socket = io.connect('https://test.enzhico.net/?token=' + token);
socket.on('connect', function () {
output('<span class="connect-msg">Client has connected to the server!</span>');
});
socket.on('message', function (data, ackServerCallback) {
output('<span class="username-msg">' + data.userName + ':</span> ' + data.message);
if (ackServerCallback) {
// send ack data to server
ackServerCallback('server message was delivered to client!');
}
});
socket.on('disconnect', function () {
output('<span class="disconnect-msg">The client has disconnected!</span>');
});
socket.on('ackevent2', function (data, ackServerCallback, arg1) {
output('<span class="username-msg">' + data.userName + ':</span> ' + data.message);
if (ackServerCallback) {
ackServerCallback('server message was delivered to client!');
}
});
socket.on('ackevent3', function (data, ackServerCallback) {
output('<span class="username-msg">' + data.userName + ':</span> ' + data.message);
if (ackServerCallback) {
ackServerCallback();
}
});
function sendDisconnect() {
socket.disconnect();
}
function sendMessage() {
var message = $('#msg').val();
$('#msg').val('');
var jsonObject = {
'@class': 'com.corundumstudio.socketio.demo.ChatObject',
userName: userName,
message: message
};
socket.emit('ackevent1', jsonObject, function (arg1, arg2) {
alert("ack from server! arg1: " + arg1 + ", arg2: " + arg2);
});
}
function output(message) {
var currentTime = "<span class='time'>" + moment().format('HH:mm:ss.SSS') + "</span>";
var element = $("<div>" + currentTime + " " + message + "</div>");
$('#console').prepend(element);
}
$(document).keydown(function (e) {
if (e.keyCode == 13) {
$('#send').click();
}
});
</script>
</head>
<body>
<h1>Netty-socketio Demo Chat</h1>
<br/>
<div id="console" class="well">
</div>
<form class="well form-inline" onsubmit="return false;">
<input id="msg" class="input-xlarge" type="text" placeholder="Type something..."/>
<button type="button" onClick="sendMessage()" class="btn" id="send">Send</button>
<button type="button" onClick="sendDisconnect()" class="btn">Disconnect</button>
</form>
</body>
</html>

View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Demo Chat</title>
<link href="bootstrap.css" rel="stylesheet">
<style>
body {
padding:20px;
}
#console {
height: 400px;
overflow: auto;
}
.username-msg {color:orange;}
.connect-msg {color:green;}
.disconnect-msg {color:red;}
.send-msg {color:#888}
</style>
<script src="js/socket.io/socket.io.js"></script>
<script src="js/moment.min.js"></script>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
var socket = io.connect('http://localhost:9092');
socket.on('connect', function() {
alert('socketio client connected');
});
socket.on('msg', function(file) {
var arrayBuffer = new Uint8Array(file).buffer;
var blob = new Blob([arrayBuffer]);
var imgList = $('ul#img-list');
var li = $('<li/>').appendTo(imgList);
$('<div/>').text(file.name).appendTo(li);
var img = $('<img/>').appendTo(li);
var reader = new FileReader();
reader.onload = (function(aImg) {
return function(e) {
aImg.attr('src', e.target.result);
aImg.attr('width', 150);
};
})(img);
reader.readAsDataURL(blob);
});
$(document).ready(function() {
var fileInput = $('#file-field');
fileInput.bind({
change: function() {
displayFiles(this.files);
}
});
function displayFiles(files) {
$.each(files, function(i, file) {
if (!file.type.match(/image.*/)) {
return true;
}
var reader = new FileReader();
reader.onload = function(e) {
socket.emit('msg', e.target.result);
};
reader.readAsArrayBuffer(file);
});
}
});
</script>
</head>
<body>
Please upload any image file.
<br/>
<br/>
<div>
<input type="file" name="file" id="file-field" />
</div>
<div id="img-container">
<ul id="img-list"></ul>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Demo Chat</title>
<link href="bootstrap.css" rel="stylesheet">
<style>
body {
padding:20px;
}
#console {
height: 400px;
overflow: auto;
}
.username-msg {color:orange;}
.connect-msg {color:green;}
.disconnect-msg {color:red;}
.send-msg {color:#888}
</style>
<script src="js/socket.io/socket.io.js"></script>
<script src="js/moment.min.js"></script>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
var userName = 'user' + Math.floor((Math.random()*1000)+1);
var socket = io.connect('http://localhost:9092');
socket.on('connect', function() {
output('<span class="connect-msg">Client has connected to the server!</span>');
});
socket.on('chatevent', function(data) {
output('<span class="username-msg">' + data.userName + ':</span> ' + data.message);
});
socket.on('disconnect', function() {
output('<span class="disconnect-msg">The client has disconnected!</span>');
});
function sendDisconnect() {
socket.disconnect();
}
function sendMessage() {
var message = $('#msg').val();
$('#msg').val('');
socket.emit('chatevent', {userName: userName, message: message});
}
function output(message) {
var currentTime = "<span class='time'>" + moment().format('HH:mm:ss.SSS') + "</span>";
var element = $("<div>" + currentTime + " " + message + "</div>");
$('#console').prepend(element);
}
$(document).keydown(function(e){
if(e.keyCode == 13) {
$('#send').click();
}
});
</script>
</head>
<body>
<h1>Netty-socketio Demo Chat</h1>
<br/>
<div id="console" class="well">
</div>
<form class="well form-inline" onsubmit="return false;">
<input id="msg" class="input-xlarge" type="text" placeholder="Type something..."/>
<button type="button" onClick="sendMessage()" class="btn" id="send">Send</button>
<button type="button" onClick="sendDisconnect()" class="btn">Disconnect</button>
</form>
</body>
</html>

View File

@ -0,0 +1,104 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Demo Chat</title>
<link href="bootstrap.css" rel="stylesheet">
<style>
body {
padding:20px;
}
#console {
height: 400px;
overflow: auto;
}
.username-msg {color:orange;}
.connect-msg {color:green;}
.disconnect-msg {color:red;}
.send-msg {color:#888}
</style>
<script src="js/socket.io/socket.io.js"></script>
<script src="js/moment.min.js"></script>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
var userName = 'user' + Math.floor((Math.random()*1000)+1);
var socket = io.connect('http://123.207.66.156:9099?username=' + userName + '&password=123456');
socket.on('connect', function() {
output('<span class="connect-msg">Client has connected to the server!</span>');
});
socket.on('ping', function() {
output('<span class="connect-msg">Client Ping msg to the server!</span>');
});
socket.on('pong', function() {
output('<span class="connect-msg">Client Pong msg from the server!</span>');
});
socket.on('chatevent', function(data) {
output('<span class="username-msg">' + data.userName + ':</span> ' + data.message);
});
socket.on('disconnect', function() {
output('<span class="disconnect-msg">The client has disconnected!</span>');
});
function sendDisconnect() {
socket.disconnect();
}
function sendMessage() {
var message = $('#msg').val();
$('#msg').val('');
var jsonObject = {
userName: userName,
message: message
};
socket.emit('chatevent', jsonObject);
}
function output(message) {
var currentTime = "<span class='time'>" + moment().format('HH:mm:ss.SSS') + "</span>";
var element = $("<div>" + currentTime + " " + message + "</div>");
$('#console').prepend(element);
}
$(document).keydown(function(e){
if(e.keyCode == 13) {
$('#send').click();
}
});
</script>
</head>
<body>
<h1>Netty-socketio Demo Chat</h1>
<br/>
<div id="console" class="well">
</div>
<form class="well form-inline" onsubmit="return false;">
<input id="msg" class="input-xlarge" type="text" placeholder="Type something..."/>
<button type="button" onClick="sendMessage()" class="btn" id="send">Send</button>
<button type="button" onClick="sendDisconnect()" class="btn">Disconnect</button>
</form>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,139 @@
<!DOCTYPE html>
<html>
<head>
<title>Demo Chat</title>
<link href="bootstrap.css" rel="stylesheet">
<style>
body {
padding:20px;
}
.console {
height: 400px;
overflow: auto;
}
.username-msg {color:orange;}
.connect-msg {color:green;}
.disconnect-msg {color:red;}
.send-msg {color:#888}
</style>
<script src="js/socket.io/socket.io.js"></script>
<script src="js/moment.min.js"></script>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
var userName1 = 'user1_' + Math.floor((Math.random()*1000)+1);
var userName2 = 'user2_' + Math.floor((Math.random()*1000)+1);
var chat1Socket = io.connect('http://localhost:9092/chat1');
var chat2Socket = io.connect('http://localhost:9092/chat2');
function connectHandler(parentId) {
return function() {
output('<span class="connect-msg">Client has connected to the server!</span>', parentId);
}
}
function messageHandler(parentId) {
return function(data) {
output('<span class="username-msg">' + data.userName + ':</span> ' + data.message, parentId);
}
}
function disconnectHandler(parentId) {
return function() {
output('<span class="disconnect-msg">The client has disconnected!</span>', parentId);
}
}
function sendMessageHandler(parentId, userName, chatSocket) {
var message = $(parentId + ' .msg').val();
$(parentId + ' .msg').val('');
var jsonObject = {'@class': 'com.corundumstudio.socketio.demo.ChatObject',
userName: userName,
message: message};
chatSocket.json.send(jsonObject);
}
chat1Socket.on('connect', connectHandler('#chat1'));
chat2Socket.on('connect', connectHandler('#chat2'));
chat1Socket.on('message', messageHandler('#chat1'));
chat2Socket.on('message', messageHandler('#chat2'));
chat1Socket.on('disconnect', disconnectHandler('#chat1'));
chat2Socket.on('disconnect', disconnectHandler('#chat2'));
function sendDisconnect1() {
chat1Socket.disconnect();
}
function sendDisconnect2() {
chat2Socket.disconnect();
}
function sendMessage1() {
sendMessageHandler('#chat1', userName1, chat1Socket);
}
function sendMessage2() {
sendMessageHandler('#chat2', userName2, chat2Socket);
}
function output(message, parentId) {
var currentTime = "<span class='time'>" + moment().format('HH:mm:ss.SSS') + "</span>";
var element = $("<div>" + currentTime + " " + message + "</div>");
$(parentId + ' .console').prepend(element);
}
$(document).keydown(function(e){
if(e.keyCode == 13) {
$('#send').click();
}
});
</script>
</head>
<body>
<h1>Namespaces demo chat</h1>
<br/>
<div id="chat1" style="width: 49%; float: left;">
<h4>chat1</h4>
<div class="console well">
</div>
<form class="well form-inline" onsubmit="return false;">
<input class="msg input-xlarge" type="text" placeholder="Type something..."/>
<button type="button" onClick="sendMessage1()" class="btn" id="send1">Send</button>
<button type="button" onClick="sendDisconnect1()" class="btn">Disconnect</button>
</form>
</div>
<div id="chat2" style="width: 49%; float: right;" >
<h4>chat2</h4>
<div class="console well">
</div>
<form class="well form-inline" onsubmit="return false;">
<input class="msg input-xlarge" type="text" placeholder="Type something..."/>
<button type="button" onClick="sendMessage2()" class="btn" id="send2">Send</button>
<button type="button" onClick="sendDisconnect2()" class="btn">Disconnect</button>
</form>
</div>
</body>
</html>

View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html>
<head>
<title>Demo Chat</title>
<link href="bootstrap.css" rel="stylesheet">
<style>
body {
padding:20px;
}
#console {
height: 400px;
overflow: auto;
}
.username-msg {color:orange;}
.connect-msg {color:green;}
.disconnect-msg {color:red;}
.send-msg {color:#888}
</style>
<script src="js/socket.io/socket.io.js"></script>
<script src="js/moment.min.js"></script>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script>
var userName = 'user' + Math.floor((Math.random()*1000)+1);
var socket = io.connect('https://localhost:10443');
socket.on('connect', function() {
output('<span class="connect-msg">Client has connected to the server!</span>');
});
socket.on('chatevent', function(data) {
output('<span class="username-msg">' + data.userName + ':</span> ' + data.message);
});
socket.on('disconnect', function() {
output('<span class="disconnect-msg">The client has disconnected!</span>');
});
function sendDisconnect() {
socket.disconnect();
}
function sendMessage() {
var message = $('#msg').val();
$('#msg').val('');
socket.emit('chatevent', {userName: userName, message: message});
}
function output(message) {
var currentTime = "<span class='time'>" + moment().format('HH:mm:ss.SSS') + "</span>";
var element = $("<div>" + currentTime + " " + message + "</div>");
$('#console').prepend(element);
}
$(document).keydown(function(e){
if(e.keyCode == 13) {
$('#send').click();
}
});
</script>
</head>
<body>
<h1>Netty-socketio Demo Chat</h1>
<br/>
<div id="console" class="well">
</div>
<form class="well form-inline" onsubmit="return false;">
<input id="msg" class="input-xlarge" type="text" placeholder="Type something..."/>
<button type="button" onClick="sendMessage()" class="btn" id="send">Send</button>
<button type="button" onClick="sendDisconnect()" class="btn">Disconnect</button>
</form>
</body>
</html>

View File

@ -0,0 +1,29 @@
package com.enzhico.jwt.socket.model;
/**
* ChatMessage
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/30
*/
public class ChatMessage {
private String userName;
private String message;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -0,0 +1,40 @@
package com.enzhico.jwt.socket.model;
import java.io.Serializable;
/**
* LoginRequest
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/18
*/
public class LoginRequest implements Serializable {
private int code;
private String body;
public LoginRequest() {
}
public LoginRequest(int code, String body) {
super();
this.code = code;
this.body = body;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}

View File

@ -0,0 +1,58 @@
package com.enzhico.jwt.socket.server;
import com.corundumstudio.socketio.AckCallback;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.VoidAckCallback;
import com.corundumstudio.socketio.listener.DataListener;
public class AckChatLauncher {
public static void main(String[] args) throws InterruptedException {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(9092);
final SocketIOServer server = new SocketIOServer(config);
server.addEventListener("ackevent1", ChatObject.class, new DataListener<ChatObject>() {
@Override
public void onData(final SocketIOClient client, ChatObject data, final AckRequest ackRequest) {
// check is ack requested by client,
// but it's not required check
if (ackRequest.isAckRequested()) {
// send ack response with data to client
ackRequest.sendAckData("client message was delivered to server!", "yeah!");
}
// send message back to client with ack callback WITH data
ChatObject ackChatObjectData = new ChatObject(data.getUserName(), "message with ack data");
client.sendEvent("ackevent2", new AckCallback<String>(String.class) {
@Override
public void onSuccess(String result) {
System.out.println("ack from client: " + client.getSessionId() + " data: " + result);
}
}, ackChatObjectData);
ChatObject ackChatObjectData1 = new ChatObject(data.getUserName(), "message with void ack");
client.sendEvent("ackevent3", new VoidAckCallback() {
protected void onSuccess() {
System.out.println("void ack from: " + client.getSessionId());
}
}, ackChatObjectData1);
}
});
server.start();
Thread.sleep(Integer.MAX_VALUE);
server.stop();
}
}

View File

@ -0,0 +1,38 @@
package com.enzhico.jwt.socket.server;
import java.io.UnsupportedEncodingException;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.Transport;
import com.corundumstudio.socketio.listener.DataListener;
public class BinaryEventLauncher {
public static void main(String[] args) throws InterruptedException, UnsupportedEncodingException {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(9092);
config.setMaxFramePayloadLength(1024 * 1024);
config.setMaxHttpContentLength(1024 * 1024);
final SocketIOServer server = new SocketIOServer(config);
server.addEventListener("msg", byte[].class, new DataListener<byte[]>() {
@Override
public void onData(SocketIOClient client, byte[] data, AckRequest ackRequest) {
client.sendEvent("msg", data);
}
});
server.start();
Thread.sleep(Integer.MAX_VALUE);
server.stop();
}
}

View File

@ -0,0 +1,30 @@
package com.enzhico.jwt.socket.server;
import com.corundumstudio.socketio.listener.*;
import com.corundumstudio.socketio.*;
public class ChatLauncher {
public static void main(String[] args) throws InterruptedException {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(9092);
final SocketIOServer server = new SocketIOServer(config);
server.addEventListener("chatevent", ChatObject.class, new DataListener<ChatObject>() {
@Override
public void onData(SocketIOClient client, ChatObject data, AckRequest ackRequest) {
// broadcast messages to all clients
server.getBroadcastOperations().sendEvent("chatevent", data);
}
});
server.start();
Thread.sleep(Integer.MAX_VALUE);
server.stop();
}
}

View File

@ -0,0 +1,31 @@
package com.enzhico.jwt.socket.server;
public class ChatObject {
private String userName;
private String message;
public ChatObject() {
}
public ChatObject(String userName, String message) {
super();
this.userName = userName;
this.message = message;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -0,0 +1,32 @@
package com.enzhico.jwt.socket.server;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.DataListener;
public class EventChatLauncher {
public static void main(String[] args) throws InterruptedException {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(9092);
final SocketIOServer server = new SocketIOServer(config);
server.addEventListener("chatevent", ChatObject.class, new DataListener<ChatObject>() {
@Override
public void onData(SocketIOClient client, ChatObject data, AckRequest ackRequest) {
server.getBroadcastOperations().sendEvent("chatevent", data);
}
});
server.start();
Thread.sleep(Integer.MAX_VALUE);
server.stop();
}
}

View File

@ -0,0 +1,40 @@
package com.enzhico.jwt.socket.server;
import com.corundumstudio.socketio.listener.*;
import com.corundumstudio.socketio.*;
public class NamespaceChatLauncher {
public static void main(String[] args) throws InterruptedException {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(9092);
final SocketIOServer server = new SocketIOServer(config);
final SocketIONamespace chat1namespace = server.addNamespace("/chat1");
chat1namespace.addEventListener("message", ChatObject.class, new DataListener<ChatObject>() {
@Override
public void onData(SocketIOClient client, ChatObject data, AckRequest ackRequest) {
// broadcast messages to all clients
chat1namespace.getBroadcastOperations().sendEvent("message", data);
}
});
final SocketIONamespace chat2namespace = server.addNamespace("/chat2");
chat2namespace.addEventListener("message", ChatObject.class, new DataListener<ChatObject>() {
@Override
public void onData(SocketIOClient client, ChatObject data, AckRequest ackRequest) {
// broadcast messages to all clients
chat2namespace.getBroadcastOperations().sendEvent("message", data);
}
});
server.start();
Thread.sleep(Integer.MAX_VALUE);
server.stop();
}
}

View File

@ -0,0 +1,131 @@
package com.enzhico.jwt.socket.server;
import com.corundumstudio.socketio.*;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.enzhico.jwt.socket.model.LoginRequest;
import io.socket.engineio.client.Socket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class NamespaceSocketServer {
private static final Logger logger = LoggerFactory.getLogger(NamespaceSocketServer.class);
public static void main(String[] args) {
/*
* 创建Socket并设置监听端口
*/
Configuration config = new Configuration();
//设置主机名
config.setHostname("localhost");
//设置监听端口
config.setPort(9092);
// 协议升级超时时间毫秒默认10秒。HTTP握手升级为ws协议超时时间
config.setUpgradeTimeout(10000);
// Ping消息超时时间毫秒默认60秒这个时间间隔内没有接收到心跳消息就会发送超时事件
config.setPingTimeout(180000);
// Ping消息间隔毫秒默认25秒。客户端向服务器发送一条心跳消息间隔
config.setPingInterval(60000);
// 连接认证这里使用token更合适
config.setAuthorizationListener(new AuthorizationListener() {
@Override
public boolean isAuthorized(HandshakeData data) {
// 客户端使用 options.query = "username=test&password=test";
// 可以使用如下代码获取用户密码信息,本文不做身份验证
String username = data.getSingleUrlParam("username");
String password = data.getSingleUrlParam("password");
logger.info("认证信息username=" + username + ",password=" + password);
// 如果认证不通过会返回一个Socket.EVENT_CONNECT_ERROR事件
return true;
}
});
final SocketIOServer server = new SocketIOServer(config);
/*
* 添加连接监听事件,监听是否与客户端连接到服务器
*/
server.addConnectListener(new ConnectListener() {
@Override
public void onConnect(SocketIOClient client) {
// 判断是否有客户端连接
if (client != null) {
logger.info("连接成功。clientId=" + client.getSessionId().toString());
client.joinRoom(client.getHandshakeData().getSingleUrlParam("appid"));
} else {
logger.error("并没有人连接上。。。");
}
}
});
/*
* 添加监听事件,监听客户端的事件
* 1.第一个参数eventName需要与客户端的事件要一致
* 2.第二个参数eventClase是传输的数据类型
* 3.第三个参数listener是用于接收客户端传的数据数据类型需要与eventClass一致
*/
server.addEventListener("login", LoginRequest.class, new DataListener<LoginRequest>() {
@Override
public void onData(SocketIOClient client, LoginRequest data, AckRequest ackRequest) {
logger.info("接收到客户端login消息code = " + data.getCode() + ",body = " + data.getBody());
// check is ack requested by client,
// but it's not required check
if (ackRequest.isAckRequested()) {
// send ack response with data to client
ackRequest.sendAckData("已成功收到客户端登录请求", "yeah");
}
// 向客户端发送消息
List<String> list = new ArrayList<>();
list.add("登录成功sessionId=" + client.getSessionId());
// 第一个参数必须与eventName一致第二个参数data必须与eventClass一致
String room = client.getHandshakeData().getSingleUrlParam("appid");
server.getRoomOperations(room).sendEvent("login", list.toString());
// client.disconnect();
}
});
//启动服务
server.start();
}
private static void addNamespace(SocketIOServer server, String namespace) {
final SocketIONamespace chat1namespace = server.addNamespace(namespace);
chat1namespace.addEventListener(Socket.EVENT_MESSAGE, ChatObject.class, new DataListener<ChatObject>() {
@Override
public void onData(SocketIOClient client, ChatObject data, AckRequest ackRequest) {
// broadcast messages to all clients
chat1namespace.getBroadcastOperations().sendEvent(Socket.EVENT_MESSAGE, data);
}
});
/*
* 添加监听事件,监听客户端的事件
* 1.第一个参数eventName需要与客户端的事件要一致
* 2.第二个参数eventClase是传输的数据类型
* 3.第三个参数listener是用于接收客户端传的数据数据类型需要与eventClass一致
*/
chat1namespace.addEventListener("login", LoginRequest.class, new DataListener<LoginRequest>() {
@Override
public void onData(SocketIOClient client, LoginRequest data, AckRequest ackRequest) {
logger.info("接收到客户端login消息code = " + data.getCode() + ",body = " + data.getBody());
// check is ack requested by client,
// but it's not required check
if (ackRequest.isAckRequested()) {
// send ack response with data to client
ackRequest.sendAckData("命名空间" + namespace + "已成功收到客户端登录请求", "yeah");
}
// 向客户端发送消息
List<String> list = new ArrayList<>();
list.add("登录成功");
// 第一个参数必须与eventName一致第二个参数data必须与eventClass一致
chat1namespace.getBroadcastOperations().sendEvent("loginReply", list.toString());
// client.disconnect();
}
});
}
}

View File

@ -0,0 +1,20 @@
package com.enzhico.jwt.socket.server;
import com.corundumstudio.socketio.listener.ExceptionListenerAdapter;
import io.netty.channel.ChannelHandlerContext;
/**
* MyExceptionListener
*
* @author XiongNeng
* @version 1.0
* @since 2018/1/30
*/
public class SocketExceptionListener extends ExceptionListenerAdapter {
@Override
public boolean exceptionCaught(ChannelHandlerContext ctx, Throwable e) {
System.out.println(e.getMessage());
ctx.close();
return true;
}
}

View File

@ -0,0 +1,140 @@
package com.enzhico.jwt.socket.server;
import com.corundumstudio.socketio.*;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener;
import com.enzhico.jwt.socket.model.ChatMessage;
import com.enzhico.jwt.socket.model.LoginRequest;
import io.socket.engineio.client.Socket;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class SocketServer {
private static final Logger logger = LoggerFactory.getLogger(SocketServer.class);
@Test
public void test() {
/*
* 创建Socket并设置监听端口
*/
Configuration config = new Configuration();
//设置主机名
config.setHostname("localhost");
//设置监听端口
config.setPort(9099);
// 协议升级超时时间毫秒默认10秒。HTTP握手升级为ws协议超时时间
config.setUpgradeTimeout(10000);
// Ping消息超时时间毫秒默认60秒这个时间间隔内没有接收到心跳消息就会发送超时事件
config.setPingTimeout(15000);
// Ping消息间隔毫秒默认25秒。客户端向服务器发送一条心跳消息间隔
config.setPingInterval(5000);
// 这个版本0.9.0不能处理好namespace和query参数的问题。所以为了做认证必须使用全局默认命名空间
config.setAuthorizationListener(new AuthorizationListener() {
@Override
public boolean isAuthorized(HandshakeData data) {
// 客户端使用 options.query = "username=test&password=test";
// 可以使用如下代码获取用户密码信息,本文不做身份验证
String username = data.getSingleUrlParam("username");
String password = data.getSingleUrlParam("password");
logger.info("认证信息username=" + username + ",password=" + password);
// 如果认证不通过会返回一个Socket.EVENT_CONNECT_ERROR事件
return true;
}
});
config.setExceptionListener(new SocketExceptionListener());
final SocketIOServer server = new SocketIOServer(config);
// 添加命名空间
// addNamespace(server, "/ns");
/*
* 添加连接监听事件,监听是否与客户端连接到服务器
*/
server.addConnectListener(new ConnectListener() {
@Override
public void onConnect(SocketIOClient client) {
// 判断是否有客户端连接
if (client != null) {
logger.info("连接成功。clientId=" + client.getSessionId().toString());
client.joinRoom("room1");
} else {
logger.error("并没有人连接上。。。");
}
}
});
server.addDisconnectListener(new DisconnectListener() {
@Override
public void onDisconnect(SocketIOClient client) {
System.out.println("服务器收到断线通知... sessionId=" + client.getSessionId());
}
});
server.addEventListener(Socket.EVENT_MESSAGE, String.class, new DataListener<String>() {
@Override
public void onData(SocketIOClient client, String data, AckRequest ackRequest) {
if (ackRequest.isAckRequested()) {
// send ack response with data to client
ackRequest.sendAckData("服务器回答Socket.EVENT_MESSAGE", "你狠");
}
}
});
server.addEventListener("chatevent", ChatMessage.class, new DataListener<ChatMessage>() {
@Override
public void onData(SocketIOClient client, ChatMessage data, AckRequest ackRequest) {
System.out.println("服务器收到客户端的chatevent消息");
System.out.println(data);
client.sendEvent("chatevent", data);
}
});
/*
* 添加监听事件,监听客户端的事件
* 1.第一个参数eventName需要与客户端的事件要一致
* 2.第二个参数eventClase是传输的数据类型
* 3.第三个参数listener是用于接收客户端传的数据数据类型需要与eventClass一致
*/
server.addEventListener("login", LoginRequest.class, new DataListener<LoginRequest>() {
@Override
public void onData(SocketIOClient client, LoginRequest data, AckRequest ackRequest) {
logger.info("接收到客户端login消息code = " + data.getCode() + ",body = " + data.getBody());
// check is ack requested by client,
// but it's not required check
if (ackRequest.isAckRequested()) {
// send ack response with data to client
ackRequest.sendAckData("服务器已成功收到客户端登录请求", "yeah");
}
// 向客户端发送消息
List<String> list = new ArrayList<>();
list.add("登录成功");
// 第一个参数必须与eventName一致第二个参数data必须与eventClass一致
// 房间广播消息
server.getRoomOperations("room1").sendEvent("loginReply", list.toString());
// client.sendEvent("loginReply", list.toString());
// client.disconnect();
}
});
//启动服务
server.start();
while (true) {
try {
Thread.sleep(200000000000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,38 @@
package com.enzhico.jwt.socket.server;
import java.io.InputStream;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.DataListener;
public class SslChatLauncher {
public static void main(String[] args) throws InterruptedException {
Configuration config = new Configuration();
config.setHostname("localhost");
config.setPort(10443);
config.setKeyStorePassword("test1234");
InputStream stream = SslChatLauncher.class.getResourceAsStream("/keystore.jks");
config.setKeyStore(stream);
final SocketIOServer server = new SocketIOServer(config);
server.addEventListener("chatevent", ChatObject.class, new DataListener<ChatObject>() {
@Override
public void onData(SocketIOClient client, ChatObject data, AckRequest ackRequest) {
server.getBroadcastOperations().sendEvent("chatevent", data);
}
});
server.start();
Thread.sleep(Integer.MAX_VALUE);
server.stop();
}
}

Binary file not shown.