My Tcp server is using waaaay too much memory - c#

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.

Related

check when a client is disconnected

I have a console application in c#
this code can tell me when a client si connected in TCP to port 3001 and the message sent
I cant understand when he disconnects, its going into while (client.Connected) unlimited, i tried to check with a PING but sometimes returns false even if connnected,
I am stuck
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
int port = 3001;
TcpListener listener = new TcpListener(IPAddress.Any, port);
listener.Start();
Console.WriteLine("Listening on port " + port + "...");
while (true)
{
TcpClient client = listener.AcceptTcpClient();
Console.WriteLine("Accepted connection from " + client.Client.RemoteEndPoint.ToString());
while (client.Connected)
{
NetworkStream stream = client.GetStream();
if (stream.DataAvailable)
{
byte[] buffer = new byte[1024];
int bytesRead = stream.Read(buffer, 0, buffer.Length);
string data = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine("Received data: " + data);
}
//check if client still connected
string[] cli = client.Client.RemoteEndPoint.ToString().Split(Convert.ToChar(":"));
string Host = cli[0];
int Uri = port;// int.Parse(cli[1]);
if (PingHost(Host,Uri)==false)
{
Console.WriteLine("Client disconnected.");
break;
}
}
}
}
public static bool PingHost(string hostUri, int portNumber)
{
try
{
using (var client = new TcpClient(hostUri, portNumber))
return true;
}
catch (SocketException ex)
{
//MessageBox.Show("Error pinging host:'" + hostUri + ":" + portNumber.ToString() + "'");
return false;
}
}
}
}

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

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.

C# websocket server not firing the onmessage event in html5

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.

Web Proxy Created in C# needing to prompt for authentication

I worte a little Web Proxy program that uses a TcpListener, which listen on a specific port for web calls. Once it recieves a call it creates a socket, gets the header of the call, forwards it onto the web page requested, reads the response and returns it to the client doing the request. The proxy works lovely, but now I want to limit who has access to the net via the proxy by implimenting user names. How would I incorparate authentication onto my proxy?
Here is my code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
namespace WebProxy2
{
public partial class Form1 : Form
{
public bool proxyOn = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public void log(string logText)
{
Application.DoEvents();
textBox1.Text += logText + "\r\n";
StreamWriter sw = new StreamWriter(#"c:\proxyLog.txt",true);
sw.WriteLine(logText);
sw.Close();
Application.DoEvents();
}
class WebProxy2
{
Socket clientSocket;
Form1 proxyGui;
Byte[] read = new byte[1024];
Byte[] Buffer = null;
Encoding ASCII = Encoding.ASCII;
const string HTTP_VERSION = "HTTP/1.0";
const string CRLF = "\r\n";
Byte[] RecvBytes = new Byte[4096];
public WebProxy2(Socket socket, Form1 form)
{
this.clientSocket = socket;
this.proxyGui = form;
}
public void run()
{
Application.DoEvents();
String clientmessage = " ", sURL = " ";
int bytes = readmessage(read, ref clientSocket, ref clientmessage);
if (bytes == 0)
{
return;
}
int index1 = clientmessage.IndexOf(' ');
int index2 = clientmessage.IndexOf(' ', index1 + 1);
if ((index1 == -1) || (index2 == -1))
{
throw new IOException();
}
proxyGui.log("Connecting to Site: " + clientmessage.Substring(index1 + 1, index2 - index1));
proxyGui.log("Connection from " + clientSocket.RemoteEndPoint);
string part1 = clientmessage.Substring(index1 + 1, index2 - index1);
int index3 = part1.IndexOf('/', index1 + 8);
int index4 = part1.IndexOf(' ', index1 + 8);
int index5 = index4 - index3;
sURL = part1.Substring(index1 + 4, (part1.Length - index5) - 8);
try
{
IPHostEntry IPHost = Dns.Resolve(sURL);
proxyGui.log("Request resolved: " + IPHost.HostName);
string[] aliases = IPHost.Aliases;
IPAddress[] address = IPHost.AddressList;
proxyGui.log(address[0].ToString());
IPEndPoint sEndpoint = new IPEndPoint(address[0], 80);
Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPsocket.Connect(sEndpoint);
if (IPsocket.Connected)
proxyGui.log("Socket connect OK");
string GET = clientmessage;
Byte[] ByteGet = ASCII.GetBytes(GET);
IPsocket.Send(ByteGet, ByteGet.Length, 0);
Int32 rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
proxyGui.log("Recieved " + rBytes);
//Buffer = RecvBytes;
String strRetPage = null;
strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
while (rBytes > 0)
{
rBytes = IPsocket.Receive(RecvBytes, RecvBytes.Length, 0);
strRetPage = strRetPage + ASCII.GetString(RecvBytes, 0, rBytes);
}
IPsocket.Shutdown(SocketShutdown.Both);
IPsocket.Close();
sendmessage(clientSocket, strRetPage);
}
catch (Exception exc2)
{
proxyGui.log(exc2.ToString());
}
}
private int readmessage(byte[] ByteArray, ref Socket s, ref String clientmessage)
{
int bytes = s.Receive(ByteArray, 1024, 0);
string messagefromclient = Encoding.ASCII.GetString(ByteArray);
clientmessage = (String)messagefromclient;
return bytes;
}
private void sendmessage(Socket s, string message)
{
Buffer = new Byte[message.Length + 1];
int length = ASCII.GetBytes(message, 0, message.Length, Buffer, 0);
s.Send(Buffer, length, 0);
}
}
const int port = 8080;
TcpListener tcplistener = new TcpListener(port);
private void btnProxy_Click_1(object sender, EventArgs e)
{
proxyOn = true;
log("Listening on port " + port + " " + DateTime.Now.ToString());
tcplistener.Start();
while (proxyOn)
{
Application.DoEvents();
if (tcplistener.Pending())
{
Socket socket = tcplistener.AcceptSocket();
WebProxy2 webproxy = new WebProxy2(socket, this);
webproxy.run();
}
Application.DoEvents();
}
}
private void btnStop_Click_1(object sender, EventArgs e)
{
Application.DoEvents();
proxyOn = false;
tcplistener.Stop();
log("Proxy stopped !!! " + DateTime.Now.ToString());
Application.DoEvents();
}
}
}
It's not clear whether you've implemented your own HTTP proxy protocol (more or less a simple TCP redirection based on the Host header) or if you're using the standard HTTP proxy protocol.
If you go for the standard proxy (which is probably better, unless you have a good reason not to do so), you should be able to use the Proxy-Authenticate, Proxy-Authorization and Proxy-Authentication-Info headers instead of WWW-Authenticate, Authorization and Authentication-Info (respectively) for HTTP Basic or Digest authentication for example.

Categories