mirror of
https://github.com/kataras/iris.git
synced 2025-12-27 14:57:05 +00:00
Add the new websocket package (which is just a helper for kataras/neffos) and an example for go server, client, browser client and nodejs client. Add a .fossa.yml and the generated NOTICE file for 3rd-party libs. Update go.mod, go.sum. Update the vendor folder for pongo2 to its latest master as well
Former-commit-id: 89c05079415977d65e7328a1eb8a1c602d76f78a
This commit is contained in:
93
_examples/websocket/basic/browser/index.html
Normal file
93
_examples/websocket/basic/browser/index.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!-- the message's input -->
|
||||
<input id="input" type="text" />
|
||||
|
||||
<!-- when clicked then a websocket event will be sent to the server, at this example we registered the 'chat' -->
|
||||
<button id="sendBtn" disabled>Send</button>
|
||||
|
||||
<!-- the messages will be shown here -->
|
||||
<pre id="output"></pre>
|
||||
<!-- import the iris client-side library for browser from a CDN or locally.
|
||||
However, `neffos.(min.)js` is a NPM package too so alternatively,
|
||||
you can use it as dependency on your package.json and all nodejs-npm tooling become available:
|
||||
see the "browserify" example for more-->
|
||||
<script src="https://cdn.jsdelivr.net/npm/neffos.js@0.1.8/dist/neffos.min.js"></script>
|
||||
<script>
|
||||
// `neffos` global variable is available now.
|
||||
var scheme = document.location.protocol == "https:" ? "wss" : "ws";
|
||||
var port = document.location.port ? ":" + document.location.port : "";
|
||||
var wsURL = scheme + "://" + document.location.hostname + port + "/echo";
|
||||
|
||||
var outputTxt = document.getElementById("output");
|
||||
function addMessage(msg) {
|
||||
outputTxt.innerHTML += msg + "\n";
|
||||
}
|
||||
|
||||
function handleError(reason) {
|
||||
console.log(reason);
|
||||
window.alert(reason);
|
||||
}
|
||||
|
||||
function handleNamespaceConnectedConn(nsConn) {
|
||||
let inputTxt = document.getElementById("input");
|
||||
let sendBtn = document.getElementById("sendBtn");
|
||||
|
||||
sendBtn.disabled = false;
|
||||
sendBtn.onclick = function () {
|
||||
const input = inputTxt.value;
|
||||
inputTxt.value = "";
|
||||
nsConn.emit("chat", input);
|
||||
addMessage("Me: " + input);
|
||||
};
|
||||
}
|
||||
|
||||
async function runExample() {
|
||||
// You can omit the "default" and simply define only Events, the namespace will be an empty string"",
|
||||
// however if you decide to make any changes on this example make sure the changes are reflecting inside the ../server.go file as well.
|
||||
try {
|
||||
const conn = await neffos.dial(wsURL, {
|
||||
default: { // "default" namespace.
|
||||
_OnNamespaceConnected: function (nsConn, msg) {
|
||||
addMessage("connected to namespace: " + msg.Namespace);
|
||||
handleNamespaceConnectedConn(nsConn)
|
||||
},
|
||||
_OnNamespaceDisconnect: function (nsConn, msg) {
|
||||
addMessage("disconnected from namespace: " + msg.Namespace);
|
||||
},
|
||||
chat: function (nsConn, msg) { // "chat" event.
|
||||
addMessage(msg.Body);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// You can either wait to conenct or just conn.connect("connect")
|
||||
// and put the `handleNamespaceConnectedConn` inside `_OnNamespaceConnected` callback instead.
|
||||
// const nsConn = await conn.connect("default");
|
||||
// handleNamespaceConnectedConn(nsConn);
|
||||
conn.connect("default");
|
||||
|
||||
} catch (err) {
|
||||
handleError(err);
|
||||
}
|
||||
}
|
||||
|
||||
runExample();
|
||||
|
||||
// If "await" and "async" are available, use them instead^, all modern browsers support those,
|
||||
// all of the javascript examples will be written using async/await method instead of promise then/catch callbacks.
|
||||
// A usage example of promise then/catch follows:
|
||||
// neffos.dial(wsURL, {
|
||||
// default: { // "default" namespace.
|
||||
// _OnNamespaceConnected: function (ns, msg) {
|
||||
// addMessage("connected to namespace: " + msg.Namespace);
|
||||
// },
|
||||
// _OnNamespaceDisconnect: function (ns, msg) {
|
||||
// addMessage("disconnected from namespace: " + msg.Namespace);
|
||||
// },
|
||||
// chat: function (ns, msg) { // "chat" event.
|
||||
// addMessage(msg.Body);
|
||||
// }
|
||||
// }
|
||||
// }).then(function (conn) {
|
||||
// conn.connect("default").then(handleNamespaceConnectedConn).catch(handleError);
|
||||
// }).catch(handleError);
|
||||
</script>
|
||||
11
_examples/websocket/basic/browserify/README.md
Normal file
11
_examples/websocket/basic/browserify/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Browserify example
|
||||
|
||||
```sh
|
||||
$ npm install --only=dev # install browserify from the devDependencies.
|
||||
$ npm run-script build # browserify and minify the `app.js` into `bundle.js`.
|
||||
$ cd ../ && go run server.go # start the neffos server.
|
||||
```
|
||||
|
||||
> make sure that you have [golang](https://golang.org/dl) installed to run and edit the neffos (server-side).
|
||||
|
||||
That's all, now navigate to <http://localhost:8080/browserify>.
|
||||
61
_examples/websocket/basic/browserify/app.js
Normal file
61
_examples/websocket/basic/browserify/app.js
Normal file
@@ -0,0 +1,61 @@
|
||||
const neffos = require('neffos.js');
|
||||
|
||||
var scheme = document.location.protocol == "https:" ? "wss" : "ws";
|
||||
var port = document.location.port ? ":" + document.location.port : "";
|
||||
|
||||
var wsURL = scheme + "://" + document.location.hostname + port + "/echo";
|
||||
|
||||
var outputTxt = document.getElementById("output");
|
||||
function addMessage(msg) {
|
||||
outputTxt.innerHTML += msg + "\n";
|
||||
}
|
||||
|
||||
function handleError(reason) {
|
||||
console.log(reason);
|
||||
window.alert(reason);
|
||||
}
|
||||
|
||||
function handleNamespaceConnectedConn(nsConn) {
|
||||
const inputTxt = document.getElementById("input");
|
||||
const sendBtn = document.getElementById("sendBtn");
|
||||
|
||||
sendBtn.disabled = false;
|
||||
sendBtn.onclick = function () {
|
||||
const input = inputTxt.value;
|
||||
inputTxt.value = "";
|
||||
|
||||
nsConn.emit("chat", input);
|
||||
addMessage("Me: " + input);
|
||||
};
|
||||
}
|
||||
|
||||
async function runExample() {
|
||||
try {
|
||||
const conn = await neffos.dial(wsURL, {
|
||||
default: { // "default" namespace.
|
||||
_OnNamespaceConnected: function (nsConn, msg) {
|
||||
addMessage("connected to namespace: " + msg.Namespace);
|
||||
handleNamespaceConnectedConn(nsConn);
|
||||
},
|
||||
_OnNamespaceDisconnect: function (nsConn, msg) {
|
||||
addMessage("disconnected from namespace: " + msg.Namespace);
|
||||
},
|
||||
chat: function (nsConn, msg) { // "chat" event.
|
||||
addMessage(msg.Body);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// You can either wait to conenct or just conn.connect("connect")
|
||||
// and put the `handleNamespaceConnectedConn` inside `_OnNamespaceConnected` callback instead.
|
||||
// const nsConn = await conn.connect("default");
|
||||
// handleNamespaceConnectedConn(nsConn);
|
||||
conn.connect("default");
|
||||
|
||||
} catch (err) {
|
||||
handleError(err);
|
||||
}
|
||||
}
|
||||
|
||||
runExample();
|
||||
|
||||
1
_examples/websocket/basic/browserify/bundle.js
Normal file
1
_examples/websocket/basic/browserify/bundle.js
Normal file
File diff suppressed because one or more lines are too long
10
_examples/websocket/basic/browserify/index.html
Normal file
10
_examples/websocket/basic/browserify/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<!-- the message's input -->
|
||||
<input id="input" type="text" />
|
||||
|
||||
<!-- when clicked then a websocket event will be sent to the server, at this example we registered the 'chat' -->
|
||||
<button id="sendBtn" disabled>Send</button>
|
||||
|
||||
<!-- the messages will be shown here -->
|
||||
<pre id="output"></pre>
|
||||
|
||||
<script src="./bundle.js"></script>
|
||||
16
_examples/websocket/basic/browserify/package.json
Normal file
16
_examples/websocket/basic/browserify/package.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "neffos.js.example.browserify",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"browserify": "browserify ./app.js -o ./bundle.js",
|
||||
"minifyES6": "minify ./bundle.js --outFile ./bundle.js",
|
||||
"build": "npm run-script browserify && npm run-script minifyES6"
|
||||
},
|
||||
"dependencies": {
|
||||
"neffos.js": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^16.2.3",
|
||||
"babel-minify": "^0.5.0"
|
||||
}
|
||||
}
|
||||
85
_examples/websocket/basic/go-client/client.go
Normal file
85
_examples/websocket/basic/go-client/client.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris/websocket"
|
||||
)
|
||||
|
||||
const (
|
||||
endpoint = "ws://localhost:8080/echo"
|
||||
namespace = "default"
|
||||
dialAndConnectTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
// this can be shared with the server.go's.
|
||||
// `NSConn.Conn` has the `IsClient() bool` method which can be used to
|
||||
// check if that's is a client or a server-side callback.
|
||||
var clientEvents = websocket.Namespaces{
|
||||
namespace: websocket.Events{
|
||||
websocket.OnNamespaceConnected: func(c *websocket.NSConn, msg websocket.Message) error {
|
||||
log.Printf("[%s] connected to namespace [%s]", c, msg.Namespace)
|
||||
return nil
|
||||
},
|
||||
websocket.OnNamespaceDisconnect: func(c *websocket.NSConn, msg websocket.Message) error {
|
||||
log.Printf("[%s] disconnected from namespace [%s]", c, msg.Namespace)
|
||||
return nil
|
||||
},
|
||||
"chat": func(c *websocket.NSConn, msg websocket.Message) error {
|
||||
log.Printf("[%s] sent: %s", c.Conn.ID(), string(msg.Body))
|
||||
|
||||
// Write message back to the client message owner with:
|
||||
// c.Emit("chat", msg)
|
||||
// Write message to all except this client with:
|
||||
c.Conn.Server().Broadcast(c, msg)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(dialAndConnectTimeout))
|
||||
defer cancel()
|
||||
|
||||
client, err := websocket.Dial(ctx, websocket.GorillaDialer, endpoint, clientEvents)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
c, err := client.Connect(ctx, namespace)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Fprint(os.Stdout, ">> ")
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for {
|
||||
if !scanner.Scan() {
|
||||
log.Printf("ERROR: %v", scanner.Err())
|
||||
return
|
||||
}
|
||||
|
||||
text := scanner.Bytes()
|
||||
|
||||
if bytes.Equal(text, []byte("exit")) {
|
||||
if err := c.Disconnect(nil); err != nil {
|
||||
log.Printf("reply from server: %v", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
ok := c.Emit("chat", text)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Fprint(os.Stdout, ">> ")
|
||||
}
|
||||
} // try running this program twice or/and run the server's http://localhost:8080 to check the browser client as well.
|
||||
53
_examples/websocket/basic/server.go
Normal file
53
_examples/websocket/basic/server.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/websocket"
|
||||
)
|
||||
|
||||
const namespace = "default"
|
||||
|
||||
// if namespace is empty then simply websocket.Events{...} can be used instead.
|
||||
var serverEvents = websocket.Namespaces{
|
||||
namespace: websocket.Events{
|
||||
websocket.OnNamespaceConnected: func(c *websocket.NSConn, msg websocket.Message) error {
|
||||
log.Printf("[%s] connected to namespace [%s]", c, msg.Namespace)
|
||||
return nil
|
||||
},
|
||||
websocket.OnNamespaceDisconnect: func(c *websocket.NSConn, msg websocket.Message) error {
|
||||
log.Printf("[%s] disconnected from namespace [%s]", c, msg.Namespace)
|
||||
return nil
|
||||
},
|
||||
"chat": func(c *websocket.NSConn, msg websocket.Message) error {
|
||||
log.Printf("[%s] sent: %s", c.Conn.ID(), string(msg.Body))
|
||||
|
||||
// Write message back to the client message owner with:
|
||||
// c.Emit("chat", msg)
|
||||
// Write message to all except this client with:
|
||||
c.Conn.Server().Broadcast(c, msg)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
websocketServer := websocket.New(
|
||||
websocket.DefaultGorillaUpgrader, /*DefaultGobwasUpgrader can be used as well*/
|
||||
serverEvents)
|
||||
|
||||
// serves the endpoint of ws://localhost:8080/echo
|
||||
app.Get("/echo", websocket.Handler(websocketServer))
|
||||
|
||||
// serves the browser-based websocket client.
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ServeFile("./browser/index.html", false)
|
||||
})
|
||||
|
||||
// serves the npm browser websocket client usage example.
|
||||
app.StaticWeb("/browserify", "./browserify")
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/websocket"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ServeFile("websockets.html", false) // second parameter: enable gzip?
|
||||
})
|
||||
|
||||
setupWebsocket(app)
|
||||
|
||||
// x2
|
||||
// http://localhost:8080
|
||||
// http://localhost:8080
|
||||
// write something, press submit, see the result.
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
|
||||
func setupWebsocket(app *iris.Application) {
|
||||
// create our echo websocket server
|
||||
ws := websocket.New(websocket.Config{
|
||||
// These are low-level optionally fields,
|
||||
// user/client can't see those values.
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
// only javascript client-side code has the same rule,
|
||||
// which you serve using the ws.ClientSource (see below).
|
||||
EvtMessagePrefix: []byte("my-custom-prefix:"),
|
||||
})
|
||||
ws.OnConnection(handleConnection)
|
||||
|
||||
// register the server on an endpoint.
|
||||
// see the inline javascript code in the websockets.html, this endpoint is used to connect to the server.
|
||||
app.Get("/echo", ws.Handler())
|
||||
|
||||
// serve the javascript builtin client-side library,
|
||||
// see websockets.html script tags, this path is used.
|
||||
app.Any("/iris-ws.js", func(ctx iris.Context) {
|
||||
ctx.Write(ws.ClientSource)
|
||||
})
|
||||
}
|
||||
|
||||
func handleConnection(c websocket.Connection) {
|
||||
// Read events from browser
|
||||
c.On("chat", func(msg string) {
|
||||
// Print the message to the console, c.Context() is the iris's http context.
|
||||
fmt.Printf("[%s <%s>] %s\n", c.ID(), c.Context().RemoteAddr(), msg)
|
||||
// Write message back to the client message owner with:
|
||||
// c.Emit("chat", msg)
|
||||
// Write message to all except this client with:
|
||||
c.To(websocket.Broadcast).Emit("chat", msg)
|
||||
})
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<!-- the message's input -->
|
||||
<input id="input" type="text" />
|
||||
|
||||
<!-- when clicked then an iris websocket event will be sent to the server, at this example we registered the 'chat' -->
|
||||
<button onclick="send()">Send</button>
|
||||
|
||||
<!-- the messages will be shown here -->
|
||||
<pre id="output"></pre>
|
||||
<!-- import the iris client-side library for browser-->
|
||||
<script src="/iris-ws.js"></script>
|
||||
|
||||
<script>
|
||||
var scheme = document.location.protocol == "https:" ? "wss" : "ws";
|
||||
var port = document.location.port ? (":" + document.location.port) : "";
|
||||
// see app.Get("/echo", ws.Handler()) on main.go
|
||||
var wsURL = scheme + "://" + document.location.hostname + port+"/echo";
|
||||
|
||||
var input = document.getElementById("input");
|
||||
var output = document.getElementById("output");
|
||||
|
||||
// Ws comes from the auto-served '/iris-ws.js'
|
||||
var socket = new Ws(wsURL)
|
||||
socket.OnConnect(function () {
|
||||
output.innerHTML += "Status: Connected\n";
|
||||
});
|
||||
|
||||
socket.OnDisconnect(function () {
|
||||
output.innerHTML += "Status: Disconnected\n";
|
||||
});
|
||||
|
||||
// read events from the server
|
||||
socket.On("chat", function (msg) {
|
||||
addMessage(msg);
|
||||
});
|
||||
|
||||
function send() {
|
||||
addMessage("Me: " + input.value); // write ourselves
|
||||
socket.Emit("chat", input.value);// send chat event data to the websocket server
|
||||
input.value = ""; // clear the input
|
||||
}
|
||||
|
||||
function addMessage(msg) {
|
||||
output.innerHTML += msg + "\n";
|
||||
}
|
||||
</script>
|
||||
@@ -1,96 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
|
||||
"github.com/kataras/iris/websocket"
|
||||
)
|
||||
|
||||
type clientPage struct {
|
||||
Title string
|
||||
Host string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.RegisterView(iris.HTML("./templates", ".html")) // select the html engine to serve templates
|
||||
|
||||
ws := websocket.New(websocket.Config{})
|
||||
|
||||
// register the server on an endpoint.
|
||||
// see the inline javascript code i the websockets.html, this endpoint is used to connect to the server.
|
||||
app.Get("/my_endpoint", ws.Handler())
|
||||
|
||||
// serve the javascript builtin client-side library,
|
||||
// see websockets.html script tags, this path is used.
|
||||
app.Any("/iris-ws.js", func(ctx iris.Context) {
|
||||
ctx.Write(websocket.ClientSource)
|
||||
})
|
||||
|
||||
app.StaticWeb("/js", "./static/js") // serve our custom javascript code
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ViewData("", clientPage{"Client Page", "localhost:8080"})
|
||||
ctx.View("client.html")
|
||||
})
|
||||
|
||||
Conn := make(map[websocket.Connection]bool)
|
||||
var myChatRoom = "room1"
|
||||
var mutex = new(sync.Mutex)
|
||||
|
||||
ws.OnConnection(func(c websocket.Connection) {
|
||||
c.Join(myChatRoom)
|
||||
mutex.Lock()
|
||||
Conn[c] = true
|
||||
mutex.Unlock()
|
||||
c.On("chat", func(message string) {
|
||||
if message == "leave" {
|
||||
c.Leave(myChatRoom)
|
||||
c.To(myChatRoom).Emit("chat", "Client with ID: "+c.ID()+" left from the room and cannot send or receive message to/from this room.")
|
||||
c.Emit("chat", "You have left from the room: "+myChatRoom+" you cannot send or receive any messages from others inside that room.")
|
||||
return
|
||||
}
|
||||
})
|
||||
c.OnDisconnect(func() {
|
||||
mutex.Lock()
|
||||
delete(Conn, c)
|
||||
mutex.Unlock()
|
||||
fmt.Printf("\nConnection with ID: %s has been disconnected!\n", c.ID())
|
||||
})
|
||||
})
|
||||
|
||||
var delay = 1 * time.Second
|
||||
go func() {
|
||||
i := 0
|
||||
for {
|
||||
mutex.Lock()
|
||||
broadcast(Conn, fmt.Sprintf("aaaa %d\n", i))
|
||||
mutex.Unlock()
|
||||
time.Sleep(delay)
|
||||
i++
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
i := 0
|
||||
for range time.Tick(1 * time.Second) { //another way to get clock signal
|
||||
mutex.Lock()
|
||||
broadcast(Conn, fmt.Sprintf("aaaa2 %d\n", i))
|
||||
mutex.Unlock()
|
||||
time.Sleep(delay)
|
||||
i++
|
||||
}
|
||||
}()
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
|
||||
func broadcast(Conn map[websocket.Connection]bool, message string) {
|
||||
for k := range Conn {
|
||||
k.To("room1").Emit("chat", message)
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
var messageTxt;
|
||||
var messages;
|
||||
|
||||
$(function () {
|
||||
|
||||
messageTxt = $("#messageTxt");
|
||||
messages = $("#messages");
|
||||
|
||||
|
||||
w = new Ws("ws://" + HOST + "/my_endpoint");
|
||||
w.OnConnect(function () {
|
||||
console.log("Websocket connection established");
|
||||
});
|
||||
|
||||
w.OnDisconnect(function () {
|
||||
appendMessage($("<div><center><h3>Disconnected</h3></center></div>"));
|
||||
});
|
||||
|
||||
w.On("chat", function (message) {
|
||||
appendMessage($("<div>" + message + "</div>"));
|
||||
});
|
||||
|
||||
$("#sendBtn").click(function () {
|
||||
w.Emit("chat", messageTxt.val().toString());
|
||||
messageTxt.val("");
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
|
||||
function appendMessage(messageDiv) {
|
||||
var theDiv = messages[0];
|
||||
var doScroll = theDiv.scrollTop == theDiv.scrollHeight - theDiv.clientHeight;
|
||||
messageDiv.appendTo(messages);
|
||||
if (doScroll) {
|
||||
theDiv.scrollTop = theDiv.scrollHeight - theDiv.clientHeight;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{{ .Title}}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="messages"
|
||||
style="border-width: 1px; border-style: solid; height: 400px; width: 375px;">
|
||||
|
||||
</div>
|
||||
<input type="text" id="messageTxt" />
|
||||
<button type="button" id="sendBtn">Send</button>
|
||||
<script type="text/javascript">
|
||||
var HOST = {{.Host}}
|
||||
</script>
|
||||
<script src="js/vendor/jquery-2.2.3.min.js" type="text/javascript"></script>
|
||||
<!-- This is auto-serving by the iris, you don't need to have this file in your disk-->
|
||||
<script src="/iris-ws.js" type="text/javascript"></script>
|
||||
<!-- -->
|
||||
<script src="js/chat.js" type="text/javascript"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,179 +0,0 @@
|
||||
package main
|
||||
|
||||
// Run first `go run main.go server`
|
||||
// and `go run main.go client` as many times as you want.
|
||||
// Originally written by: github.com/antlaw to describe an old issue.
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/websocket"
|
||||
|
||||
xwebsocket "golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
// WS is the current websocket connection
|
||||
var WS *xwebsocket.Conn
|
||||
|
||||
// $ go run main.go server
|
||||
// $ go run main.go client
|
||||
func main() {
|
||||
if len(os.Args) == 2 && strings.ToLower(os.Args[1]) == "server" {
|
||||
ServerLoop()
|
||||
} else if len(os.Args) == 2 && strings.ToLower(os.Args[1]) == "client" {
|
||||
ClientLoop()
|
||||
} else {
|
||||
fmt.Println("wsserver [server|client]")
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// client side
|
||||
func sendUntilErr(sendInterval int) {
|
||||
i := 1
|
||||
for {
|
||||
time.Sleep(time.Duration(sendInterval) * time.Second)
|
||||
err := SendMessage("2", "all", "objectupdate", "2.UsrSchedule_v1_1")
|
||||
if err != nil {
|
||||
fmt.Println("failed to send join message", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Println("objectupdate", i)
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func recvUntilErr() {
|
||||
var msg = make([]byte, 2048)
|
||||
var n int
|
||||
var err error
|
||||
i := 1
|
||||
for {
|
||||
if n, err = WS.Read(msg); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Printf("%v Received: %s.%v\n", time.Now(), string(msg[:n]), i)
|
||||
i++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//ConnectWebSocket connect a websocket to host
|
||||
func ConnectWebSocket() error {
|
||||
var origin = "http://localhost/"
|
||||
var url = "ws://localhost:8080/socket"
|
||||
var err error
|
||||
WS, err = xwebsocket.Dial(url, "", origin)
|
||||
return err
|
||||
}
|
||||
|
||||
// CloseWebSocket closes the current websocket connection
|
||||
func CloseWebSocket() error {
|
||||
if WS != nil {
|
||||
return WS.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendMessage broadcast a message to server
|
||||
func SendMessage(serverID, to, method, message string) error {
|
||||
buffer := []byte(message)
|
||||
return SendtBytes(serverID, to, method, buffer)
|
||||
}
|
||||
|
||||
// SendtBytes broadcast a message to server
|
||||
func SendtBytes(serverID, to, method string, message []byte) error {
|
||||
// look https://github.com/kataras/iris/blob/master/websocket/message.go , client.js.go and client.js
|
||||
// to understand the buffer line:
|
||||
buffer := []byte(fmt.Sprintf("%s%v;0;%v;%v;", websocket.DefaultEvtMessageKey, method, serverID, to))
|
||||
buffer = append(buffer, message...)
|
||||
_, err := WS.Write(buffer)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClientLoop connects to websocket server, the keep send and recv dataS
|
||||
func ClientLoop() {
|
||||
for {
|
||||
time.Sleep(time.Second)
|
||||
err := ConnectWebSocket()
|
||||
if err != nil {
|
||||
fmt.Println("failed to connect websocket", err.Error())
|
||||
continue
|
||||
}
|
||||
// time.Sleep(time.Second)
|
||||
err = SendMessage("2", "all", "join", "dummy2")
|
||||
go sendUntilErr(1)
|
||||
recvUntilErr()
|
||||
err = CloseWebSocket()
|
||||
if err != nil {
|
||||
fmt.Println("failed to close websocket", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// server side
|
||||
|
||||
// OnConnect handles incoming websocket connection
|
||||
func OnConnect(c websocket.Connection) {
|
||||
fmt.Println("socket.OnConnect()")
|
||||
c.On("join", func(message string) { OnJoin(message, c) })
|
||||
c.On("objectupdate", func(message string) { OnObjectUpdated(message, c) })
|
||||
// ok works too c.EmitMessage([]byte("dsadsa"))
|
||||
c.OnDisconnect(func() { OnDisconnect(c) })
|
||||
|
||||
}
|
||||
|
||||
// ServerLoop listen and serve websocket requests
|
||||
func ServerLoop() {
|
||||
app := iris.New()
|
||||
|
||||
ws := websocket.New(websocket.Config{})
|
||||
|
||||
// register the server on an endpoint.
|
||||
// see the inline javascript code i the websockets.html, this endpoint is used to connect to the server.
|
||||
app.Get("/socket", ws.Handler())
|
||||
|
||||
ws.OnConnection(OnConnect)
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
|
||||
// OnJoin handles Join broadcast group request
|
||||
func OnJoin(message string, c websocket.Connection) {
|
||||
t := time.Now()
|
||||
c.Join("server2")
|
||||
fmt.Println("OnJoin() time taken:", time.Since(t))
|
||||
}
|
||||
|
||||
// OnObjectUpdated broadcasts to all client an incoming message
|
||||
func OnObjectUpdated(message string, c websocket.Connection) {
|
||||
t := time.Now()
|
||||
s := strings.Split(message, ";")
|
||||
if len(s) != 3 {
|
||||
fmt.Println("OnObjectUpdated() invalid message format:" + message)
|
||||
return
|
||||
}
|
||||
serverID, _, objectID := s[0], s[1], s[2]
|
||||
err := c.To("server"+serverID).Emit("objectupdate", objectID)
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to broacast object")
|
||||
return
|
||||
}
|
||||
fmt.Println(fmt.Sprintf("OnObjectUpdated() message:%v, time taken: %v", message, time.Since(t)))
|
||||
}
|
||||
|
||||
// OnDisconnect clean up things when a client is disconnected
|
||||
func OnDisconnect(c websocket.Connection) {
|
||||
c.Leave("server2")
|
||||
fmt.Println("OnDisconnect(): client disconnected!")
|
||||
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@echo off
|
||||
REM run.bat 30
|
||||
start go run main.go server
|
||||
for /L %%n in (1,1,%1) do start go run main.go client
|
||||
@@ -1,58 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/kataras/iris/websocket"
|
||||
)
|
||||
|
||||
const (
|
||||
url = "ws://localhost:8080/socket"
|
||||
prompt = ">> "
|
||||
)
|
||||
|
||||
/*
|
||||
How to run:
|
||||
Start the server, if it is not already started by executing `go run ../server/main.go`
|
||||
And open two or more terminal windows and start the clients:
|
||||
$ go run main.go
|
||||
>> hi!
|
||||
*/
|
||||
func main() {
|
||||
c, err := websocket.Dial(nil, url, websocket.ConnectionConfig{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c.OnError(func(err error) {
|
||||
fmt.Printf("error: %v", err)
|
||||
})
|
||||
|
||||
c.OnDisconnect(func() {
|
||||
fmt.Println("Server was force-closed[see ../server/main.go#L17] this connection after 20 seconds, therefore I am disconnected.")
|
||||
os.Exit(0)
|
||||
})
|
||||
|
||||
c.On("chat", func(message string) {
|
||||
fmt.Printf("\n%s\n", message)
|
||||
})
|
||||
|
||||
fmt.Println("Start by typing a message to send")
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for {
|
||||
fmt.Print(prompt)
|
||||
if !scanner.Scan() || scanner.Err() != nil {
|
||||
break
|
||||
}
|
||||
msgToSend := scanner.Text()
|
||||
if msgToSend == "exit" {
|
||||
break
|
||||
}
|
||||
|
||||
c.Emit("chat", msgToSend)
|
||||
}
|
||||
|
||||
fmt.Println("Terminated.")
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/websocket"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
ws := websocket.New(websocket.Config{})
|
||||
ws.OnConnection(func(c websocket.Connection) {
|
||||
go func() {
|
||||
<-time.After(20 * time.Second)
|
||||
c.Disconnect()
|
||||
}()
|
||||
|
||||
c.On("chat", func(message string) {
|
||||
c.To(websocket.Broadcast).Emit("chat", c.ID()+": "+message)
|
||||
})
|
||||
|
||||
c.OnDisconnect(func() {
|
||||
fmt.Printf("Connection with ID: %s has been disconnected!\n", c.ID())
|
||||
})
|
||||
})
|
||||
|
||||
app.Get("/socket", ws.Handler())
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
Reference in New Issue
Block a user