I'm learning how to get my C# program communicate with browser.
I'm using TCP in C# and WebSocket in my HTML5 browser.
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace ShouldWork
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
TCPServer server = new TCPServer();
System.Threading.Thread obj_thread = new System.Threading.Thread(server.startServer);
obj_thread.Start();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
TcpClient client = new TcpClient("127.0.0.1", 7000);
NetworkStream ns = client.GetStream();
byte[] data_tosend = createDataPacket(Encoding.UTF8.GetBytes(tx_data_send.Text));
ns.Write(data_tosend, 0, data_tosend.Length);
}
private byte[] createDataPacket(byte[] data)
{
byte[] initialize = new byte[1];
initialize[0] = 2;
byte[] separator = new byte[1];
separator[0] = 4;
byte[] datalength = Encoding.UTF8.GetBytes(Convert.ToString(data.Length));
MemoryStream ms = new MemoryStream();
ms.Write(initialize, 0, initialize.Length);
ms.Write(datalength, 0, datalength.Length);
ms.Write(separator, 0, separator.Length);
ms.Write(data, 0, data.Length);
return ms.ToArray();
}
}
class TCPServer
{
TcpListener listener;
public TCPServer()
{
listener = new TcpListener(IPAddress.Any, 7000);
}
public void startServer()
{
listener.Start();
while (true)
{
TcpClient client = listener.AcceptTcpClient();
NetworkStream ns = client.GetStream();
if(ns.ReadByte() == 2)
{
byte[] recv_data = readStream(ns);
Form1.ActiveForm.Invoke(new MethodInvoker(delegate
{
((TextBox)Form1.ActiveForm.Controls.Find("tx_recv_data", true)[0]).Text = Encoding.UTF8.GetString(recv_data);
}));
}
}
}
public byte[] readStream(NetworkStream ns)
{
byte[] data_buff = null;
int b = 0;
String buff_length = "";
while ((b = ns.ReadByte()) != 4)
{
buff_length += (char)b;
}
int data_length = Convert.ToInt32(buff_length);
data_buff = new byte[data_length];
int byte_read = 0;
int byte_offset = 0;
while (byte_offset < data_length)
{
byte_read = ns.Read(data_buff, byte_offset, data_length - byte_offset);
byte_offset += byte_read;
}
return data_buff;
}
}
}
UI
When user clicks Start Server button, the program would then start the TCPServer. Then we can enter some text in the second textbox and my code will then process it and display the message on the first textbox.
Now I'd like to move the client part to the browser, so I created a simple web app and test out connection.
Code snippet
<!DOCTYPE html>
<html>
<head>
<title>Socket demo</title>
</head>
<body>
<button type="button" onclick="testWebSocket()">Connect to C# server</button><br><br>
<script language="javascript" type="text/javascript">
function testWebSocket(){
var socket = new WebSocket('ws://127.0.0.1:7000');
console.log("ssss");
socket.onopen = function(){
console.log("on open");
socket.send("Hello");
}
socket.onclose = function(evt){
console.log("on close");
}
socket.onerror = function(evt){
console.log("on error");
console.log(evt.data);
}
}
</script>
</body>
</html>
Here is what's wrong..... the onopen function doesn't seems to work at all, chrome console does display "sss" and that's it....
Is there something wrong with the approach I'm using?
As indicated in the comments, WebSocket uses its own framing schema.
Take a look to this link: https://hpbn.co/websocket/, specially the part where the framing is explained: https://hpbn.co/websocket/#binary-framing-layer
The reason why the connection never gets open, is because it is unable of completing the handshake : https://hpbn.co/websocket/#http-upgrade-negotiation
Related
I need shared memory communication between c# application and webpage through javascript
public partial class FormMemoryWritter : Form
{
MemoryMappedFile _memoryFIle;
public FormMemoryWritter()
{
InitializeComponent();
_memoryFIle = MemoryMappedFile.CreateOrOpen("myFile", int.MaxValue);
}
private void btnSend_Click(object sender, EventArgs e)
{
try
{
byte[] bytes = UTF8Encoding.UTF8.GetBytes(txtBox.Text);
var accessor = _memoryFIle.CreateViewAccessor(0, bytes.Length);
accessor.WriteArray<byte>(0, bytes, 0, bytes.Length);
}
catch (Exception)
{
}
}
}
Above code use in c# applicaion but how to received that that data in webpage through javascript
I have a project in NativeScript and i'm accessing the bluetooth android api via JavaScript as in this example:
android.bluetooth.BluetoothAdapter.getDefaultAdapter();
I am able to find the paired devices and connect to them. I wanted some example of how to forward data to the device and have a return of this device.
I've seen something in the android documents about:
getOutputStream()
and
getInputStream()
but I do not know how to use this via JavaScript.
I want is to send an command to an Elm327 OBD2 device and receive the data from this device.
Sample native code:
private OutputStream outputStream;
private InputStream inStream;
private void init() throws IOException {
BluetoothAdapter blueAdapter = BluetoothAdapter.getDefaultAdapter();
if (blueAdapter != null) {
if (blueAdapter.isEnabled()) {
Set<BluetoothDevice> bondedDevices = blueAdapter.getBondedDevices();
if(bondedDevices.size() > 0) {
Object[] devices = (Object []) bondedDevices.toArray();
BluetoothDevice device = (BluetoothDevice) devices[position];
ParcelUuid[] uuids = device.getUuids();
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuids[0].getUuid());
socket.connect();
outputStream = socket.getOutputStream();
inStream = socket.getInputStream();
}
Log.e("error", "No appropriate paired devices.");
} else {
Log.e("error", "Bluetooth is disabled.");
}
}
}
public void write(String s) throws IOException {
outputStream.write(s.getBytes());
}
public void run() {
final int BUFFER_SIZE = 1024;
byte[] buffer = new byte[BUFFER_SIZE];
int bytes = 0;
int b = BUFFER_SIZE;
while (true) {
try {
bytes = inStream.read(buffer, bytes, BUFFER_SIZE - bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
So I'm trying to make a webservice that allows someone to obtain data from a server. Right now, the server I'm using is written using java's HttpServer class. I plan to make the server accessible using fetch() in javascript, but it's not working.
When I was first testing out my server, I used Apache's HttpComponents library, and that client(written in java). was able to receive the test json that came from my server. However, when I used fetch() on my javascript client, nothing is received when I console.log everything. It doesn't make sense to me why it would work in Java, but not javascript. Does anyone know why this is not working? Am I just doing the javascript part wrong, and it does actually work? Thanks!
Code snippets for reference:
java server:
public class Main {
private static final int PORT = 1337;
private static final int BACKLOG = 1;
public static void main(String[] args) {
try {
HttpServer server = HttpServer.create(new InetSocketAddress(PORT), BACKLOG);
System.out.print("started on" + PORT);
HttpContext context = server.createContext("/ex", new Handler());
server.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Handler implements HttpHandler {
#Override
public void handle(HttpExchange he) throws IOException {
System.out.println("handled");
JSONObject obj = new JSONObject();
obj.put("name", "value");
obj.put("num", new Integer(100));
obj.put("balance", new Double(1000.21));
obj.put("is_vip", new Boolean(true));
obj.put("array", new int[]{1, 2, 3});
String response = obj.toJSONString();
he.sendResponseHeaders(200, response.length());
he.getResponseBody().write(response.getBytes());
}
}
java client:
public class PostTest {
public static void main(String[] args) throws IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("http://localhost:1337/ex");
CloseableHttpResponse response = httpClient.execute(httppost);
System.out.println("STATUS LINE");
System.out.println(response.getStatusLine().toString());
System.out.println("HEADER");
Header[] h = response.getAllHeaders();
for(int i = 0; i < h.length; i++) {
System.out.println(h[i]);
}
System.out.println("ENTITY.CONTENT");
try(BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"))) {
String s;
while((s = br.readLine()) != null) {
System.out.println(s);
}
}
}
}
Javascript:
var init = {mode: "no-cors"};
async function f() {
return fetch("http://localhost:1337/ex", init).then(res => res.text()).then(posts => console.log(posts));
}
f();
I have a server written in C# using Sockets:
/*
Richard D. Grant
R.grant.jr.122193#gmail.com
-Contact for details-
*/
using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Threading;
namespace SERVER{
static class Application{
private static readonly List<Socket> _client_list = new List<Socket>();
private const ushort _port = 8080, _buffer_len = 1024;
private static byte[] _buf = new byte[_buffer_len];
private static string key;
static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
private static Boolean exiting = false;
static int Main(){
Console.Title = "Server Application";
Socket server_socket = StartServer();
while(!exiting){
}
return CloseServer(server_socket);
}
private static Socket StartServer(){
IPEndPoint IPE = new IPEndPoint(IPAddress.Any, _port); // 192.168.0.14:80
Socket server_socket = new Socket(IPE.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
server_socket.Bind(IPE);
server_socket.Listen(128);
server_socket.BeginAccept(AcceptCallback, server_socket);
Console.WriteLine("Server Succeeded.");
return server_socket;
}
private static void AcceptCallback(IAsyncResult AR){
Console.WriteLine("accepting...");
Socket server_socket = (Socket)AR.AsyncState;
Socket client_socket = server_socket.EndAccept(AR);
client_socket.BeginReceive(_buf, 0, _buffer_len, SocketFlags.None, RecCallback, client_socket);
server_socket.BeginAccept(AcceptCallback, server_socket);
}
private static void RecCallback(IAsyncResult AR){
Console.WriteLine("Recieving");
Socket client_socket = (Socket)AR.AsyncState;
int rec_len = client_socket.EndReceive(AR);
byte[] rec_buf = new byte[rec_len];
Array.Copy(_buf, rec_buf, rec_len);
string rec_text = Encoding.UTF8.GetString(rec_buf);
if(!_client_list.Contains(client_socket)){
_client_list.Add(client_socket);
key = rec_text.Replace("ey:", "`")
.Split('`')[1] // dGhlIHNhbXBsZSBub25jZQ== \r\n .......
.Replace("\r", "").Split('\n')[0] // dGhlIHNhbXBsZSBub25jZQ==
.Trim();
var test1 = AcceptKey(ref key);
var newLine = "\r\n";
var response = "HTTP/1.1 101 Switching Protocols" + newLine
+ "Upgrade: websocket" + newLine
+ "Connection: Upgrade" + newLine
+ "Sec-WebSocket-Accept: " + test1 + newLine + newLine
;
client_socket.Send(Encoding.UTF8.GetBytes(response));
client_socket.Send("server received");
}else{
Console.WriteLine(rec_text);
}
_buf = new byte[_buffer_len];
client_socket.BeginReceive(_buf, 0, _buffer_len, SocketFlags.None, RecCallback, client_socket);
}
private static void client_disconnect(Socket soc){
soc.Shutdown(SocketShutdown.Both);
soc.Close();
}
private static ushort CloseServer(Socket server_socket){
foreach(Socket client in _client_list){
client_disconnect(client);
}
server_socket.Close();
return 0;
}
private static string AcceptKey(ref string key){
string longKey = key + guid;
byte[] hashBytes = ComputeHash(longKey);
return Convert.ToBase64String(hashBytes);
}
static SHA1 sha1 = SHA1CryptoServiceProvider.Create();
private static byte[] ComputeHash(string str){
return sha1.ComputeHash(Encoding.UTF8.GetBytes(str));
}
}
}
And i have the HTML5 websocket client:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function connect() {
var ws = new WebSocket("ws://localhost:8080/service");
ws.onopen = function () {
ws.send("Hello World"); // I WANT TO SEND THIS MESSAGE TO THE SERVER!!!!!!!!
console.log("opened!");
};
ws.onmessage = function (evt) {
console.log("About to receive data");
var received_msg = evt.data;
console.log("Message received = "+received_msg);
};
ws.onclose = function () {
// websocket is closed.
console.log("Connection is closed...");
};
};
</script>
</head>
<body style="font-size:xx-large" >
<div>
Click here to start</div>
</body>
</html>
HTML5 websocket requires a handshake, and the server deals with that accordingly.
client_socket.send(Encoding.UTF8.GetBytes("send"));
Does not trigger html5 onmessage
ws.send("send");
returns scrambled text to the server, but it is sent successfully.
The server deals with the handshake, but it does not deal with the packet frame after that. The message is not sent back in plain text and requires some processing.
How can I send and receive WebSocket messages on the server side?
This details the frame specification. For example, the first byte is always 129, the seconds has to do with the length. There is an example C# method to decode the frame on the link provided.
I wanted to post the source code to my solution, though i would like to give credit to AlexH for pointing me in the correct location.
private static byte[] encode(string str){
List<byte> lb = new List<byte>();
lb.Add(0x81);//129 to represent text frame
lb.Add((byte)str.Length);//2nd byte represents the length of the string
lb.AddRange(System.Text.Encoding.UTF8.GetBytes(str));
return lb.ToArray();
}
Frame:
+---------------------------------+
| FRAME TYPE | DATA LENGTH | DATA |
+---------------------------------+
I have Silverlight app. For example I want add some JS script which can interact with SL app. For example I want add google map use JS api. Can I do this, But I must send some data from SL to JS to add pins on map, draw figures on map ect.
If you are using Windows Phone and you dont mind that part of the xaml to be a webview yo can.
First add a webview to the xaml
<phone:WebBrowser Name="webView" BorderThickness="0" BorderBrush="Transparent" IsScriptEnabled="True"
ScriptNotify="WebBrowser_ScriptNotify" />
Then you have to bind the webview with the load event and then saveg files to storage and load your html and js files
webView.Loaded += WebBrowser_OnLoaded;
private void WebBrowser_OnLoaded(object sender, RoutedEventArgs e)
{
SaveFilesToIsoStore();
chatView.Navigate(new Uri("Assets/HtmlContent/index.html", UriKind.Relative));
}
private void SaveFilesToIsoStore()
{
//These files must match what is included in the application package,
//or BinaryStream.Dispose below will throw an exception.
string[] files = {
"Assets/HtmlContent/index.html",
"Assets/HtmlContent/js/libs/jquery-1.11.0.min.js", "Assets/HtmlContent/js/pagejs.js", "Assets/HtmlContent/css/style.css"
};
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
if (false == isoStore.FileExists(files[0]))
{
foreach (string f in files)
{
StreamResourceInfo sr = Application.GetResourceStream(new Uri(f, UriKind.Relative));
using (BinaryReader br = new BinaryReader(sr.Stream))
{
byte[] data = br.ReadBytes((int)sr.Stream.Length);
SaveToIsoStore(f, data);
}
}
}
}
private void SaveToIsoStore(string fileName, byte[] data)
{
string strBaseDir = string.Empty;
string delimStr = "/";
char[] delimiter = delimStr.ToCharArray();
string[] dirsPath = fileName.Split(delimiter);
//Get the IsoStore.
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
//Re-create the directory structure.
for (int i = 0; i < dirsPath.Length - 1; i++)
{
strBaseDir = System.IO.Path.Combine(strBaseDir, dirsPath[i]);
isoStore.CreateDirectory(strBaseDir);
}
//Remove the existing file.
if (isoStore.FileExists(fileName))
{
isoStore.DeleteFile(fileName);
}
//Write the file.
using (BinaryWriter bw = new BinaryWriter(isoStore.CreateFile(fileName)))
{
bw.Write(data);
bw.Close();
So on the js you have to talk to the c# like this
function sendMessageToCodeBehind(someData) {
window.external.notify(JSON.stringify({ method: 'AddMessage', data: someData }));
}
On the code behind you would recibe the messages from the webview like this:
private void WebBrowser_ScriptNotify(object sender, NotifyEventArgs e)
{
var example = new { method = string.Empty, data = new object() };
var obj = JsonConvert.DeserializeAnonymousType(e.Value, example);
switch (obj.method) {
case "methodName":
}
}
And you would send back messages to the js like this
webView.InvokeScript("jsMethodName", JsonConvert.SerializeObject(new { Message = "some json message" }));