How to send message in WebSocket - c#

I took a simple WebSocket server, where web-client sent message (Hello Wordld) and after the server respond to client and sent Hello World"". But I want to get a data from server and after client will print date on web -page. What I did wrong? Can you help me
namespace WebSocket
{
class Program
{
static Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
static private string guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
static void Main(string[] args)
{
serverSocket.Bind(new IPEndPoint(IPAddress.Any, 8080));
serverSocket.Listen(128);
serverSocket.BeginAccept(null, 0, OnAccept, null);
Console.Read();
}
private static void OnAccept(IAsyncResult result)
{
byte[] buffer = new byte[1024];
try
{
Socket client = null;
string headerResponse = "";
if (serverSocket != null && serverSocket.IsBound)
{
client = serverSocket.EndAccept(result);
var i = client.Receive(buffer);
headerResponse = (System.Text.Encoding.UTF8.GetString(buffer)).Substring(0, i);
// write received data to the console
Console.WriteLine(headerResponse);
}
if (client != null)
{
/* Handshaking and managing ClientSocket */
var key = headerResponse.Replace("ey:", "`")
.Split('`')[1] // dGhlIHNhbXBsZSBub25jZQ== \r\n .......
.Replace("\r", "").Split('\n')[0] // dGhlIHNhbXBsZSBub25jZQ==
.Trim();
// key should now equal dGhlIHNhbXBsZSBub25jZQ==
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
//+ "Sec-WebSocket-Protocol: chat, superchat" + newLine
//+ "Sec-WebSocket-Version: 13" + newLine
;
// which one should I use? none of them fires the onopen method
client.Send(System.Text.Encoding.UTF8.GetBytes(response));
var i = client.Receive(buffer); // wait for client to send a message
// once the message is received decode it in different formats
Console.WriteLine(Convert.ToBase64String(buffer).Substring(0, i));
Console.WriteLine("\n\nPress enter to send data to client");
Console.Read();
var time = DateTime.Now.ToString();
int length = time.Length;
var Data = Encoding.UTF8.GetBytes(time);
buffer = Data;
var subA = SubArray<byte>(buffer, 0, length);
client.Send(subA);
Thread.Sleep(10000);//wait for message to be send
}
}
catch (SocketException exception)
{
throw exception;
}
finally
{
if (serverSocket != null && serverSocket.IsBound)
{
serverSocket.BeginAccept(null, 0, OnAccept, null);
}
}
}
public static T[] SubArray<T>(T[] data, int index, int length)
{
T[] result = new T[length];
Array.Copy(data, index, result, 0, length);
return result;
}
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(System.Text.Encoding.ASCII.GetBytes(str));
}
}
}
This is web-client
<script type="text/JavaScript">
function connect() {
var ws = new WebSocket("ws://localhost:8080/service");
ws.onopen = function () {
alert("About to send data");
ws.send("Hello World");
alert("Message sent!");
};
ws.onmessage = function (evt) {
// alert("About to receive data");
var received_msg = evt.data;
document.write("Message received = "+received_msg);
// alert("Message received = "+received_msg);
};
ws.onclose = function () {
// websocket is closed.
alert("Connection is closed...");
};
};
</script>
For example if I will delete this sentences
var time = DateTime.Now.ToString();
int length = time.Length;
var Data = Encoding.UTF8.GetBytes(time);
buffer = Data;
and change the
var subA = SubArray<byte>(buffer, 0, length);
after this everything is work, but it only send Hello World, but I want to send a time and date. How I can do it? Please help me

Related

Networking code is not working properly, and is corrupting my data

So i am trying to write a simple proxy/relay to download a webpage trough. But it does not work very well. Sometimes the webpage is empty, or the images on the webpage are corrupted and incomplete, etc. So, it must be a networking problem. (the network stream is not completely read).
How can i solve this issue?
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace TrafficRerouter
{
class Program
{
private static int bufferSize = 8196;
private static string destIp = "www.projectrho.com";
static void Main(string[] args)
{
StartTcpListener(80);
}
private static byte[] SendReceiveRemoteServer(string host, int port, byte[] data)
{
try
{
// Create a TcpClient.
// Note, for this client to work you need to have a TcpServer
// connected to the same address as specified by the server, port
// combination.
var client = new TcpClient(host, port);
// Get a client stream for reading and writing.
// Stream stream = client.GetStream();
var stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
var str = Encoding.Unicode.GetString(data);
Console.Write("\nSent to server: ");
Col_Out(RemoveBinaryData(str), ConsoleColor.Red);
// Receive the TcpServer.response.
// Read the first batch of the TcpServer response bytes.
var bytes = new byte[bufferSize];
var allBytes = new List<byte>();
var i = stream.Read(bytes, 0, bytes.Length);
// Loop to receive all the data sent by the client.
while (i != 0)
{
allBytes.AddRange(bytes);
bytes = new Byte[bufferSize];
i = stream.DataAvailable ? stream.Read(bytes, 0, bytes.Length) : 0;
}
str = Encoding.Unicode.GetString(data);
Console.WriteLine("\nReceived from server: ");
Col_Out(RemoveBinaryData(str), ConsoleColor.DarkRed);
// Close everything.
stream.Close();
client.Close();
return allBytes.ToArray();
}
catch (ArgumentNullException e)
{
Console.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
Console.WriteLine("\n Press Enter to continue...");
return new byte[0];
}
private static void StartTcpListener(int port)
{
TcpListener server = null;
try
{
server = new TcpListener(IPAddress.Loopback, port);
// Start listening for client requests.
server.Start();
// Enter the listening loop.
while (true)
{
string s_received = "";
Console.WriteLine("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
var client = server.AcceptTcpClient();
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
var stream = client.GetStream();
// Buffer for reading data
var bytes = new Byte[bufferSize];
var allBytes = new List<byte>();
var i = stream.Read(bytes, 0, bytes.Length);
// Loop to receive all the data sent by the client.
while (i != 0)
{
allBytes.AddRange(bytes);
bytes = new Byte[bufferSize];
i = stream.DataAvailable ? stream.Read(bytes, 0, bytes.Length) : 0;
}
if (allBytes.Count > 0)
{
Console.Write("\nReceived from client : ");
Col_Out(RemoveBinaryData(Encoding.UTF8.GetString(allBytes.ToArray())) + '\n', ConsoleColor.DarkGreen);
var received = SendReceiveRemoteServer(destIp, 80, allBytes.ToArray());
s_received = Encoding.Unicode.GetString(received);
// Send back a response.
stream.Write(received, 0, received.Length);
Console.Write("\nSent to client : ");
Col_Out(RemoveBinaryData(s_received) + '\n', ConsoleColor.Green);
}
// Shutdown and end connection
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}
Console.WriteLine("\nHit enter to continue...");
}
private static char[] good_chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz/.,;:[]=+-_1234567890()*&\n\r".ToArray();
static string RemoveBinaryData(string s)
{
StringBuilder r = new StringBuilder();
foreach (var c in s)
{
if (good_chars.Contains(c)) r.Append(c);
}
return (r.ToString() + "\n[BINARY_DATA]").Replace("\n", "█ ") + "\n";
}
static void Col_Out(string str, ConsoleColor c)
{
var oldc = Console.ForegroundColor;
Console.ForegroundColor = c;
Console.Write(str);
Console.ForegroundColor = oldc;
}
}
}

How to POST data and get response from Unix Socket with .net core

I'm attempting to communicate with the Docker Daemon using dotnet core. I've been using this guide which is working as expected.
The problem I'm having is when I attempt to POST data to the endpoint in order to modify a docker service (basically I'd like to be able to scale up / down services in this instance) I'm using the same method to send the data to the socket but changing the content:
This is the GET method to receive the running services which works:
public string GetAllServices()
{
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
var unixEndpoint = new UnixEndPoint("/var/run/docker.sock"); // this address is where the socket exists
socket.Connect(unixEndpoint); // connect to the socket
// create a request like this in HTTP spec format
var request = $"GET /v1.24/services "
+ "HTTP/1.1\r\n"
+ "Host: unix\r\n"
+ "Content-Length: 0\r\n"
+ "accept-encoding: gzip\r\n"
+ "Connection: keep-alive\r\n"
+ "Accept: */*\r\n"
+ "\r\n";
// convert the request into byte data
byte[] requestBytes = Encoding.ASCII.GetBytes(request);
// send the request to the socket
socket.Send(requestBytes);
// get the header
while (true)
{
var headerLine = ReceiveUntilCRLF(socket);
if (headerLine == "\r\n")
{
break;
}
if (headerLine == "HTTP/1.1 400 Bad Request\r\n")
{
break;
}
}
// get the payload
var payload = "";
byte[] chunkLengthBytes = new byte[512];
var chunkLength = 0;
while (true)
{
// get the length of the next chunk
var temp = ReceiveUntilCRLF(socket);
// get the chunk
byte[] chunkBytes = new byte[chunkLength];
payload += ReceiveUntilCRLF(socket);
// append chunk to payload string
if (payload.EndsWith("\r\n"))
{
break;
}
}
// in the end, disconnect and close the socket to cleanup
socket.Disconnect(false);
socket.Close();
return payload;
}
Then to update the service:
public void UpdateService(Services currentServiceState)
{
bool badRequest = false;
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
var unixEndpoint = new UnixEndPoint("/var/run/docker.sock"); // this address is where the socket exists
socket.Connect(unixEndpoint); // connect to the socket
var body = JsonConvert.SerializeObject(currentServiceState, Formatting.Indented);
string request = CreateRequestString($"/v1.24/services/{currentServiceState.Spec.Name}/update?version={currentServiceState.Version.Index}", body);
// convert the request into byte data
byte[] requestBytes = Encoding.ASCII.GetBytes(request);
// send the request to the socket
socket.Send(requestBytes);
// get the header
while (true)
{
var headerLine = ReceiveUntilCRLF(socket);
if (headerLine == "\r\n")
{
break;
}
if (headerLine == "HTTP/1.1 400 Bad Request\r\n")
{
badRequest = true;
string errorResponse = headerLine;
while (true)
{
var newLine = ReceiveUntilCRLF(socket);
errorResponse += newLine;
if (newLine == "\r\n")
{
Console.WriteLine($"{errorResponse}");
break;
}
}
break;
}
}
if(!badRequest)
{
// get the payload
var payload = "";
byte[] chunkLengthBytes = new byte[512];
var chunkLength = 0;
while (true)
{
// get the length of the next chunk
var temp = ReceiveUntilCRLF(socket);
// get the chunk
byte[] chunkBytes = new byte[chunkLength];
payload += ReceiveUntilCRLF(socket);
// append chunk to payload string
Console.Write(payload);
if (payload.EndsWith("\r\n"))
{
break;
}
}
}
// in the end, disconnect and close the socket to cleanup
socket.Disconnect(false);
socket.Close();
}
and CreateRequestString() looks like this:
public string CreateRequestString(string endpoint, string content)
{
int contentLength = 0;
if (content.Length > 0)
{
contentLength = Encoding.UTF8.GetBytes(content).Length;
}
var requestString = $"POST {endpoint} "
+ "HTTP/1.1\r\n"
+ "Host: unix\r\n"
+ "accept-encoding: gzip\r\n"
+ "Connection: keep-alive\r\n"
+ $"content-length: {contentLength}\r\n"
+ "Accept: */*\r\n"
+ "\r\n";
if (content.Length > 0)
{
requestString += $"{JsonConvert.DeserializeObject(content)}";
}
return requestString;
}
Which returns a 400 Bad Request.
I'm wondering if either:
1. Am I calculating the content length correctly?
2. Am I building the requestString correctly?
3. Is there something else i've missed?
Thanks

SocketException was caught

My code
This code for server
class Program
{
private static readonly byte[] Localhost = {127,0,0,1};
private const int Port = 8567;
static void Main(string[] args)
{
var address = new IPAddress( Localhost );
var endPoint = new IPEndPoint(address, Port);
var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(endPoint);// Error in this line
listener.Listen(3);
String data = "";
while (true)
{
Console.WriteLine("Listening on sport {0}", endPoint);
byte[] buffer = new byte[4096];
// handle incoming connection ...
var handler = listener.Accept();
Console.WriteLine("Handling incoming connection ...");
while (true)
{
int count = handler.Receive(buffer);
data += Encoding.UTF8.GetString(buffer, 0, count);
// Find start of MLLP frame, a VT character ...
int start = data.IndexOf((char) 0x0B);
if (start >= 0)
{
// Now look for the end of the frame, a FS character
int end = data.IndexOf((char) 0x1C);
if (end > start)
{
string temp = data.Substring(start + 1, end - start);
// handle message
string response = HandleMessage(temp);
// Send response
handler.Send(Encoding.UTF8.GetBytes(response));
break;
}
}
}
// close connection
handler.Shutdown( SocketShutdown.Both);
handler.Close();
Console.WriteLine("Connection closed.");
}
}
catch (Exception e)
{
Console.WriteLine("Exception caught: {0}", e.Message);
}
Console.WriteLine("Terminating - press ENTER");
Console.ReadLine();
}
private static string HandleMessage(string data)
{
Console.WriteLine("Received message");
var msg = new Message();
msg.Parse(data);
Console.WriteLine("Parsed message : {0}", msg.MessageType() );
Console.WriteLine("Message timestamp : {0}", msg.MessageDateTime() );
Console.WriteLine("Message control id : {0}", msg.MessageControlId());
// *********************************************************************
// Here you could do something usefull with the received message ;-)
// *********************************************************************
// todo
// Create a response message
//
var response = new Message();
var msh = new Segment("MSH");
msh.Field(2, "^~\\&");
msh.Field(7, DateTime.Now.ToString("yyyyMMddhhmmsszzz"));
msh.Field(9, "ACK");
msh.Field(10, Guid.NewGuid().ToString() );
msh.Field(11, "P");
msh.Field(12, "2.5.1");
response.Add(msh);
var msa = new Segment("MSA");
msa.Field(1, "AA");
msa.Field(2, msg.MessageControlId());
response.Add(msa);
// Put response message into an MLLP frame ( <VT> data <FS><CR> )
//
var frame = new StringBuilder();
frame.Append((char) 0x0B);
frame.Append(response.Serialize());
frame.Append( (char) 0x1C);
frame.Append( (char) 0x0D);
return frame.ToString();
}
}
but I am getting following error:
SocketException was caught :- An attempt was made to access a socket in a way forbidden by its access permissions
Please give me any solution.
Exception message tells that you don't have access rights to the socket you created. This can be caused by either socket being already used or user running this process having lower rights than necessary (non-admin rights; this is less likely the reason of the exception in your case).
To check whether some process is already using the socket, open Command Prompt and execute:
netstat -o | find "8567"

Send Hex from php to device using socket_sendto

I have spent days trying to figure this out. I have a GPS tracker device that communicates using UDP protocol.
And I have a hex string I need to send to this tracker:
"0d0a2a4b5700440002000000000000002a4b572c4e5230394230353330342c3030372c3034333133392c3023000000000000000000000000000000000000000000000d0a"
If I send this string using c#, the device replies back. C# Code:
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length / 2;
byte[] bytes = new byte[NumberChars];
using (var sr = new StringReader(hex))
{
for (int i = 0; i < NumberChars; i++)
bytes[i] =
Convert.ToByte(new string(new char[2] { (char)sr.Read(), (char)sr.Read() }), 16);
}
return bytes;
}
// Send Message to tracker
public static void send(string ip, string port, string msg)
{
Byte[] sendBytes = StringToByteArray(msg);
try
{
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), int.Parse(port));
UDPreceiver.Send(sendBytes, sendBytes.Length, ipEndPoint);
Program.form1.addlog("Sent: " + ByteArrayToString(sendBytes) + " - to " + ip + " on port: " + port);
}
catch (Exception e)
{
MessageBox.Show(e.ToString(), "error");
}
}
Now If I try to send the same hex string from PHP. The device does not respond, here's the php code:
// Function send
function send($ip,$port,$message){
$socket_bytes = false;
try {
// Prepare message
$strlen = strlen($message);
$message = hex2bin(strtoupper($message));
// Send Packet
if(!($this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))){
die('msg,could not create socket');
}
$socket_bytes = socket_sendto($this->socket, $message, $strlen, 0, $ip, $port);
socket_close($this->socket);
}catch(Exception $e){
return false;
}
return $socket_bytes;
}
I have exhausted my self trying to figure out how to send this. Please any help would be very appreciated.
I'm not sure but
strlen($message) != strlen(hex2bin(strtoupper($message)));
$message = 'ABCD';
echo strlen($message); //==4
echo "\n";
echo strlen(hex2bin(strtoupper($message))); //==2

Force code execution till the end of method

I'm working on client-server multithreading application:
Progress of communication is:
Server listens on socket
Client connects and send request or requests to server
Each request is ended by 0x04
Server must proceess each request with operation which is slower than incoming requests
I have a problem in "ProcessClient" method when two requests occur in short time and first request cannot be processed till the end of method beacuse second request is coming to process. Problem occurs after foreach loop:
foreach (var t in invoices)
{
SaveToDataBase(t);
}
Method does not executes till the end and it does not sends response to client with following code snippet:
var ResponseFile = ResponseClientFolder + "\\" + ResponseClientFileName + x + ".txt";
StreamWriter sw = File.CreateText(ResponseFile);
sw.WriteLine(_odgovor);
sw.Close();
_odgovor = string.Empty;
SendToClient(ResponseFile);
beacuse second request occurs at "ProcessClient" method.
Is there any way to solve this problem. I was looking for many solution without success.
Whole code is below:
private void RunListener()
{
try
{
_listener = new TcpListener(IPAddress.Parse(ServerAddres), ServerPort);
_listener.Start();
while (true)
{
TcpClient client = _listener.AcceptTcpClient();
Invoke(new Action(() => { }));
ThreadPool.QueueUserWorkItem(ProcessClient, client);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, #"Run listener");
}
}
private void ProcessClient(object state)
{
try
{
byte[] bytes = new byte[1024];
TcpClient client = state as TcpClient;
StringBuilder completeMessage = new StringBuilder();
if (client == null) return;
networkStream = client.GetStream();
int bytesRead = 0;
do
{
bytesRead = networkStream.Read(bytes, 0, bytes.Length);
completeMessage.AppendFormat("{0}", Encoding.Default.GetString(bytes, 0, bytesRead));
} while (bytesRead > 0 && bytes[bytesRead - 1] != 0x04);
completeMessage = completeMessage.Replace(#"”", "");
string datetime = DateTime.Now.ToString();
var x = datetime.Replace(".", string.Empty).Replace(":", string.Empty).Replace(" ", string.Empty);
var inputfilename = "Racun" + x + ".txt";
StreamWriter sws = File.CreateText(inputfilename);
sws.WriteLine(completeMessage);
sws.Close();
string data = completeMessage.ToString();
char[] delimiters = { '\r', '\n' };
string[] invoices = data.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
foreach (var t in invoices)
{
SaveToDataBase(t);
}
var ResponseFile = ResponseClientFolder + "\\" + ResponseClientFileName + x + ".txt";
StreamWriter sw = File.CreateText(ResponseFile);
sw.WriteLine(_odgovor);
sw.Close();
_odgovor = string.Empty;
SendToClient(ResponseFile);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, #"Proces client");
}
}
private void SendToClient(string ResponseFile)
{
try
{
byte[] byteData = File.ReadAllBytes(ResponseFile);
List<byte> byteDat = new List<byte>();
byteDat.AddRange(byteData);
byteDat.Add(0x04);
byteData = byteDat.ToArray();
networkStream.Write(byteData, 0, byteData.Length);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, #"Send to client");
}
}

Categories