Client code:
<body>
<input type=text id="input">
</body>
<script>
var connection = new WebSocket('ws://chat-mmnnww123.c9users.io');
/*AFTER CONNECTION*/
$('#input').change(function(){
connection.send(this.value);
$('#input').val("");
alert("DONE");
});
connection.onmessage = function(e){
alert(e.data);
};
</script>
This code just send message write in the input to the server website.
Server code:
var ws = require("nodejs-websocket");
var server = ws.createServer(function(conn){
console.log("New Connection");
//on text function
conn.on("text", function(str){
/*
I want to send this str to agent.html page
*/
conn.sendText("Message send : " + str.toUpperCase());
});
//closing the connection
conn.on("close", function(){
console.log("connection closed");
});
}).listen(process.env.PORT, process.env.IP);
This is the server code which SHOULD take the value in str and pass it to the agent.html page.
Now all I want is to take that str value and pass it to page agent.html that I haven't created yet. This page will help the agent to see the client message.
It should be instant and without refreshing the page.
Related
I'm trying to use server-side events (SSE) in Javascript and Node.JS to push updates to a web client.
To keep things simple, I have a function which will generate the time every second:
setTimeout(function time() {
sendEvent('time', + new Date);
setTimeout(time, uptimeTimeout);
}, 1000);
The sendEvent function puts together the event in the expected format and sends it to the client.
var clientRes;
var lastMessageId = 0;
function sendEvent(event, message) {
message = JSON.stringify(message);
++lastMessageId;
sendSSE(clientRes, lastMessageId, event, message);
}
The clientRes value comes from the server function to handle the route from the base URL.
app.use('/', function (req, res) {
clientRes = res;
...
}
What I want to achieve at the client UI is a simple page which shows:
> <h1>The current time is {event.data}</h1>
where I derive the current time from the latest message data received from the server.
I have created an index.html file to have the client listen for these server-sent messages:
<!DOCTYPE html>
<html>
<body>
<h1>Getting server updates</h1>
<div id="result"></div>
<script>
if(typeof(EventSource) !== "undefined") {
console.log("Event source is supported");
var source = new EventSource("localhost:3000");
source.onmessage = function(event) {
document.getElementById("result").innerHTML += "=>" + event.data + "<br>";
};
} else {
console.log("Event source not supported");
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
evtSource.addEventListener("time", function(event) {
const newElement = document.createElement("li");
const time = JSON.parse(event.data).time;
console.log("Time listener found time " + time);
newElement.innerHTML = "ping at " + time;
eventList.appendChild(newElement);
});
</script>
</body>
</html>
If I respond to a GET request with this index.html, I don't see any of the time messages.
That is, this server code does not work:
app.use("/", function(request, response) {
response.sendFile(__dirname + "/index.html");
clientRes = response;
});
However if I don't respond with the index.html file and allow the server to push timestamps to the client, they to show up in the browser:
event: time
id: 104
data: 1587943717153
event: time
id: 105
data: 1587943727161
...
Here's is where I'm stuck.
It appears I have successfully gotten the server to push new timestamps every second.
And the browser is seeing them and displaying the text.
But the arrival of the message from the server is not triggering the listener and the message is not being rendered based on the index.html.
Most of the examples I've seen for use of SSE involves a PHP data source. I need for the server to both generate the data and to provide the HTML to display it.
I've been successful in one or the other, but not both at the same time.
I figured out what I was missing.
I did not specify the endpoints correctly.
For the root endpoint, the server code needs to deliver the index.html file.
app.use("/", function(request, response) {
console.log("In root handler");
response.sendFile(__dirname + "/index.html");
});
Index.html contains the script that creates the event source:
var source = new EventSource("http://localhost:3000/time");
But the URL that gets passed in as the input to the EventSource constructor must be a different endpoint (not root). It needs to be the endpoint that generates the timestamps.
So in the server, the handler for the /time endpoint is the one which pushes the data.
app.use('/time', function (req, res) {
res.writeHead(200, {
'content-type': 'text/event-stream',
'cache-control': 'no-cache',
'connection': 'keep-alive'
});
// Save the response
clientRes = res;
});
so, below is a code snippet from my server.js file. When running, and I send a URL with a message, the res.end() causes the view to render a blank page.
When I comment out the res.end() command, the view displays all of the messages, but the browser waits and waits for the signal that the response from the server is complete.
I get that you can use res.end() and put data in the parens, to be transmitted and rendered by the view.
What I expect to happen is that with no args, it will just leave the view alone, but the empty args in the parens is manifesting as an empty view.
How do I indicate that the response is complete without deleting the data on the view?
server.js
var http = require('http'),
url = require('url'),
fs = require('fs');
var messages = ["testing"];
var clients = [];
http.createServer(function(req,res) {
var url_parts = url.parse(req.url);
console.log(url_parts);
if(url_parts.pathname == '/') {
// file serving
fs.readFile('./index.html', function(err, data) {
// console.log(data);
res.end(data);
});
} else if(url_parts.pathname.substr(0,5) == '/poll'){
//polling code
var count = url_parts.pathname.replace(/[^0-9]*/,'');
console.log(count);
if(messages.length > count){
res.end(JSON.stringify({
count: messages.length,
append: messages.slice(count).join("\n")+"\n"
}));
} else {
clients.push(res);
}
} else if(url_parts.pathname.substr(0, 5) == '/msg/') {
// message receiving
var msg = unescape(url_parts.pathname.substr(5));
messages.push(msg);
while(clients.length > 0) {
var client = clients.pop();
client.end(JSON.stringify({
count: messages.length,
append: msg+"\n"
}));
}
// res.end(); //if left in, this renders an empty page, if removed,
// client keeps waiting....
}
}).listen(8080, 'localhost');
console.log('server running!');
index.html
<html>
<head>
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script>
var counter = 0;
var poll = function() {
$.getJSON('/poll/'+counter, function(response) {
counter = response.count;
var elem = $('#output');
elem.text(elem.text() + response.append);
//elem.text(counter);
poll();
});
}
poll();
</script>
</head>
<body>
<textarea id="output" style="width: 90%; height: 90%;">
</textarea>
</body>
</html>
I have looked in the docs, but I don't see anything specific about using .end() method with empty args to signify and end without passing data to be rendered. I have googled this, but I don't have an answer yet.
Do a res.json({success:"true"}) instead. The reason being is because res.end inherently thinks the client was sent a view prior to the stream being closed. With res.json() you can send any generic data, without an implied view being expected as well as close out the stream on client and server side.
Move res.end() inside while loop
while (clients.length > 0) {
var client = clients.pop();
client.end(JSON.stringify({
count : messages.length,
append : msg + "\n"
}));
if(!clients.length) {
res.end();
}
}
My understand of your problem is:
You have an HTML page (index.html), which has a textarea displaying all messages submitted by user. After one message is received and displayed, it will send the request for next message immediately (/poll/<n>).
To accept user's input for latest message, you open an API (/msg/<message>). When an HTTP request is sent to this API, server will extract the message, and return this message to /poll/<n> sent in step 1.
However, as HTML page (index.html) and the request to /msg/<message> happens in the same browser window, you can't let the http handler of /msg/<message> in node.js invoke res.end(), because in that case, the browser window will render the HTTP response of /msg/<message> request (blank page). Actually, you can't make the res return 200 OK, whatever data it returns. You can't make res fail the /msg/<message> request either (using req.destroy()), because in that case the browser window will render a failure/broken page, which is worse.
Unfortunately, you can't make res of /msg/<message> in node.js keep pending either. Although it will update index.html, the browser window will keep waiting...
The root cause of your problem is: browser window resource conflict between index.html and /msg/<message> response -- as long as /msg/<message> request is sent by using index.html window's URL bar, whenever its response is sent back, the window content (index.html) will be cleaned.
One solution is: using Ajax to send /msg/<message>. In this way, there would be no conflict for window resource. Example code is listed below:
<body>
<textarea id="output" style="width: 90%; height: 90%;">
</textarea>
<div>
<input type="text" id="msg">
<button type="button" onclick="submitMsg()">Submit</button>
</div>
</body>
window.submitMsg = function() {
var msg = $('#msg').val();
$.getJSON('/msg/' + msg, function(res) {
$('#msg').val('');
console.log('message sent.');
});
}
EDIT:
Another simpler solution is: open index.html in one browser window, and open /msg/<message> in another one (use res.end('message received successfully') to indicate message receiving result).
we have a problem regarding Websocket Communication with a Windows-Client.
As minimal setup we use the python3 autobahn websocket ping-pong example.
The server is from (taken from https://github.com/crossbario/autobahn-python/blob/master/examples/asyncio/websocket/echo/server.py). The only modification is that the server sends a message to the client when the connection is opened.
The client is also taken form the autobahn pingpong example but modified in two ways. It accepts connections from a remote server and it does not send a message to the server but it expects one.
This does work well on all browsers on my Linux Machine, but it does not work from a Windows-Client. But if I send a message from the client as soon as the connection is opened, then the client is also able to receive the messages.
Here is the pyhton3 server:
from autobahn.asyncio.websocket import WebSocketServerProtocol, \
WebSocketServerFactory
class MyServerProtocol(WebSocketServerProtocol):
def onConnect(self, req.uest):
print("Client connecting: {0}".format(request.peer))
def onOpen(self):
print("WebSocket connection open.")
self.sendMessage('server hello'.encode('utf8'))
def onMessage(self, payload, isBinary):
if isBinary:
print("Binary message received: {0} bytes".format(len(payload)))
else:
print("Text message received: {0}".format(payload.decode('utf8')))
# echo back message verbatim
self.sendMessage(payload, isBinary)
def onClose(self, wasClean, code, reason):
print("WebSocket connection closed: {0}".format(reason))
if __name__ == '__main__':
import asyncio
factory = WebSocketServerFactory(u"ws://0.0.0.0:9000", debug=False)
factory.protocol = MyServerProtocol
loop = asyncio.get_event_loop()
coro = loop.create_server(factory, '0.0.0.0', 9000)
server = loop.run_until_complete(coro)
try:
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
server.close()
loop.close()
Here is the Websocket Client:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var socket = null;
var isopen = false;
window.onload = function() {
socket = new WebSocket("ws://" + location.hostname + ":9000");
socket.onopen = function() {
console.log("Connected!");
isopen = true;
//if I do this, then it works
//socket.send('hello from client'.encode('utf-8'))
}
socket.onmessage = function(e) {
console.log("Text message received: " + e.data);
}
socket.onclose = function(e) {
console.log("Connection closed.");
socket = null;
isopen = false;
}
};
</script>
</head>
<body>
</body>
</html>
Has anybody an idea what I am missing? I want to open a connection from server to client without sending a message from the client first.
okay so I am trying to make my html/javascript communicate with my nodes.js server.
what I am trying to do is post data to my nodes.js server then echo the result back into my html/javascript.
the communication is working as in node I have console.log for the postdata and I can see it via the running node console .
problem is I need javascript to wait for the node.js function to complete and then echo me the text produced by node back to the html page.
I just cannot get this to work heres my html/javascript
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<html><head><title>Welcome To ....</title>
<script type="text/javascript">
function textareaToArray(t){
return t.value.split(/[\n\r]+/);
}
function showArray(msg){
for(i = 0; i < msg.length; i++) {
// something per item
var data = {}; //your own data
$.post("http://192.168.2.109:8111" + "?" + $.param({name: msg[i]}), data);
}
// the old code
document.getElementById("message").innerHTML = msg.join("
");
}
</script>
</head>
<body>
<h1> WELCOME TO .... </h1>
<form>
<textarea rows="10" cols="60" name="alpha"></textarea>
<br>
<input type="button" value="show array" onclick="showArray(textareaToArray(this.form.alpha ))">
</form>
<br>
<textarea id="message" rows="6" cols="60" name="message"></textarea>
</body></html>
and here is my node script
var url = require('url')
var http = require('http')
var server = http.createServer(function (request, response) {
var queryData = url.parse(request.url, true).query;
response.writeHead(200, {"Content-Type": "text/plain"});
if (queryData.name) {
// user told us their name in the GET request, ex: http://host:8000/?name=Tom
var basevalue = queryData.name;
var value = basevalue.split (":");
console.log(value[0]);
console.log(value[1]);
var exec = require('child_process').exec;
exec ("casperjs test.js " + value[0] + " " + value[1] + '\n',function(err, stdout, stderr) {
response.end(stdout);
});
} else {
response.end("Contact Admin - Not Working\n");
}
});
// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8111);
can someone please show me and help me fix this thanks
IT is simple.
you need to call the alert in callback. so it will be executed when post request completed.
change your few lines as following
$.post("http://192.168.2.109:8111" + "?" + $.param({name: msg[i]}), function(data){
// data contains your response from server. now you can handle it as you want
});
I accessed my client page using this link
http://XX.XX.XX.XX/project/client.php
.It has few lines of javascript and html but its not working at all . But when i access my client page using this link
http://localhost/project/client.php
, it works. I know something i should change in javascript code but i dont know what . So please tell me . Here is my client code :
<html>
<head>
<style>
#chatlog {width:440px; height:200px; border:1px solid;overflow:auto;}
#userslog {width:440px; height:200px; border:1px solid;overflow:auto;}
#msg {width:330px; height:100px;}
</style>
<script>
function initialize(){
var host = "ws://localhost:12345/project/server3z.php";
try{
socket = new WebSocket(host);
chatlog('WebSocket - status '+socket.readyState);
socket.onopen = function(event){chatlog("WebSocket status "+this.readyState); };
socket.onmessage = function(event){ chatlog(event.data); };
socket.onclose = function(){ chatlog("WebSocket status "+this.readyState); };
socket.onerror = function(event){chatlog("Error :"+event.data); };
}
catch(err){ chatlog(err); }
}
function send()
{
var chat;
chat= document.getElementById("msg").value;
if(!chat){ alert("Message can not be empty"); return; }
try{ socket.send(chat); chatlog('Sent: '+chat); } catch(err){ log(err); }
document.getElementById("msg").value = "";
}
function quit(){
chatlog("closed!");
socket.close();
chatlog("WebSocket status "+socket.readyState);
}
function chatlog(msg)
{
var match=msg.match(/10101010101010/g);
if(match)
{
var msg=msg.split("10101010101010");
document.getElementById("userslog").innerHTML+="<br>"+msg[0];
}
else
{
document.getElementById("chatlog").innerHTML+="<br>"+msg;
}
}
function onkey(event){ if(event.keyCode==13){ send(); } }
</script>
</head>
<body onload="initialize()">
<center>
<div id="chatlog"></div>
<input id="msg" type="textbox" onkeypress="onkey(event)"/>
<button onclick="send()">Send</button>
<button onclick="quit()">Stop</button>
<div id="userslog"></div>
</center>
</body>
</html>
Don't hard-code the host to localhost, use location.hostname instead:
var host = "ws://" + location.hostname + ":12345/project/server3z.php";
You are using WebSocket are you sure that your browser in the other PC it's supports HTML5 and WebsoCKET?
WebSocket was introduced early
this line i sthe problem var host = "ws://localhost:12345/project/server3z.php";
localhost by default means your local machine. so when you access it from you local machine it maps to the correct machine but when you access it from a remote server it just searches that server because now the localhost is changed
In your code you have a hardcoded reference to a url on your local host:
var host = "ws://localhost:12345/project/server3z.php";
If you want to access it from another computer, you'll need to replace that with a domain or ip address that the remote client can resolve.
thanks for answer !! :)
madthew was right . I was using IEwhich does not support websocket. It is working in my mozila now.