I am trying to learn about websocket functionality supported by Opera browser. I got some sample code from web.
Is it possible to connect to a simple c echo server (not using web server) serving on some port (say 9999) from Opera 12.x browser using websockets? I tried this but is not working. I am getting disconnected error in browser with ERROR: undefined. At Linux echo server side, it is getting a connect request, accepting it, but not able to read any data.
I am loading the test page locally not from any web server.
If simple echo server is not sufficient, is it possible to enhance the simple echo server to return HTTP response and make it work. Basically I am trying to use websockets interfaces from browser to connect to a server without using any web server.
Thanks,
raj
websocket client (Copied from http://www.websocket.org/echo.html)
<!DOCTYPE html>
<meta charset="utf-8" />
<script language="javascript" type="text/javascript">
var wsUri = "ws://192.168.100.2:9999/";
var output;
function init()
{
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket()
{
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
}
function onOpen(evt)
{
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt)
{
writeToScreen("DISCONNECTED");
}
function onMessage(evt)
{
writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>');
websocket.close();
}
function onError(evt)
{
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function doSend(message)
{
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message)
{
var pre = document.createElement("p");
pre.style.wordWrap = "break-word";
pre.innerHTML = message;
output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<div id="output"></div>
</html>
Echo Server(copied from http://www.cs.utah.edu/~swalton/listings/sockets/programs/part2/chap6/simple-server.c)
.
.
#define MY_PORT 9999
#define MAXBUF 1024
int main(int Count, char *Strings[])
{ int sockfd;
struct sockaddr_in self;
char buffer[MAXBUF];
/*---Create streaming socket---*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
perror("Socket");
exit(errno);
}
/*---Initialize address/port structure---*/
bzero(&self, sizeof(self));
self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = INADDR_ANY;
/*---Assign a port number to the socket---*/
if ( bind(sockfd, (struct sockaddr*)&self, sizeof(self)) != 0 )
{
perror("socket--bind");
exit(errno);
}
/*---Make it a "listening socket"---*/
if ( listen(sockfd, 20) != 0 )
{
perror("socket--listen");
exit(errno);
}
/*---Forever... ---*/
while (1)
{ int clientfd;
struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);
/*---accept a connection (creating a data pipe)---*/
clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);
printf("%s:%d connected\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
printf("Received %d\n", recv(clientfd, buffer, MAXBUF, 0));
printf("Date %s\n\n", buffer);
/*---Echo back anything sent---*/
send(clientfd, buffer, recv(clientfd, buffer, MAXBUF, 0), 0);
/*---Close data connection---*/
close(clientfd);
}
.
.
.
The WebSocket protocol is not a raw TCP socket connection. You're server must also support the WebSocket protocol.
There is a online WebSockets echo service at http://www.websocket.org/echo.html
If you really want to connect from WebSockets to a raw socket server you can use websockify to bridge between the two. Disclaimer: I made websockify.
Related
I'm trying to post a (large) json file that's stored in the SPIFFS (LittleFS- of an arduino.
I first of all, fetch the JSON from a local IP address, which can change or is dynamic. Then, that json file gets stored in the internal flash of my ESP32 and sent over to our servers.
The goal is to have an ESP32 act as a bridge for local addresses.
For example:
Locally, there is a server running, that server is never accessible from outside of a network, but it is from within. We place an ESP32 in that network, to be able to read out data from the internal device and pass them through to our servers, for further processing.
The current code I have is the following;
HTTPClient http;
if (LittleFS.exists("/downloadedFile.json")) {
LittleFS.remove("/downloadedFile.json");
}
File f = LittleFS.open("/downloadedFile.json", "w", true);
if (f) {
String url;
// Build the URL...
if (username != "" && password != "") {
url = "http://" + username + ":" + password + "#" + ip + ":" + String(port) + "/data/file.json";
} else {
url = "http://" + ip + ":" + String(port) + "/data/file.json";
}
http.begin(url);
int httpCode = http.GET();
if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK) {
http.writeToStream(&f);
}
} else {
// failed.
}
f.close();
} else {
// Unable to open file
}
http.end();
if (LittleFS.exists("/downloadedFile.json")) {
File f = LittleFS.open("/downloadedFile.json", "r");
if (f) {
WiFiClienSecure client;
client.setInsecure(); // test
if (!client.connect("my.somain.com", 443)) {
// failed to connect. (never gets in here)
return;
}
client.println("POST /path/to/my/endpoint HTTP/1.1");
client.println("Host: my.somain.com");
client.println("Content-Type: application/json");
client.println("Connection: keep-alive");
client.println("Content-Length: " + String(f.size()));
client.println();
// Build the body
int len = 0;
int total = 0;
uint8_t buf[1025] = {};
size_t _len = 256;
do {
len = f.read(buf, _len);
client.write(buf, len);
total += len;
} while (len > 0);
client.println(); // end line
client.stop();
f.close();
}
}
Downloading the file always works, except for sometimes random crashing the whole system. But that's the least of my concerns.
Locally I got it working to download and re-upload the file. Struggle is when I try to achieve the same result on the server (which uses https)
Only difference is this;
Server
Local
WiFiClienSecure client;
WiFiClient client;
client.setInsecure();
client.connect("my.somain.com", 443)
client.connect("IP", 80)
The main problem is that it doesn't work on the server and that it works really unstable. the file size (when I do f.size()) is 310831.
Any help and thoughts on getting this stable is appriciated!
When I tried using Ocelot as a WebSocket proxy, I could not get it working for wss. I was able to see it working for ws.
When we are trying to proxy for wss getting decrypt operation failed while reading the bytes at the server side socket. With plan ws I am able to get this working.
Ocelot config as follows, where wss proxying is specified:
{
"Routes": [
{
"DownstreamPathTemplate": "/ws",
"UpstreamPathTemplate": "/{anything}",
"DownstreamScheme": "wss",
"DownstreamHostAndPorts": [
{
"Host": "127.0.0.1",
"Port": 8080
}
]
}
]
}
Websocket Server code which listens on port 8080:
using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
class Server
{
public static void Main()
{
string ip = "127.0.0.1";
int port = 8080;
var server = new TcpListener(IPAddress.Parse(ip), port);
server.Start();
Console.WriteLine("Server has started on {0}:{1}, Waiting for a connection...", ip, port);
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("A client connected.");
byte[] pfxData = File.ReadAllBytes(#"C:\Users\e409316\Desktop\test.pfx");
var cert = new X509Certificate2(pfxData, "Password1", X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.Exportable);
Stream sourceTcpStream = new SslStream(client.GetStream(), false);
(sourceTcpStream as SslStream).AuthenticateAsServer(
cert,
false,
SslProtocols.Tls12, true);
Stream stream = sourceTcpStream;//client.GetStream();
//Stream stream = client.GetStream();
// enter to an infinite cycle to be able to handle every change in stream
while (true)
{
//while (!stream.DataAvailable) ;
while (client.Available < 3) ; // match against "get"
byte[] bytes = new byte[client.Available];
stream.Read(bytes, 0, client.Available);
string s = Encoding.UTF8.GetString(bytes);
if (Regex.IsMatch(s, "^GET", RegexOptions.IgnoreCase))
{
Console.WriteLine("=====Handshaking from client=====\n{0}", s);
// 1. Obtain the value of the "Sec-WebSocket-Key" request header without any leading or trailing whitespace
// 2. Concatenate it with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" (a special GUID specified by RFC 6455)
// 3. Compute SHA-1 and Base64 hash of the new value
// 4. Write the hash back as the value of "Sec-WebSocket-Accept" response header in an HTTP response
string swk = Regex.Match(s, "Sec-WebSocket-Key: (.*)").Groups[1].Value.Trim();
string swka = swk + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
byte[] swkaSha1 = System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(swka));
string swkaSha1Base64 = Convert.ToBase64String(swkaSha1);
// HTTP/1.1 defines the sequence CR LF as the end-of-line marker
byte[] response = Encoding.UTF8.GetBytes(
"HTTP/1.1 101 Switching Protocols\r\n" +
"Connection: Upgrade\r\n" +
"Upgrade: websocket\r\n" +
"Sec-WebSocket-Accept: " + swkaSha1Base64 + "\r\n\r\n");
stream.Write(response, 0, response.Length);
}
else
{
bool fin = (bytes[0] & 0b10000000) != 0,
mask = (bytes[1] & 0b10000000) != 0; // must be true, "All messages from the client to the server have this bit set"
int opcode = bytes[0] & 0b00001111, // expecting 1 - text message
msglen = bytes[1] - 128, // & 0111 1111
offset = 2;
if (msglen == 126)
{
// was ToUInt16(bytes, offset) but the result is incorrect
msglen = BitConverter.ToUInt16(new byte[] { bytes[3], bytes[2] }, 0);
offset = 4;
}
else if (msglen == 127)
{
Console.WriteLine("TODO: msglen == 127, needs qword to store msglen");
// i don't really know the byte order, please edit this
// msglen = BitConverter.ToUInt64(new byte[] { bytes[5], bytes[4], bytes[3], bytes[2], bytes[9], bytes[8], bytes[7], bytes[6] }, 0);
// offset = 10;
}
if (msglen == 0)
Console.WriteLine("msglen == 0");
else if (mask)
{
byte[] decoded = new byte[msglen];
byte[] masks = new byte[4] { bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3] };
offset += 4;
for (int i = 0; i < msglen; ++i)
decoded[i] = (byte)(bytes[offset + i] ^ masks[i % 4]);
string text = Encoding.UTF8.GetString(decoded);
Console.WriteLine("{0}", text);
}
else
Console.WriteLine("mask bit not set");
Console.WriteLine();
}
}
}
}
Websocket Client code which tries to connect to ocelot endpoint (upstream endpoint on port 5000):
ClientWebSocket client = new ClientWebSocket();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
client.ConnectAsync(new Uri("wss://127.0.0.1:5000/"), CancellationToken.None).Wait();
var buffer = new byte[]{1,2,3};
client.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true,CancellationToken.None);
Error: The decryption operation failed
Found it to be a certificate validity issue. Solved it by using a trusted certificate.
I'm trying to create an rpc program to communicate hosts located on different networks and chose Router-Dealer configuration of NetMQ provided here: http://netmq.readthedocs.io/en/latest/router-dealer/#router-dealer
But the problem is that router always selects a random dealer when routing a message to backend.
Code which I used :
using (var frontend = new RouterSocket(string.Format("#tcp://{0}:{1}", "127.0.0.1", "5556")))//"#tcp://10.0.2.218:5559"
using (var backend = new DealerSocket(string.Format("#tcp://{0}:{1}", "127.0.0.1", "5557")))//"#tcp://10.0.2.218:5560"
{
// Handler for messages coming in to the frontend
frontend.ReceiveReady += (s, e) =>
{
Console.WriteLine("message arrived on frontEnd");
NetMQMessage msg = e.Socket.ReceiveMultipartMessage();
string clientAddress = msg[0].ConvertToString();
Console.WriteLine("Sending to :" + clientAddress);
//TODO: Make routing here
backend.SendMultipartMessage(msg); // Relay this message to the backend };
// Handler for messages coming in to the backend
backend.ReceiveReady += (s, e) =>
{
Console.WriteLine("message arrived on backend");
var msg = e.Socket.ReceiveMultipartMessage();
frontend.SendMultipartMessage(msg); // Relay this message to the frontend
};
using (var poller = new NetMQPoller { backend, frontend })
{
// Listen out for events on both sockets and raise events when messages come in
poller.Run();
}
}
Code for Client:
using (var client = new RequestSocket(">tcp://" + "127.0.0.1" + ":5556"))
{
var messageBytes = UTF8Encoding.UTF8.GetBytes("Hello");
var messageToServer = new NetMQMessage();
//messageToServer.AppendEmptyFrame();
messageToServer.Append("Server2");
messageToServer.Append(messageBytes);
WriteToConsoleVoid("======================================");
WriteToConsoleVoid(" OUTGOING MESSAGE TO SERVER ");
WriteToConsoleVoid("======================================");
//PrintFrames("Client Sending", messageToServer);
client.SendMultipartMessage(messageToServer);
NetMQMessage serverMessage = client.ReceiveMultipartMessage();
WriteToConsoleVoid("======================================");
WriteToConsoleVoid(" INCOMING MESSAGE FROM SERVER");
WriteToConsoleVoid("======================================");
//PrintFrames("Server receiving", clientMessage);
byte[] rpcByteArray = null;
if (serverMessage.FrameCount == 3)
{
var clientAddress = serverMessage[0];
rpcByteArray = serverMessage[2].ToByteArray();
}
WriteToConsoleVoid("======================================");
Console.ReadLine();
}
Code for Dealer:
using (var server = new ResponseSocket())
{
server.Options.Identity = UTF8Encoding.UTF8.GetBytes(confItem.ResponseServerID);
Console.WriteLine("Server ID:" + confItem.ResponseServerID);
server.Connect(string.Format("tcp://{0}:{1}", "127.0.0.1", "5557"));
using (var poller = new NetMQPoller { server })
{
server.ReceiveReady += (s, a) =>
{
byte[] response = null;
NetMQMessage serverMessage = null;
try
{
serverMessage = a.Socket.ReceiveMultipartMessage();
}
catch (Exception ex)
{
Console.WriteLine("Exception on ReceiveMultipartMessage : " + ex.ToString());
//continue;
}
byte[] eaBody = null;
string clientAddress = "";
if (serverMessage.FrameCount == 2)
{
clientAddress = serverMessage[0].ConvertToString();
Console.WriteLine("ClientAddress:" + clientAddress);
eaBody = serverMessage[1].ToByteArray();
Console.WriteLine("Received message from remote computer: {0} bytes , CurrentID : {1}", eaBody.Length, confItem.ResponseServerID);
}
else
{
Console.WriteLine("Received message from remote computer: CurrentID : {0}", confItem.ResponseServerID);
}
};
poller.Run();
}
}
Is it possible to choose a specific backend on frontend.ReceiveReady?
Thanks!
Your backend should be router as well. You need the worker to register or you need to know all the available workers and their identity. When send on the backend push the worker identity at the beginning of the server.
Take a look at the Majordomo example in the zeromq guide:
http://zguide.zeromq.org/page:all#toc72
http://zguide.zeromq.org/page:all#toc98
if i run my code in mozilla firefox after i click scan in UI select source window is opened and then it crashed.
bt the same code if i run on chrome it scan the image in the scanner after that if i click the scan on the new window it scan properly and crashed during file transfer and chrome tell a error message "a plugin (shockwave flash) isnt responding "
what may be the prob
function onScan(no_of_pages)
{
if (DWObject)
{
if (DWObject.SourceCount > 0)
{
DWObject.SelectSource();
DWObject.IfDisableSourceAfterAcquire = true;
DWObject.AcquireImage();
DWObject.MaxImagesInBuffer = no_of_pages;
}
else
alert("No TWAIN compatible drivers detected.");
}
}
function Dynamsoft_ChangeConfig(config){
config.onPrintMsg = g_DWT_PrintMsg;
}
function g_DWT_PrintMsg(strMessage) {
alert(strMessage);
}
function OnPostTransferCallback()
{
try{
if(DWObject.MaxImagesInBuffer == DWObject.HowManyImagesInBuffer)
{
DWObject.CloseSource();
sendToFlash() ;
}else
{
//TBD
}
}catch(err){
alert(err.message);
}
}
//Call back function from the
function sendToFlash()
{
try{
var flashMovie = window.document.flashContent;
flashMovie.sendToActionScript(DWObject.HowManyImagesInBuffer);
//document.getElementById("ICANSWF").sendToActionScript();
}catch(err){
alert(err.message);
}
}
//call from flash for uploading documents
function onUpload(serialNo)
{
//alert("upload the file");
var imageArr = new Array();
try{
var imageName;
var uploadPage;
var serverHost;
var CurrentPathName = unescape(location.pathname); // get current PathName in plain ASCII
var CurrentPath = CurrentPathName.substring(0, CurrentPathName.lastIndexOf("/") + 1);
uploadPage = CurrentPath+"TempUpload.php";
//uploadPage = CurrentPath+"UploadDocument.php";
//serverHost = "blabla";
//window.Plugin.HTTPPort =1451;
serverHost = "our host";
DWObject.HTTPPort = 80;
DWObject.IfSSL = false;
//alert(Plugin.HowManyImagesInBuffer);
for(var i=0;i < DWObject.HowManyImagesInBuffer;i++)
{
imageName = serialNo+"_"+(i+1)+".png";
DWObject.HTTPUploadThroughPost(serverHost,i,uploadPage,imageName);
if (DWObject.ErrorCode == 0)
{
//alert(imageName);
imageArr.push({"label":imageName,"source":"http://"+serverHost+":"+DWObject.HTTPPort+"/icanindonesia/AppData/Temp/"+imageName}); //Push image name and location in an array
}
else //succeded
{
alert(DWObject.ErrorString);
//imageArr[i] = imageName;
//alert(imageArr[i]);
}
}
}catch(err){
//alert("onUpload");
alert(err.message);
}
console.log(imageArr);
return imageArr;
}
function startDownload(url)
{
//var url='.zip';
window.open(url,'Download');
}
function openDocument(url){
window.open(url, '_blank',"ican image viewer");
}
#priya, this is Rachel from Dynamsoft.Thanks for using our Dynamic Web TWAIN SDK. Which version of Firefox and Chrome are you using? We now also have newer version of Dynamic Web TWAIN which you may try. Please contact our support team to get better help.
I tried to make an example of simple socket server.
Build and run successfully. However it doesn't work well.
Client couldn't connect to this server.
How to solve this problem? I need your help, thanks.
import Foundation
let BUFF_SIZE = 1024
func initStruct<S>() -> S {
let struct_pointer = UnsafePointer<S>.alloc(1)
let struct_memory = struct_pointer.memory
struct_pointer.destroy()
return struct_memory
}
func sockaddr_cast(p: ConstUnsafePointer<sockaddr_in>) -> UnsafePointer<sockaddr> {
return UnsafePointer<sockaddr>(p)
}
func socklen_t_cast(p: UnsafePointer<Int>) -> UnsafePointer<socklen_t> {
return UnsafePointer<socklen_t>(p)
}
var server_socket: Int32
var client_socket: Int32
var server_addr_size: Int
var client_addr_size: Int
var server_addr: sockaddr_in = initStruct()
var client_addr: sockaddr_in = initStruct()
var buff_rcv: Array<CChar> = []
var buff_snd: String
server_socket = socket(PF_INET, SOCK_STREAM, 0);
if server_socket == -1
{
println("[Fail] Create Server Socket")
exit(1)
}
else
{
println("[Success] Created Server Socket")
}
server_addr_size = sizeof(server_addr.dynamicType)
memset(&server_addr, 0, UInt(server_addr_size));
server_addr.sin_family = sa_family_t(AF_INET)
server_addr.sin_port = 4000
server_addr.sin_addr.s_addr = UInt32(0x00000000) // INADDR_ANY = (u_int32_t)0x00000000 ----- <netinet/in.h>
let bind_server = bind(server_socket, sockaddr_cast(&server_addr), socklen_t(server_addr_size))
if bind_server == -1
{
println("[Fail] Bind Port");
exit(1);
}
else
{
println("[Success] Binded Port");
}
if listen(server_socket, 5) == -1
{
println("[Fail] Listen");
exit(1);
}
else
{
println("[Success] Listening : \(server_addr.sin_port) Port ...");
}
var n = 0
while n < 1
{
client_addr_size = sizeof(client_addr.dynamicType)
client_socket = accept(server_socket, sockaddr_cast(&client_addr), socklen_t_cast(&client_addr_size))
if client_socket == -1
{
println("[Fail] Accept Client Connection");
exit(1);
}
else
{
println("[Success] Accepted Client : \(inet_ntoa(client_addr.sin_addr)) : \(client_addr.sin_port)");
}
read(client_socket, &buff_rcv, UInt(BUFF_SIZE))
println("[Success] Received : \(buff_rcv)")
buff_snd = "\(strlen(buff_rcv)) : \(buff_rcv)"
write(client_socket, &buff_snd, strlen(buff_snd) + 1)
close(client_socket)
}
The port number in the socket address must be in big-endian byte order:
server_addr.sin_port = UInt16(4000).bigEndian
So your program actually listens on port 40975 (hex 0xA00F) and not
on port 4000 (hex 0x0FA0).
Another problem is here:
var buff_rcv: Array<CChar> = []
// ...
read(client_socket, &buff_rcv, UInt(BUFF_SIZE))
Your buffer is an empty array, but recv() expects a buffer of size BUFF_SIZE.
The behaviour is undefined. To get a buffer of the required size, use
var buff_rcv = [CChar](count:BUFF_SIZE, repeatedValue:0)
// ...
read(client_socket, &buff_rcv, UInt(buff_rcv.count))
Remark: Here you cast the address of an Int to the address of an socklen_t
and pass that to the accept() function:
client_socket = accept(server_socket, sockaddr_cast(&client_addr), socklen_t_cast(&client_addr_size))
That is not safe. If Int and socklen_t have different sizes then the behaviour
will be undefined. You should declare server_addr_size and client_addr_size
as socklen_t and remove the socklen_t_cast() function:
client_socket = accept(server_socket, sockaddr_cast(&client_addr), &client_addr_size)
As Martin R commented before, the write command shouldn't be using the swift string as that. Something like this will work properly:
write(client_socket, buff_snd.cStringUsingEncoding(NSUTF8StringEncoding)!, countElements(buff_snd) + 1)