in JavaScript i call local windows TCPClient service (c#)
var url = 'wss://127.0.0.1:6372';
var oWebSocket = new WebSocket(url); // error
in server
serverCertificate = new X509Certificate2(certificate, "pwd");
TcpListener listener = new TcpListener(IPAddress.Parse(ip), port);
listener.Start();
while (true)
{
Console.WriteLine("Waiting for a client to connect...");
TcpClient client = listener.AcceptTcpClient();
ProcessClientS(client);
}
static void ProcessClientS(TcpClient client)
{
SslStream sslStream = new SslStream(client.GetStream(), false);
// Authenticate the server but don't require the client to authenticate.
try
{
sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls12, true); //error line
in server side I get "A call to SSPI failed, see inner exception." and "An unknown error occurred while processing the certificate"
in client side I get " Error in connection establishment: net::ERR_CERT_COMMON_NAME_INVALID"
How can I pass local certificate to my server
About 4 hours of research...here we go.
I have a C# program that sends and listens for anything coming in a specific Socket. Using the sockets, C# can send stuff to it and can receive from it just fine. Now, going to my JavaScript file, I'm using the WebSocket interface to communicate with C#, but doesn't work (usually times out after a couple of minutes). When the Socket is online, the JavaScript code will take up to about 4 minutes then throw an error saying "WebSocket opening handshake timed out". The thing is I know that it can find because, when the port of the ip doesn't exist the JavaScript file throws an error in the next couple seconds.
Things I've done:
Turn off all firewalls, use both ws and wss at the beginning of the ip and port (ex: wss://xxx.xxx.x.xx:11111), change the port, change the ip to a valid ip still reachable, research for 4 hours.
C#:
IPHostEntry ipHost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddr = IPAddress.Parse("ip");
IPEndPoint localEndPoint = new IPEndPoint(ipAddr, 11111);
Socket listener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
while (true)
{
Console.WriteLine("Waiting connection...");
Socket clientSocket = listener.Accept();
byte[] bytes = new Byte[1024];
string data = null;
while (true)
{
int numByte = clientSocket.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, numByte);
if (data.IndexOf("<EOF>") > -1)
{
break;
}
}
Console.WriteLine("Text received -> {0} ", data);
byte[] message = Encoding.ASCII.GetBytes("Test Server");
clientSocket.Send(message);
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
JavaScript:
socket = new WebSocket("wss://ip:11111");
socket.onopen = function()
{
alert("Connected!");
}
socket.onerror = function()
{
alert("Connection Failed");
}
The ip is local
Long story short, C# can communicate with itself and JavaScript can find it but can't communicate with it.
Properly complete a handshake. (Or use a library / connection type that does.)
The WebSocket protocol (as original defined in RFC6455 - The WebSocket Protocol) does not open a plain unrestricted socket, in part for security reasons.
Since the handshake is not complete, the client WS request will timeout as the HTTP “Upgrade” response is never received. Until the handshake is complete, the WS will not be active over the underlying TCP connection.
Initiating a WebSocket connection (“the handshake”) is defined in section 4 of the RFC. It is also discussed in How JavaScript works: Deep dive into WebSockets and HTTP/2 with SSE + how to pick the right path.
The client establishes a WebSocket connection through a process known as the WebSocket handshake. This process starts with the client sending a regular HTTP request to the server. An Upgrade header is included in this request which informs the server that the client wishes to establish a WebSocket connection.
..
Now that [after] the handshake is complete the initial HTTP connection is replaced by a WebSocket connection that uses the same underlying TCP/IP connection. At this point, either party can start sending data.
I installed Mosquitto on a VM referring the following link
https://gist.github.com/smoofit/dafa493aec8d41ea057370dbfde3f3fc
The Mosquitto Broker is Up and shows
1565283316: mosquitto version 1.4.12 (build date 2019-08-08 15:47:50+0000) starting
1565283316: Config loaded from /etc/mosquitto/mosquitto.conf.
1565283316: Opening websockets listen socket on port 9001.
1565283316: Opening ipv4 listen socket on port 1883.
1565283316: Opening ipv6 listen socket on port 1883.
But not able to connect from the Paho Javascript Client
I tried installing the newest version of Mqtt with mosquitto. I allowed 9001 and 1883 ports on firewall but not able to connect.
Here is my JS Client Code.
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript"></script>
</head>
<script>
// Create a client instance
client = new Paho.MQTT.Client(IPAddress, Number(9001), "clientId");
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
// connect the client
client.connect({onSuccess:onConnect});
// called when the client connects
function onConnect() {
// Once a connection has been made, make a subscription and send a message.
console.log("onConnect");
client.subscribe("World");
message = new Paho.MQTT.Message("Hello");
message.destinationName = "World";
client.send(message);
}
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:"+responseObject.errorMessage);
}
}
// called when a message arrives
function onMessageArrived(message) {
console.log("onMessageArrived:"+message.payloadString);
}
</script>
</html>
Please help me fix this. Thanks in advance
I am building a system using an ESP8266/NodeMcu module (similar to an Arduino, just with networking capabilities) and a NodeJs server running on the local network.
To discover the IP address of the server, I'm trying to use UDP broadcasting on the NodeMcu module. The idea is to send out a message on the local broadcasting IP (e.g. 192.168.1.255). The server then receives the message and sends a response, confirming that it is the server. This way, the NodeMcu knows the direct address of the server for further communication.
The problem is, that the server is completely flooding itself with the same message whenever it receives the first message from the NodeMcu, while the NodeMcu actually sends out a message only once a second.
It looks like this on the NodeMcu side:
[UDP] Sending UDP Broadcast on IP: 192.168.43.255, Port: 8080, Message: ESP8266 UDP Server Discovery Broadcast
The server outputs something like this, many times a second:
[10:33:07] 127.0.0.1:8080 # service discovery : ESP8266 UDP Server Discovery Broadcast
[10:33:07] 127.0.0.1:8080 # service discovery : ESP8266 UDP Server Discovery Broadcast
[10:33:07] 127.0.0.1:8080 # service discovery : ESP8266 UDP Server Discovery Broadcast
It doesn't make sense that it's receiving that many messages, especially because it's apparently coming from 127.0.0.1 and not the IP of the NodeMcu. It also doesn't send out any response.
I tried to receive the broadcast on my phone with a UDP Monitor app, an application called Packet Sender and the Linux Terminal. It all worked fine, and sending a manual response triggered the acknowledgement on the NodeMcu.
So I'm thinking there has to be some kind of error with the server, or with the network I'm using. The server is running on Linux on my computer, while I'm hosting the network via a hotspot on my phone (my real WiFi network blocked UDP broadcasting). The Linux firewall is turned off.
I'm no expert in JavaScript or NodeJs by any means and the server was written by someone I'm working with, but he has no clue either. Anyway, this is the important part on the server:
client.on('listening', function () {
var address = client.address();
debugMessage(
format('Service discovery running on port %s', config.port)
);
client.setBroadcast(true);
});
client.on('message', function (message, rinfo) {
debugMessage(
format('%s:%s # service discovery : %s', rinfo.address, rinfo.port, message)
);
client.send(message, 0, message.length, rinfo.port, rinfo.ip);
});
client.bind(config.port);
The code on the NodeMcu looks like this:
#include <ESP8266WiFi.h> // WiFi library
#include <WiFiUdp.h> // UPD functionality
// UDP variables
WiFiUDP udp;
unsigned int localUdpPort = 8080;
char incomingPacket[255];
const char broadcastMessage[] = "ESP8266 UDP Server Discovery Broadcast";
// Server details - written to when the server is found
IPAddress serverIp = ~WiFi.subnetMask() | WiFi.gatewayIP(); // Use Broadcast Address as default in case the UDP service discovery isn't working as intended
unsigned int serverPort = localUdpPort; // Use local port as default in case the UDP service discovery ins't working as intended
void setupWiFi()
{
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
#if LOGGING
Serial.println("Connecting to network: " + (String) WIFI_SSID);
#endif
while (WiFi.status() != WL_CONNECTED)
{
delay(100);
}
#if LOGGING
Serial.print("Connected to network, Local IP Address: ");
Serial.println(WiFi.localIP());
#endif
udp.begin(localUdpPort); // begin listening on UDP port
#if LOGGING
Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localUdpPort);
#endif LOGGING
}
// Discover the server via a UDP broadcast, and store it's IP and Port in the local network in field variables for later use
// IMPORTANT - For the server to work, the Linux Firewall has to be disabled!!!
void discoverServer()
{
changeColor(PURPLE, false); // change the color of the RGB status LED to signal that the program is searching for the server
bool serverFound = false; // stop when the server is found
IPAddress broadcastIp = ~WiFi.subnetMask() | WiFi.gatewayIP(); // Get the Broadcast IP of the local network (e.g. 192.168.0.255)
while (!serverFound)
{
// Send UDP Broadcast
udp.beginPacket(broadcastIp, localUdpPort);
udp.write(broadcastMessage);
udp.endPacket();
#if LOGGING
Serial.printf("[UDP] Sending UDP Broadcast on IP: %s, Port: %d, Message: %s\n", broadcastIp.toString().c_str(), localUdpPort, broadcastMessage);
#endif
delay(1000); // Pause a few milliseconds to avoid flooding the network
// Receive UDP packets
int packetSize = udp.parsePacket();
if (packetSize > 0)
{
// Read incoming UDP Packet
int len = udp.read(incomingPacket, 255);
if (len > 0)
{
incomingPacket[len] = 0;
}
#if LOGGING
Serial.printf("[UDP] Received %d bytes from %s, port %d\n", packetSize, udp.remoteIP().toString().c_str(), udp.remotePort());
Serial.printf("[UDP] Packet contents: %s\n", incomingPacket);
#endif
// Check if the received message is from the server we are searching for
if (strcmp(incomingPacket, broadcastMessage) == 0)
{
serverIp = udp.remoteIP();
serverPort = udp.remotePort();
#if LOGGING
Serial.printf("[UDP] Found Server on IP: %s, Port: %d\n", serverIp.toString().c_str(), serverPort);
#endif
serverFound = true;
changeColor(YELLOW, false); // Change status color of RGB LED back to yellow
}
}
}
}
I'm really wondering if there is something wrong with the server, the network or the NodeMcu. Especially because every other method I tried worked perfectly, just not when I'm sending it from the NodeMcu. Any help is very much appreciated!
It turned out that there was an error in the server code.
Instead of
client.send(message, 0, message.length, rinfo.port, rinfo.ip);
it should have been
client.send(message, 0, message.length, rinfo.port, rinfo.address);
The server didn't know rinfo.ip, so it spammed itself with the same message over and over again.
I am developing an app for some time and recently I attached to the app an SSL Certificate (it is not self-signed; it is signed by Comodo, so the problem can't occur from here). I implemented long ago a WebSocket endpoint on my Java Glassfish server and I'm using it with javascript. I have been using the WebSocket successfully via http until now, when I moved to https.
Let's have a look at the code snippets I use:
Server Endpoint:
#ServerEndpoint(value = "/ws/chat",
encoders = ChatMessageEncoder.class,
decoders = ChatMessageDecoder.class)
public class ChatEndpoint {
#OnOpen
public void open(final Session session) {
// stuff happenin'
}
#OnMessage
public void onMessage(final Session session) {
// stuff happenin' }
#OnError
public void onError(Throwable t) {
t.printStackTrace();
System.out.println("error");
}
#OnClose
public void onClose() {
}
}
Client Connection:
var wsocketPrivate;
function connectToChatserver() {
var serviceLocation = 'wss://<ip>:8080/ws/chat';
$rootScope.wsocketPrivate = new WebSocket(serviceLocation);
$rootScope.wsocketPrivate.onmessage = onMessageReceived;
};
function onMessageReceived(evt) {
console.log(evt)
};
connectToChatserver();
Not having activated ssl certificate and using var serviceLocation = 'ws://<ip>:8080/ws/chat'; (ws instead of wss) works perfectly fine. When I moved to https, it asked for wss (the browser blocked my ws handshake because it wasn't secure) and moving to wss, the following error occurs:
WebSocket connection to 'wss://<ip>:8080/ws/chat' failed: Error in connection establishment: net::ERR_TIMED_OUT
What am I doing wrong? Can you suggest some tests to find out more information?
Thank you,
Mihai
I finally found where the problem was. I was using an nginx front server as a proxy. The default configuration of that server was blocking my wss for some weird reason.