C# websocket server not firing the onmessage event in html5 - c#

Perhaps I badly need a hand now.
I am currently having a problem regarding websocket server using c# and HTML5. It is not firing my onmessage() event in html5. It opens the socket connection and triggers the onopen() event. But, once a connection is established, it continues to close the connection. Here's my simple code:
SERVER (c#):
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
public Socket ListenerSocker { get; private set; }
static IPEndPoint ipLocal;
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.Listen(200);
serverSocket.BeginAccept(null, 0, OnAccept, null);
Console.Read();
}
private static void OnClientConnect()
{
serverSocket.BeginAccept(null, 0, OnAccept, null);
}
private static void OnAccept(IAsyncResult result)
{
byte[] buffer = new byte[1024];
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-Key: " + test1 + newLine + newLine
+ "Sec-WebSocket-Key: " + 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 subA = SubArray<byte>(buffer, 0, i);
Console.WriteLine("***SUBA****:"+subA);
Console.WriteLine("TEST");
client.Send(subA);
// Thread.Sleep(10000);//wait for message to be send
// OnClientConnect();
}
}
public static T[] SubArray<T>(T[] data, int index, int length)
{
T[] result = new T[length];
Array.Copy(data, index, result, 0, length);
Console.WriteLine(result);
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));
}
}
}
CLIENT (HTML5):
<!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");
console.log(ws);
ws.onopen = function () {
alert("About to send data");
ws.send("test"); // I WANT TO SEND THIS MESSAGE TO THE SERVER!!!!!!!!
alert("Message sent!");
};
ws.onmessage = function (evt) {
alert("About to receive data");
var received_msg = evt.data;
alert("Message received = "+received_msg);
};
ws.onclose = function () {
// websocket is closed.
alert("Connection is closed...");
};
};
function send(){
}
</script>
</head>
<body style="font-size:xx-large" >
<div>
Click here to start</div>
</body>
</html>
I can get this:
alert("About to send data");
and this:
alert("Message sent!");
but after that, the connection closes. I could also check that the server receives data from client. The thing is, once I send data from server to client, for me to be able to return what the client has given me, the connection suddenly closes. What could possibly be the problem?

Websocket messages are not plain text; they need to have a simple framing protocol applied
Framing rules differ slightly for client->server and server->client messages. I imagine the client is closing its connection when you try to echo its message without applying the different framing.
See the data framing section of RFC6455 for how to decode/encode messages. Or, if you're using .NET4.5, you could consider using System.Net.WebSockets instead of writing your own server.

Related

C# socket client server disconection

Hi i have the following socket server/client codes which another stackoverflow member gave me.
Basically the server listens to multiple clients, it all works good and smooth but when a client exits the app the server crashes because of unexpected disconnect.
I read about heartbeed but don't know how to implement it as im quite a noob at c#
Below are the codes
Server:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class AsynchIOServer
{
static System.Collections.Concurrent.ConcurrentBag<Socket> ConnectedClients = new System.Collections.Concurrent.ConcurrentBag<Socket>();
static void Process(Socket client)
{
Console.WriteLine("Incoming connection from " + client.RemoteEndPoint);
const int maxMessageSize = 1024;
byte[] response;
int received;
while (true)
{
if (client.Poll(-1, SelectMode.SelectRead))
{
// Receive message from the server:
response = new byte[maxMessageSize];
received = client.Receive(response);
if (received == 0)
{
Console.WriteLine("Client closed connection!");
if (!ConnectedClients.TryTake(out client))
Console.WriteLine("Error when removing connection socket object from list (" + client.RemoteEndPoint + ")!");
return;
}
List<byte> respBytesList = new List<byte>(response);
respBytesList.RemoveRange(received, maxMessageSize - received); // truncate zero end
Console.WriteLine("Client " + client.RemoteEndPoint + " : " + Encoding.ASCII.GetString(respBytesList.ToArray()));
}
}
}
public static void Main()
{
int backlog = -1, port = 2222;
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.ReceiveTimeout = -1;
// Start listening.
try
{
server.Bind(new IPEndPoint(IPAddress.Any, port));
server.Listen(backlog);
}
catch (Exception)
{
Console.WriteLine("Listening failed!");
Console.ReadKey();
return;
}
Console.WriteLine("Start listening...");
new System.Threading.Thread(() => {
while (true)
{
Socket client = server.Accept();
ConnectedClients.Add(client);
new System.Threading.Thread(() => {
try { Process(client); }
catch (Exception ex)
{
Console.WriteLine(client.RemoteEndPoint + " client connection processing error: " + ex.Message);
if (!ConnectedClients.TryTake(out client))
Console.WriteLine("Error when removing connection socket object from list (" + client.RemoteEndPoint + ")!");
}
}).Start();
}
}).Start();
while (true)
{
byte[] sent = Encoding.ASCII.GetBytes(Console.ReadLine());
if (sent.Length == 0) break;
foreach (Socket s in ConnectedClients.ToArray()) s.Send(sent);
}
Console.WriteLine("Press any key for exit...");
foreach (Socket s in ConnectedClients.ToArray()) s.Close();
Console.ReadKey();
}
}
Client:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class Client
{
static void WorkWithServer(Socket server)
{
const int maxMessageSize = 1024;
byte[] response;
int received;
while (true)
{
try
{
// Receive message from the server:
response = new byte[maxMessageSize];
received = server.Receive(response);
if (received == 0)
{
Console.WriteLine("Server closed connection.");
return;
}
List<byte> respBytesList = new List<byte>(response);
respBytesList.RemoveRange(received, maxMessageSize - received); // truncate zero end
Console.WriteLine("Server: " + Encoding.ASCII.GetString(respBytesList.ToArray()));
// Send message to the server:
/* Console.Write("You: ");
server.Send(Encoding.ASCII.GetBytes(Console.ReadLine()));
Console.WriteLine(); */
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
return;
}
}
}
static public void Main(string[] Args)
{
IPEndPoint serverEp = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2222);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.ReceiveTimeout = -1;
// Connect to the server.
try { server.Connect(serverEp); }
catch (Exception)
{
Console.WriteLine("Establish connection with server (" + serverEp + ") failed!");
Console.ReadKey();
return;
}
Console.WriteLine("Connection with server (" + serverEp + ") established!");
WorkWithServer(server);
Console.WriteLine("Press any key for exit...");
Console.ReadKey();
}
}
Apart from that i want the server to receive data from another server and once received transmit it to all the connected clients
I know i am probabily asking for too much but as i said my c# skills are almost none and i cannot afford paying someone

My Tcp server is using waaaay too much memory

so I've made a C# TCP server, however whenever I connected multiple clients for a test, the whole device starts to lag out and the memory goes to 500 MB, earlier 1GB. I understand that this has to do with code structure and so however I'm not sure what's really causing this.
Image.
Console.
Basically, here's my server class.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Roleplay_Flash_Server.assets.communication
{
class server
{
private static TcpListener serverHandle;
private const string prefix = "[communication->server.cs] ";
private static bool responded = false;
public static void init(int port)
{
serverHandle = new TcpListener(IPAddress.Any, port);
serverHandle.Start();
Console.WriteLine("Waiting on a client...");
while (responded == false)
{
serverHandle.BeginAcceptTcpClient(HandleAsyncConnection, serverHandle);
//responded = false;
}
}
private static void HandleAsyncConnection(IAsyncResult response)
{
responded = true;
serverHandle.BeginAcceptTcpClient(HandleAsyncConnection, serverHandle);
TcpClient client = serverHandle.EndAcceptTcpClient(response);
communication.client.incoming.connection(client);
communication.client.events.pingIntervalEvent.init(client);
communication.client.events.handshakeEvent.init(client);
while(true)
{
string test = readRequest(client);
}
destruct(client);
}
public static string readRequest(TcpClient socket)
{
byte[] data = new byte[1024];
int response = socket.Client.Receive(data);
if (response == 0) return "";
string clientIP = ((IPEndPoint)socket.Client.RemoteEndPoint).Address.ToString();
string clientPort = ((IPEndPoint)socket.Client.RemoteEndPoint).Port.ToString();
Console.Write(prefix + "Received data from {#" + "?" + "}, {" + clientIP + ":" + clientPort + "}: " + Encoding.ASCII.GetString(data, 0, response));
return Encoding.ASCII.GetString(data, 0, response);
}
private static void destruct(TcpClient socket)
{
string clientIP = ((IPEndPoint)socket.Client.RemoteEndPoint).Address.ToString();
string clientPort = ((IPEndPoint)socket.Client.RemoteEndPoint).Port.ToString();
Console.Write(prefix + "Lost connection with {#" + "?" + "}, {" + clientIP + ":" + clientPort + "}.");
socket.Close();
}
}
}
Edit: All classes which may be causing this memory overflow:
https://pastebin.com/eB54fJY2
https://pastebin.com/LW2A7RZk
https://pastebin.com/t9YvTNsj
https://pastebin.com/C18du82K
So I've fixed this issue by simply removing the BeginAcceptTcpClient from the Async callback, this was causing the function to be called in the infinite loop but also in another callback called from the loop, making excessive memory overflow.

Tcp .Send Doesn't work after using for the first time

I am UsingClient.Send(Encoding.ASCII.GetBytes(Message)); to send a message to the client, when i tried sending a second message it doesn't give any error so i think it send with no problem but it never reaches the client (127.0.0.1)
Code That Send
public void SendMessage(Socket _Client, string Message)
{
foreach (Socket Client in Clients)
{
IPEndPoint TargetEndPoint = _Client.LocalEndPoint as IPEndPoint;
IPAddress TargetIp = TargetEndPoint.Address;
int TargetPort = TargetEndPoint.Port;
IPEndPoint ClientEndPoint = Client.LocalEndPoint as IPEndPoint;
IPAddress ClientIp = ClientEndPoint.Address;
int ClientPort = ClientEndPoint.Port;
if (TargetIp.ToString() == ClientIp.ToString() && TargetPort == ClientPort)
{
Client.Send(Encoding.ASCII.GetBytes(Message));
//Client.EndSend();
}
}
}
Code That Receive
private void RecivedCallBack(IAsyncResult Result)
{
//Create a int with the Buffer Size
int BufferSize = _Socket.EndReceive(Result);
//Create a new byte array with the Buffer Size
byte[] Packet = new byte[BufferSize];
//Copy Buffer to Packet
Array.Copy(_Buffer, Packet, Packet.Length);
//Handle Packet
PacketHandler.Packet(Encoding.UTF8.GetString(Packet));
//Makes _Buffer a new byte
_Buffer = new byte[1024];
//Get Ready to recive data
_Socket.BeginReceive(_Buffer, 0, _Buffer.Length, SocketFlags.None, RecivedCallBack, null);
}
Code that Handle
public static void Packet(string Message)
{
Console.WriteLine(Message);
switch (Message)
{
case "StartChat":
_ChatForm Start = new _ChatForm();
Start.ShowDialog();
break;
case "StopChat":
_ChatForm._Chat.EndChat();
break;
}
}
TCP is stream based, so your client has no way to know when the message has ended. Either use UDP, implement a way to detect the end of messages (eg send a 4 byte message with the length of the real message, before sending the real message... and read on the client until the whole message has been received), or use a library. I like Hazel: https://github.com/DarkRiftNetworking/Hazel-Networking.
The great thing about Hazel is that it implements reliable UDP. So, if you need to have your "messages" arrive in the order in which they were sent, or if you need guaranteed delivery and receipt of such messages (such as what TCP provides), then you can do so with their reliable UDP implementation.
They will also implement Web Sockets at some point :) Good luck!
A client/server example from the documentation:
Server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using Hazel;
using Hazel.Tcp;
namespace HazelExample
{
class ServerExample
{
static ConnectionListener listener;
public static void Main(string[] args)
{
listener = new TcpConnectionListener(IPAddress.Any, 4296);
listener.NewConnection += NewConnectionHandler;
Console.WriteLine("Starting server!");
listener.Start();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
listener.Close();
}
static void NewConnectionHandler(object sender, NewConnectionEventArgs args)
{
Console.WriteLine("New connection from " + args.Connection.EndPoint.ToString();
args.Connection.DataReceived += DataReceivedHandler;
args.Recycle();
}
private static void DataReceivedHandler(object sender, DataEventArgs args)
{
Connection connection = (Connection)sender;
Console.WriteLine("Received (" + string.Join<byte>(", ", args.Bytes) + ") from " + connection.EndPoint.ToString());
connection.SendBytes(args.Bytes, args.SendOption);
args.Recycle();
}
}
}
Client
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Hazel;
using Hazel.Tcp;
namespace HazelExample
{
class ClientExample
{
static Connection connection;
public static void Main(string[] args)
{
NetworkEndPoint endPoint = new NetworkEndPoint("127.0.0.1", 4296);
connection = new TcpConnection(endPoint);
connection.DataReceived += DataReceived;
Console.WriteLine("Connecting!");
connection.Connect();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
connection.Close();
}
}
}

C# Socket Server Continuously Reading

I just made a C# socket server and it works perfectly, but if I would like to make it to be able to listen the inputs the program crashes. My question is: how can I make to continuously listen after the clients commands.
Here is my code:
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace mc_server
{
class Program
{
private static TcpListener serverSocket;
private static TcpClient clientSocket;
private static StreamReader reader;
private static StreamWriter writer;
private static int PORT = 5000;
static void Main(string[] args)
{
Console.WriteLine(DateTime.Now.ToString() + " >> Server starting...");
StartServer();
Console.ReadKey(true);
serverSocket.Stop();
}
private static void StartServer()
{
try
{
serverSocket = new TcpListener(IPAddress.Any, PORT);
serverSocket.Start();
Console.WriteLine(DateTime.Now.ToString() + " >> Server started");
while (true)
{
clientSocket = serverSocket.AcceptTcpClient();
reader = new StreamReader(clientSocket.GetStream());
writer = new StreamWriter(clientSocket.GetStream());
StartListening();
}
}
catch (Exception e)
{
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
Console.WriteLine(DateTime.Now.ToString() + " [ERR]: Internet connection unavailable! (" + e.ToString() + ")");
else
Console.WriteLine(DateTime.Now.ToString() + " [ERR]: Server can't be started! (" + e.ToString() + ")");
}
}
private static void StartListening()
{
try
{
string line;
//while (true)
//{
line = reader.ReadLine();
if (line.Contains("connected"))
{
Console.WriteLine(DateTime.Now.ToString() + " >> Remote connected");
}
else if (line.Contains("get_dir"))
{
Console.WriteLine("in_get_dir");
foreach (string directory in Directory.GetDirectories(path))
{
DirectoryInfo dir_name = new DirectoryInfo(directory);
string dirName = dir_name.Name;
writer.WriteLine(line);
}
}
//}
}
catch (Exception e)
{
Console.WriteLine(DateTime.Now.ToString() + " [ERR]: " + e.ToString() + ")");
}
}
}
}
Thank you so much for your help!
Regards, Stanley.
I just made a C# socket server and it works perfectly, but if I would like to make it to be able to listen the inputs the program crashes.
I am not sure what you meant by that, but I think you have a problem in receiving/reading the response.
serverSocket = new TcpListener(IPAddress.Any, PORT);
serverSocket.Start();
You've created a TcpListener named 'serverSocket'. Now let's create a socket that helps us send and receive data between the server and the client. Creating a Streamwriter and Streamreader is too long and complicated. You'll have to deal with flushing, disposing, and closing them.
Here's my 3 simplified guide of using Socket to communicate:
1.) Creating a Socket:
Socket socket = serverSocket.AcceptSocket(); // This is a
//synchronous function. It will not execute the next line until a client
//connects to the server
2.) Sending data:
socket.Send(Encoding.ASCII.GetBytes("I am sending a short text to
the client")); // This will send the text to client. It ONLY accepts byte
//array, therefore we have to convert it from string to byte array to be
//able
//to send it.
3.) Receiving/Reading Data:
// For Receiving Text from the Client
byte[] responseByteArray = new byte[socket.ReceiveBufferSize]; //
//This will create a byte array to store the data. socket.ReceiveBufferSize
//will tells us the length of the data sent in byte array (not string yet)
int responseLength = socket.Receive(responseByteArray); // Tells us
//the length of the response in byte array (not string yet)
string response = null; // We will create a variable 'response' to
//store the final result of the conversion
for (int i = 0; i < responseLength; i++) // Loop to convert All byte
//from byte array to string
{
response = response + (char)responseByteArray[i]; // Converts
//every single byte of character to char
}
Console.WriteLine(response); // Prints out the final result in
//string
You can use async/await keywords to read & write data asynchronously on the sockets.
That way, your input logic will stay separate. If you use async/await, you won't have to manage threads manually.

How to send message in WebSocket

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

Categories