C# - Multithreaded TCP Server/Client - c#

I am trying to understand the correct way of how should I make good multithreaded TCP server.
Here is what I have so far:
public class WorldServer
{
public List<ServerClient> clients = new List<ServerClient>();
public int port = 8080;
public TcpListener server;
private bool serverStarted;
private int connectionIncrementor;
private MySQLConnection mySQLConnection = new MySQLConnection();
private MySqlConnection mysqlConn = null;
static void Main(string[] args)
{
WorldServer serverInstance = new WorldServer();
Console.WriteLine("Starting World Server...");
try
{
serverInstance.mysqlConn = new MySqlConnection(serverInstance.mySQLConnection.mysqlConnectionString);
serverInstance.mysqlConn.Open();
Console.WriteLine("Connected to MySQL version: " + serverInstance.mysqlConn.ServerVersion + "\n");
}
catch (Exception e)
{
Console.WriteLine("MySQL Error: " + e.ToString());
}
finally
{
if (serverInstance.mysqlConn != null)
{
serverInstance.mysqlConn.Close();
}
}
serverInstance.clients = new List<ServerClient>();
try
{
serverInstance.server = new TcpListener(IPAddress.Any, serverInstance.port);
serverInstance.server.Start();
serverInstance.StartListening();
serverInstance.serverStarted = true;
Console.WriteLine("Server has been started on port: " + serverInstance.port);
}
catch (Exception e)
{
Console.WriteLine("Socket error: " + e.Message);
}
while (true)
{
serverInstance.Update();
}
}
private void Update()
{
//Console.WriteLine("Call");
if (!serverStarted)
{
return;
}
foreach (ServerClient c in clients.ToList())
{
//Check if TCP is not null
if (c.tcp == null)
return;
// Is the client still connected?
if (!IsConnected(c.tcp))
{
c.tcp.Close();
clients.Remove(c);
Console.WriteLine(c.connectionId + " has disconnected.");
continue;
//Console.WriteLine("Check for connection?\n");
}
else
{
// Check for message from Client.
NetworkStream s = c.tcp.GetStream();
if (s.DataAvailable)
{
string data = c.streamReader.ReadLine();
if (data != null)
{
if (ValidateJSON(data))
{
Thread incomingData = new Thread(() => OnIncomingData(c, data));
incomingData.Start();
}
}
}
//continue;
}
}
}
public bool ValidateJSON(string s)
{
try
{
JToken.Parse(s);
return true;
}
catch (JsonReaderException ex)
{
Trace.WriteLine(ex);
return false;
}
}
private void OnIncomingData(ServerClient c, string data)
{
dynamic json = JsonConvert.DeserializeObject(data);
string header = json.header;
//Console.WriteLine("HEADER ID:" + json.header);
string connId = json.connectionId;
int.TryParse(connId, out int connectionId);
int characterId = 0;
Dictionary<string, string> receivedData = new Dictionary<string, string>();
if (json.data != null)
{
receivedData = json.data.ToObject<Dictionary<string, string>>();
}
if (json.data["characterId"] != null)
{
characterId = json.data["characterId"];
}
string prefix = header.Substring(0, 2);
if (prefix != "1x")
{
Console.WriteLine("Unknown packet: " + data + "\n");
}
else
{
string HeaderPacket = header.Substring(2);
switch (HeaderPacket)
{
default:
Console.WriteLine("Unknown packet: " + data + "\n");
break;
case "004":
Console.WriteLine("Test Packet"); ;
break;
}
}
//Broadcast(null, data, clients);
//Console.WriteLine(c.clientName + " has sent the following message :" + data);
}
public bool IsConnected(TcpClient c)
{
try
{
if (c != null && c.Client != null && c.Client.Connected)
{
if (c.Client.Poll(0, SelectMode.SelectRead))
{
return !(c.Client.Receive(new byte[1], SocketFlags.Peek) == 0);
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
private void StartListening()
{
server.BeginAcceptTcpClient(OnConnection, server);
}
private void OnConnection(IAsyncResult ar)
{
connectionIncrementor++;
TcpListener listener = (TcpListener)ar.AsyncState;
clients.Add(new ServerClient(listener.EndAcceptTcpClient(ar)));
clients[clients.Count - 1].connectionId = connectionIncrementor;
StartListening();
//Send a message to everyone, say someone has connected!
Dictionary<string, object> SendDataBroadcast = new Dictionary<string, object>();
SendDataBroadcast.Add("connectionId", clients[clients.Count - 1].connectionId);
Broadcast("001", SendDataBroadcast, clients[clients.Count - 1].connectionId);
Console.WriteLine(clients[clients.Count - 1].connectionId + " has connected.");
}
public void Broadcast(string header, Dictionary<string, object> data, int cnnId = 0)
{
string jsonData = JsonConvert.SerializeObject(data, Formatting.Indented);
foreach (ServerClient c in clients)
{
try
{
if (header == null)
{
header = "000";
}
JsonData SendData = new JsonData();
SendData.header = "0x" + header;
SendData.data = JObject.Parse(jsonData);
SendData.connectionId = cnnId;
string JSonData = JsonConvert.SerializeObject(SendData);
//Console.WriteLine("SENDING: " + JSonData);
c.streamWriter.WriteLine(JSonData);
c.streamWriter.Flush();
}
catch (Exception e)
{
Console.WriteLine("Write error : " + e.Message + " to client " + c.connectionId);
}
}
}
public void Send(string header, Dictionary<string, object> data, int cnnId)
{
string jsonData = JsonConvert.SerializeObject(data, Formatting.Indented);
foreach (ServerClient c in clients.ToList())
{
if (c.connectionId == cnnId)
{
try
{
//Console.WriteLine("Sending...");
if (header == null)
{
header = "000";
}
JsonData SendData = new JsonData();
SendData.header = "0x" + header;
SendData.data = JObject.Parse(jsonData);
SendData.connectionId = cnnId;
string JSonData = JsonConvert.SerializeObject(SendData);
c.streamWriter.WriteLine(JSonData);
c.streamWriter.Flush();
//Console.WriteLine("Trying to send data to connection id: " + cnnId + " data:" + sendData);
}
catch (Exception e)
{
Console.WriteLine("Write error : " + e.Message + " to client " + c.connectionId);
}
}
}
}
}
public class ServerClient
{
public TcpClient tcp;
public StreamReader streamReader;
public StreamWriter streamWriter;
public int accountId;
public int connectionId;
public ServerClient(TcpClient clientSocket)
{
tcp = clientSocket;
streamReader = new StreamReader(tcp.GetStream(), false);
streamWriter = new StreamWriter(tcp.GetStream());
clientSocket.NoDelay = true;
}
}
The TCP server works. However I am really not sure if this is the best approach I can take.
Have I made the multi-threading well ? Probably not. I would like to receive advices where i can make it better.
Do I need to create a new thread on every OnIncomingData ?
Do I need to create new thread on every Send and Broadcast ?
Very often I receive error here foreach (ServerClient c in clients.ToList()). What can be the cause of it ?
What parts of the client is good to be multithreaded also aka the listening function for incoming data or the sending functions?
All advices are most welcome!

I wrote code for an OP last year that was a TCP Server and wrote to a SQL Server. I modified that code a few minutes ago to make it more general. The changes are not tested but original code worked very well. I used Asynchronous Send and Receive. I also used a fifo to send messages from the transport layer to the application layer. See code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Data;
using System.Data.SqlClient;
using System.Timers;
using System.Threading;
namespace TCP_Server
{
public class StateObject
{
public long connectionNumber = -1;
public Socket workSocket { get; set; }
public byte[] buffer { get; set; }
public int fifoCount { get; set; }
}
public enum PROCESS_STATE
{
ACCEPT,
READ,
PROCESS,
UNPACK
}
public enum UNPACK_STATUS
{
ERROR,
NOT_ENOUGH_BYTES,
BAD_CRC,
GOOD_MESSAGE,
DEFAULT
}
public enum PROTOCOL_NUMBER
{
LOGIN_MESSAGE,
NONE
}
class Program
{
const string IP = "127.0.0.1";
const int PORT = 8841;
const Boolean test = true;
static void Main(string[] args)
{
Server server = new Server(IP, PORT, test);
Console.WriteLine("Connection Ended");
}
}
public class Server
{
const int BUFFER_SIZE = 1024;
const string CONNECT_STRING = #"Data Source=.\SQLEXPRESS;Initial Catalog=MyDataTable;Integrated Security=SSPI;";
const string LOGIN_INSERT_COMMMAND_TEXT = "use MyTable INSERT INTO Login (TerminalID,Date) VALUES(#TerminalID,#Date)";
const string LOCATION_INSERT_COMMMAND_TEXT = "INSERT INTO MyTable (CurrTime, Message)" +
"VALUES (#CurrTime, #Message)";
static SqlConnection conn = null;
static SqlCommand cmdLogin = null;
static SqlCommand cmdLocation = null;
static long connectionNumber = 0;
//mapping of connection number to StateObject
static Dictionary<long, KeyValuePair<List<byte>, StateObject>> connectionDict = new Dictionary<long, KeyValuePair<List<byte>, StateObject>>();
//fifo contains list of connections number wait with receive data
public static List<long> fifo = new List<long>();
public static AutoResetEvent allDone = new AutoResetEvent(false);
public static AutoResetEvent acceptDone = new AutoResetEvent(false);
public enum DATABASE_MESSAGE_TYPE
{
LOGIN,
LOCATION
}
public class WriteDBMessage
{
public DATABASE_MESSAGE_TYPE message { get; set; }
}
public class WriteDBMessageLogin : WriteDBMessage
{
public DateTime date { get; set; }
public string message { get; set; }
}
public class WriteDBMessageLocation : WriteDBMessage
{
public DateTime currTime { get; set; }
public byte[] message { get; set; }
}
public static class WriteDBAsync
{
public enum Mode
{
READ,
WRITE
}
public static List<WriteDBMessage> fifo = new List<WriteDBMessage>();
public static System.Timers.Timer timer = null;
public static void WriteDatabase()
{
timer = new System.Timers.Timer(1000);
timer.Elapsed += Timer_Elapsed;
timer.Start();
}
public static WriteDBMessage ReadWriteFifo(Mode mode, WriteDBMessage message)
{
Object thisLock2 = new Object();
lock (thisLock2)
{
switch (mode)
{
case Mode.READ:
if (fifo.Count > 0)
{
message = fifo[0];
fifo.RemoveAt(0);
}
break;
case Mode.WRITE:
fifo.Add(message);
break;
}
}
return message;
}
static void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
timer.Enabled = false;
WriteDBMessage row = null;
int rowsAdded = 0;
uint number = 0;
try
{
while ((row = ReadWriteFifo(Mode.READ, null)) != null)
{
switch (row.message)
{
case DATABASE_MESSAGE_TYPE.LOGIN:
cmdLogin.Parameters["#Date"].Value = ((WriteDBMessageLogin)row).date;
rowsAdded = cmdLogin.ExecuteNonQuery();
break;
}
}
}
catch (Exception ex)
{
//Console.WriteLine("Error : '{0}'", ex.Message);
}
timer.Enabled = true;
}
}
public Server(string IP, int port, Boolean test)
{
try
{
conn = new SqlConnection(CONNECT_STRING);
conn.Open();
cmdLogin = new SqlCommand(LOGIN_INSERT_COMMMAND_TEXT, conn);
cmdLogin.Parameters.Add("#TerminalID", SqlDbType.NVarChar, 8);
cmdLogin.Parameters.Add("#Date", SqlDbType.DateTime);
cmdLocation = new SqlCommand(LOCATION_INSERT_COMMMAND_TEXT, conn);
cmdLocation.Parameters.Add("#IMEI", SqlDbType.NVarChar, 50);
cmdLocation.Parameters.Add("#TrackTime", SqlDbType.DateTime);
cmdLocation.Parameters.Add("#currTime", SqlDbType.DateTime);
cmdLocation.Parameters.Add("#Longitude", SqlDbType.NChar, 50);
cmdLocation.Parameters.Add("#Lattitude", SqlDbType.NVarChar, 50);
cmdLocation.Parameters.Add("#speed", SqlDbType.Float);
}
catch (Exception ex)
{
Console.WriteLine("Error : '{0}'", ex.Message);
//Console.ReadLine();
return;
}
try
{
//initialize the timer for writing to database.
WriteDBAsync.WriteDatabase();
StartListening(IP, port, test);
// Open 2nd listener to simulate two devices, Only for testing
//StartListening(IP, port + 1, test);
ProcessMessages();
}
catch (Exception ex)
{
Console.WriteLine("Error : '{0}'", ex.Message);
//Console.ReadLine();
return;
}
}
public void StartListening(string IP, int port, Boolean test)
{
try
{
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.GetHostEntry(IP); //Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
//IPAddress local = IPAddress.Parse(IP);
IPEndPoint localEndPoint = null;
if (test)
{
localEndPoint = new IPEndPoint(IPAddress.Any, port);
}
else
{
localEndPoint = new IPEndPoint(ipAddress, port);
}
// Create a TCP/IP socket.
Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
allDone.Reset();
acceptDone.Reset();
listener.Bind(localEndPoint);
listener.Listen(100);
//login code, wait for 1st message
Console.WriteLine("Wait 5 seconds for login message");
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
public void ProcessMessages()
{
UInt16 sendCRC = 0;
DateTime date;
int year = 0;
int month = 0;
int day = 0;
int hour = 0;
int minute = 0;
int second = 0;
KeyValuePair<List<byte>, StateObject> byteState;
KeyValuePair<UNPACK_STATUS, byte[]> status;
byte[] receiveMessage = null;
StateObject state = null;
byte[] serialNumber = null;
byte[] serverFlagBit = null;
byte[] stringArray = null;
string stringMessage = "";
byte lengthOfCommand = 0;
PROTOCOL_NUMBER protocolNumber = PROTOCOL_NUMBER.NONE;
try
{
Boolean firstMessage = true;
acceptDone.Set();
//loop forever
while (true)
{
allDone.WaitOne();
//read fifo until empty
while (true)
{
//read one connection until buffer doesn't contain any more packets
byteState = ReadWrite(PROCESS_STATE.PROCESS, null, null, -1);
if (byteState.Value.fifoCount == -1) break;
state = byteState.Value;
while (true)
{
status = Unpack(byteState);
if (status.Key == UNPACK_STATUS.NOT_ENOUGH_BYTES)
break;
if (status.Key == UNPACK_STATUS.ERROR)
{
Console.WriteLine("Error : Bad Receive Message, Data");
break;
}
//message is 2 start bytes + 1 byte (message length) + 1 byte message length + 2 end bytes
receiveMessage = status.Value;
int messageLength = receiveMessage[2];
Console.WriteLine("Status : '{0}', Receive Message : '{1}'", status.Key == UNPACK_STATUS.GOOD_MESSAGE ? "Good" : "Bad", BytesToString(receiveMessage.Take(messageLength + 5).ToArray()));
if (status.Key != UNPACK_STATUS.GOOD_MESSAGE)
{
break;
}
else
{
if (firstMessage)
{
if (receiveMessage[3] != 0x01)
{
Console.WriteLine("Error : Expected Login Message : '{0}'", BytesToString(receiveMessage));
break;
}
firstMessage = false;
}
//skip start bytes, message length. then go back 4 bytes (CRC and serial number)
serialNumber = receiveMessage.Skip(2 + 1 + messageLength - 4).Take(2).ToArray();
protocolNumber = (PROTOCOL_NUMBER)receiveMessage[3];
Console.WriteLine("Protocol Number : '{0}'", protocolNumber.ToString());
switch (protocolNumber)
{
case PROTOCOL_NUMBER.LOGIN_MESSAGE:
break;
} //end switch
}// End if
} //end while
}//end while fifo > 0
allDone.Reset();
}//end while true
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
static string BytesToString(byte[] bytes)
{
return string.Join("", bytes.Select(x => x.ToString("X2")));
}
static KeyValuePair<UNPACK_STATUS, byte[]> Unpack(KeyValuePair<List<byte>, StateObject> bitState)
{
List<byte> working_buffer = bitState.Key;
//return null indicates an error
if (working_buffer.Count() < 3) return new KeyValuePair<UNPACK_STATUS, byte[]>(UNPACK_STATUS.NOT_ENOUGH_BYTES, null);
int len = working_buffer[2];
if (working_buffer.Count < len + 5) return new KeyValuePair<UNPACK_STATUS, byte[]>(UNPACK_STATUS.NOT_ENOUGH_BYTES, null);
// check start and end bytes
// remove message fro workig buffer and dictionary
KeyValuePair<List<byte>, StateObject> byteState = ReadWrite(PROCESS_STATE.UNPACK, null, null, bitState.Value.connectionNumber);
if (byteState.Key.Count == 0) return new KeyValuePair<UNPACK_STATUS, byte[]>(UNPACK_STATUS.ERROR, null);
List<byte> packet = byteState.Key;
//crc test
byte[] crc = packet.Skip(len + 1).Take(2).ToArray();
ushort crcShort = (ushort)((crc[0] << 8) | crc[1]);
//skip start bytes, crc, and end bytes
return new KeyValuePair<UNPACK_STATUS, byte[]>(UNPACK_STATUS.GOOD_MESSAGE, packet.ToArray());
}
static KeyValuePair<List<byte>, StateObject> ReadWrite(PROCESS_STATE ps, Socket handler, IAsyncResult ar, long unpackConnectionNumber)
{
KeyValuePair<List<byte>, StateObject> byteState = new KeyValuePair<List<byte>, StateObject>(); ;
StateObject stateObject = null;
int bytesRead = -1;
int workingBufferLen = 0;
List<byte> working_buffer = null;
byte[] buffer = null;
Object thisLock1 = new Object();
lock (thisLock1)
{
switch (ps)
{
case PROCESS_STATE.ACCEPT:
acceptDone.WaitOne();
acceptDone.Reset();
stateObject = new StateObject();
stateObject.buffer = new byte[BUFFER_SIZE];
connectionDict.Add(connectionNumber, new KeyValuePair<List<byte>, StateObject>(new List<byte>(), stateObject));
stateObject.connectionNumber = connectionNumber++;
stateObject.workSocket = handler;
byteState = new KeyValuePair<List<byte>, StateObject>(null, stateObject);
acceptDone.Set();
break;
case PROCESS_STATE.READ:
//catch when client disconnects
//wait if accept is being called
//acceptDone.WaitOne();
try
{
stateObject = ar.AsyncState as StateObject;
// Read data from the client socket.
bytesRead = stateObject.workSocket.EndReceive(ar);
if (bytesRead > 0)
{
byteState = connectionDict[stateObject.connectionNumber];
buffer = new byte[bytesRead];
Array.Copy(byteState.Value.buffer, buffer, bytesRead);
byteState.Key.AddRange(buffer);
}
//only put one instance of connection number into fifo
if (!fifo.Contains(byteState.Value.connectionNumber))
{
fifo.Add(byteState.Value.connectionNumber);
}
}
catch (Exception ex)
{
//will get here if client disconnects
fifo.RemoveAll(x => x == byteState.Value.connectionNumber);
connectionDict.Remove(byteState.Value.connectionNumber);
byteState = new KeyValuePair<List<byte>, StateObject>(new List<byte>(), null);
}
break;
case PROCESS_STATE.PROCESS:
if (fifo.Count > 0)
{
//get message from working buffer
//unpack will later delete message
//remove connection number from fifo
// the list in the key in known as the working buffer
byteState = new KeyValuePair<List<byte>, StateObject>(connectionDict[fifo[0]].Key, connectionDict[fifo[0]].Value);
fifo.RemoveAt(0);
//put a valid value in fifoCount so -1 below can be detected.
byteState.Value.fifoCount = fifo.Count;
}
else
{
//getting here is normal when there is no more work to be performed
//set fifocount to zero so rest of code know fifo was empty so code waits for next receive message
byteState = new KeyValuePair<List<byte>, StateObject>(null, new StateObject() { fifoCount = -1 });
}
break;
case PROCESS_STATE.UNPACK:
try
{
working_buffer = connectionDict[unpackConnectionNumber].Key;
workingBufferLen = working_buffer[2];
if ((working_buffer[0] != 0x78) && (working_buffer[1] != 0x78) && (working_buffer[workingBufferLen + 3] != 0x0D) && (working_buffer[workingBufferLen + 4] != 0x0A))
{
working_buffer.Clear();
return new KeyValuePair<List<byte>, StateObject>(new List<byte>(), null);
}
List<byte> packet = working_buffer.GetRange(0, workingBufferLen + 5);
working_buffer.RemoveRange(0, workingBufferLen + 5);
byteState = new KeyValuePair<List<byte>, StateObject>(packet, null);
}
catch (Exception ex)
{
int testPoint = 0;
}
break;
}// end switch
}
return byteState;
}
public static void AcceptCallback(IAsyncResult ar)
{
try
{
// Get the socket that handles the client request.
// Retrieve the state object and the handler socket
// from the asynchronous state object.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = ReadWrite(PROCESS_STATE.ACCEPT, handler, ar, -1).Value;
handler.BeginReceive(state.buffer, 0, BUFFER_SIZE, 0,
new AsyncCallback(ReadCallback), state);
}
catch (Exception ex)
{
int myerror = -1;
}
}
public static void ReadCallback(IAsyncResult ar)
{
try
{
StateObject state = ar.AsyncState as StateObject;
Socket handler = state.workSocket;
// Read data from the client socket.
KeyValuePair<List<byte>, StateObject> byteState = ReadWrite(PROCESS_STATE.READ, handler, ar, -1);
if (byteState.Value != null)
{
allDone.Set();
handler.BeginReceive(state.buffer, 0, BUFFER_SIZE, 0,
new AsyncCallback(ReadCallback), state);
}
else
{
int testPoint = 0;
}
}
catch (Exception ex)
{
int myerror = -1;
}
// Signal the main thread to continue.
allDone.Set();
}
}
}

Related

Connection Refused to Server when using SOCKS5 Proxy and Tor C#

I have this code that uses SOCKS5 Proxy to connect to Tor and then tries to connect the Client to the remote Server on a VPS machine that runs a C# server. The problem is I can't establish the connection.
The Server is written in C#, it listens to connections on port 1604 and it's a hidden service meaning any traffic that comes trough port 1604 will be redirected to 127.0.0.1:1604 where my server listens.
Test 1
When I connected directly to test if my client get make a HTTP request to a webserver on port 80 it works, when i use the .onion address to access the webserver it works too. When I check yougetsignal using the remote machine IP it's open as you can see
Also here is the torrc FILE config
GREAT EVERYTHING WORKS SO FAR, BUT WAIT A SECOND
Test 2
When I try to connect the client to my standalone server (not a webserver) directly it works like I expected it to do, but when i try to use the HOSTNAME generated by tor.exe (the same HOSTNAME I used in Test 1) i get Connection Refused and General SOCKS server failure.
I can't find what I'm doing wrong and why I can't reach my server, please assist me and thank you for your time.
The Code
Client
Socks Code
public class ConnectionException : ApplicationException
{
public ConnectionException(string message)
: base(message)
{
}
}
/// <summary>
/// Provides sock5 functionality to clients (Connect only).
/// </summary>
public class SocksProxy
{
private SocksProxy() { }
#region ErrorMessages
private static string[] errorMsgs = {
"Operation completed successfully.",
"General SOCKS server failure.",
"Connection not allowed by ruleset.",
"Network unreachable.",
"Host unreachable.",
"Connection refused.",
"TTL expired.",
"Command not supported.",
"Address type not supported.",
"Unknown error."
};
#endregion
public static Socket ConnectToSocks5Proxy(string proxyAdress, ushort proxyPort, string destAddress, ushort destPort,
string userName, string password)
{
IPAddress destIP = null;
IPAddress proxyIP = null;
byte[] request = new byte[257];
byte[] response = new byte[257];
ushort nIndex;
try
{
proxyIP = IPAddress.Parse(proxyAdress);
}
catch (FormatException)
{ // get the IP address
proxyIP = Dns.GetHostByAddress(proxyAdress).AddressList[0];
}
// Parse destAddress (assume it in string dotted format "212.116.65.112" )
try
{
destIP = IPAddress.Parse(destAddress);
}
catch (FormatException)
{
// wrong assumption its in domain name format "www.microsoft.com"
}
IPEndPoint proxyEndPoint = new IPEndPoint(proxyIP, proxyPort);
// open a TCP connection to SOCKS server...
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Connect(proxyEndPoint);
nIndex = 0;
request[nIndex++] = 0x05; // Version 5.
request[nIndex++] = 0x01; // 2 Authentication methods are in packet...
request[nIndex++] = 0x00; // NO AUTHENTICATION REQUIRED
//request[nIndex++] = 0x02; // USERNAME/PASSWORD
// Send the authentication negotiation request...
s.Send(request, nIndex, SocketFlags.None);
// Receive 2 byte response...
int nGot = s.Receive(response, 2, SocketFlags.None);
if (nGot != 2)
throw new ConnectionException("Bad response received from proxy server.");
if (response[1] == 0xFF)
{ // No authentication method was accepted close the socket.
s.Close();
throw new ConnectionException("None of the authentication method was accepted by proxy server.");
}
byte[] rawBytes;
if (/*response[1]==0x02*/false)
{//Username/Password Authentication protocol
nIndex = 0;
request[nIndex++] = 0x05; // Version 5.
// add user name
request[nIndex++] = (byte)userName.Length;
rawBytes = Encoding.Default.GetBytes(userName);
rawBytes.CopyTo(request, nIndex);
nIndex += (ushort)rawBytes.Length;
// add password
request[nIndex++] = (byte)password.Length;
rawBytes = Encoding.Default.GetBytes(password);
rawBytes.CopyTo(request, nIndex);
nIndex += (ushort)rawBytes.Length;
// Send the Username/Password request
s.Send(request, nIndex, SocketFlags.None);
// Receive 2 byte response...
nGot = s.Receive(response, 2, SocketFlags.None);
if (nGot != 2)
throw new ConnectionException("Bad response received from proxy server.");
if (response[1] != 0x00)
throw new ConnectionException("Bad Usernaem/Password.");
}
// This version only supports connect command.
// UDP and Bind are not supported.
// Send connect request now...
nIndex = 0;
request[nIndex++] = 0x05; // version 5.
request[nIndex++] = 0x01; // command = connect.
request[nIndex++] = 0x00; // Reserve = must be 0x00
if (destIP != null)
{// Destination adress in an IP.
switch (destIP.AddressFamily)
{
case AddressFamily.InterNetwork:
// Address is IPV4 format
request[nIndex++] = 0x01;
rawBytes = destIP.GetAddressBytes();
rawBytes.CopyTo(request, nIndex);
nIndex += (ushort)rawBytes.Length;
break;
case AddressFamily.InterNetworkV6:
// Address is IPV6 format
request[nIndex++] = 0x04;
rawBytes = destIP.GetAddressBytes();
rawBytes.CopyTo(request, nIndex);
nIndex += (ushort)rawBytes.Length;
break;
}
}
else
{// Dest. address is domain name.
request[nIndex++] = 0x03; // Address is full-qualified domain name.
request[nIndex++] = Convert.ToByte(destAddress.Length); // length of address.
rawBytes = Encoding.Default.GetBytes(destAddress);
rawBytes.CopyTo(request, nIndex);
nIndex += (ushort)rawBytes.Length;
}
// using big-edian byte order
byte[] portBytes = BitConverter.GetBytes(destPort);
for (int i = portBytes.Length - 1; i >= 0; i--)
request[nIndex++] = portBytes[i];
// send connect request.
s.Send(request, nIndex, SocketFlags.None);
// Point of breaking !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
s.Receive(response); // Get variable length response...
if (response[1] != 0x00)
throw new ConnectionException(errorMsgs[response[1]]); // Crashes the Client !!!!!!!!!!!
// Success Connected...
return s;
}
}
Main Code
Socket s;
// s = SocksProxy.ConnectToSocks5Proxy("127.0.0.1", 9150, "xoembwt22tmxseask2qyuudbxoubiuafw54klkwuktvv6bxbhrdffqyd.onion", 1604, "U$er", "Pa$$word!"); //NOT WORKING
//s = SocksProxy.ConnectToSocks5Proxy("127.0.0.1", 9150, "xoembwt22tmxseask2qyuudbxoubiuafw54klkwuktvv6bxbhrdffqyd.onion", 80, "", ""); // WORKING
s = SocksProxy.ConnectToSocks5Proxy("127.0.0.1", 9150, "xoembwt22tmxseask2qyuudbxoubiuafw54klkwuktvv6bxbhrdffqyd.onion", 1604, "", ""); //NOT WORKING
// s = SocksProxy.ConnectToSocks5Proxy("127.0.0.1", 9150, "X.X.X.100", 1604, "", ""); //WORKING
//client is a TCPClient
client.Client = s;
Server
Server Class
public class Server : Common
{
private static int counter;
private readonly ConcurrentDictionary<int, ClientToken> clients = new ConcurrentDictionary<int, ClientToken>();
public TcpListener listener;
private Thread listenerThread;
public bool Active => listenerThread != null && listenerThread.IsAlive;
public static int NextConnectionId()
{
int id = Interlocked.Increment(ref counter);
if (id == int.MaxValue) throw new Exception("connection id limit reached: " + id);
return id;
}
private void Listen(int port)
{
try
{
listener = new TcpListener(new IPEndPoint(IPAddress.Any, port));
listener.Server.NoDelay = NoDelay;
listener.Server.SendTimeout = SendTimeout;
listener.Start();
Logger.Log("Server: listening port=" + port);
while (true)
{
TcpClient client = listener.AcceptTcpClient();
int connectionId = NextConnectionId();
ClientToken token = new ClientToken(client);
clients[connectionId] = token;
Thread sendThread = new Thread(() =>
{
try
{
SendLoop(connectionId, client, token.sendQueue, token.sendPending);
}
catch (ThreadAbortException) { }
catch (Exception exception)
{
Logger.LogError("Server send thread exception: " + exception);
}
});
sendThread.IsBackground = true;
sendThread.Start();
Thread receiveThread = new Thread(() =>
{
try
{
ReceiveLoop(connectionId, client, receiveQueue, MaxMessageSize);
clients.TryRemove(connectionId, out ClientToken _);
sendThread.Interrupt();
}
catch (Exception exception)
{
Logger.LogError("Server client thread exception: " + exception);
}
});
receiveThread.IsBackground = true;
receiveThread.Start();
}
}
catch (ThreadAbortException exception)
{
Logger.Log("Server thread aborted. That's okay. " + exception);
}
catch (SocketException exception)
{
Logger.Log("Server Thread stopped. That's okay. " + exception);
}
catch (Exception exception)
{
Logger.LogError("Server Exception: " + exception);
}
}
public bool Start(int port)
{
if (Active) return false;
receiveQueue = new ConcurrentQueue<Message>();
Logger.Log("Server: Start port=" + port);
listenerThread = new Thread(() => { Listen(port); });
listenerThread.IsBackground = true;
listenerThread.Priority = ThreadPriority.BelowNormal;
listenerThread.Start();
return true;
}
public void Stop()
{
if (!Active) return;
Logger.Log("Server: stopping...");
listener?.Stop();
listenerThread?.Interrupt();
listenerThread = null;
foreach (KeyValuePair<int, ClientToken> kvp in clients)
{
TcpClient client = kvp.Value.client;
try
{
client.GetStream().Close();
}
catch { }
client.Close();
}
clients.Clear();
}
public bool Send(int connectionId, byte[] data)
{
if (data.Length <= MaxMessageSize)
{
ClientToken token;
if (clients.TryGetValue(connectionId, out token))
{
token.sendQueue.Enqueue(data);
token.sendPending.Set();
return true;
}
Logger.Log("Server.Send: invalid connectionId: " + connectionId);
return false;
}
Logger.LogError("Client.Send: message too big: " + data.Length + ". Limit: " + MaxMessageSize);
return false;
}
public string GetClientAddress(int connectionId)
{
ClientToken token;
if (clients.TryGetValue(connectionId, out token))
return ((IPEndPoint) token.client.Client.RemoteEndPoint).Address.ToString();
return "";
}
public bool Disconnect(int connectionId)
{
ClientToken token;
if (clients.TryGetValue(connectionId, out token))
{
token.client.Close();
Logger.Log("Server.Disconnect connectionId:" + connectionId);
return true;
}
return false;
}
private class ClientToken
{
public readonly TcpClient client;
public readonly ManualResetEvent sendPending = new ManualResetEvent(false);
public readonly SafeQueue<byte[]> sendQueue = new SafeQueue<byte[]>();
public ClientToken(TcpClient client)
{
this.client = client;
}
}
}
Common
public abstract class Common
{
public static int messageQueueSizeWarning = 100000;
public int MaxMessageSize = 2147483647;
public bool NoDelay = true;
protected ConcurrentQueue<Message> receiveQueue = new ConcurrentQueue<Message>();
public int SendTimeout = 5000;
public int ReceiveQueueCount => receiveQueue.Count;
public bool GetNextMessage(out Message message)
{
return receiveQueue.TryDequeue(out message);
}
protected static bool SendMessagesBlocking(NetworkStream stream, byte[][] messages)
{
try
{
int packetSize = 0;
for (int i = 0; i < messages.Length; ++i)
packetSize += sizeof(int) + messages[i].Length;
byte[] payload = new byte[packetSize];
int position = 0;
for (int i = 0; i < messages.Length; ++i)
{
byte[] header = Utils.IntToBytesBigEndian(messages[i].Length);
Array.Copy(header, 0, payload, position, header.Length);
Array.Copy(messages[i], 0, payload, position + header.Length, messages[i].Length);
position += header.Length + messages[i].Length;
}
stream.Write(payload, 0, payload.Length);
return true;
}
catch (Exception exception)
{
Logger.Log("Send: stream.Write exception: " + exception);
return false;
}
}
protected static bool ReadMessageBlocking(NetworkStream stream, int MaxMessageSize, out byte[] content)
{
content = null;
byte[] header = new byte[4];
if (!stream.ReadExactly(header, 4))
return false;
int size = Utils.BytesToIntBigEndian(header);
if (size <= MaxMessageSize)
{
content = new byte[size];
return stream.ReadExactly(content, size);
}
Logger.LogWarning("ReadMessageBlocking: possible allocation attack with a header of: " + size + " bytes.");
return false;
}
protected static void ReceiveLoop(int connectionId, TcpClient client, ConcurrentQueue<Message> receiveQueue,
int MaxMessageSize)
{
NetworkStream stream = client.GetStream();
DateTime messageQueueLastWarning = DateTime.Now;
try
{
receiveQueue.Enqueue(new Message(connectionId, EventType.Connected, null));
while (true)
{
byte[] content;
if (!ReadMessageBlocking(stream, MaxMessageSize, out content))
break;
receiveQueue.Enqueue(new Message(connectionId, EventType.Data, content));
if (receiveQueue.Count > messageQueueSizeWarning)
{
TimeSpan elapsed = DateTime.Now - messageQueueLastWarning;
if (elapsed.TotalSeconds > 10)
{
Logger.LogWarning("ReceiveLoop: messageQueue is getting big(" + receiveQueue.Count +
"), try calling GetNextMessage more often. You can call it more than once per frame!");
messageQueueLastWarning = DateTime.Now;
}
}
}
}
catch (Exception exception)
{
Logger.Log("ReceiveLoop: finished receive function for connectionId=" + connectionId + " reason: " +
exception);
}
stream.Close();
client.Close();
receiveQueue.Enqueue(new Message(connectionId, EventType.Disconnected, null));
}
protected static void SendLoop(int connectionId, TcpClient client, SafeQueue<byte[]> sendQueue,
ManualResetEvent sendPending)
{
NetworkStream stream = client.GetStream();
try
{
while (client.Connected)
{
sendPending.Reset();
byte[][] messages;
if (sendQueue.TryDequeueAll(out messages))
if (!SendMessagesBlocking(stream, messages))
return;
sendPending.WaitOne();
}
}
catch (ThreadAbortException) { }
catch (ThreadInterruptedException) { }
catch (Exception exception)
{
Logger.Log("SendLoop Exception: connectionId=" + connectionId + " reason: " + exception);
}
}
}

How to transfer the data from Chrome Browser Console onto C# file

We are getting joint data in JSON Objects format. The data is streaming live on the Chrome Console as you can see in the picture.
How do we take this data (from the Chrome Console) and send it over to a C# file on the computer in real-time?
From Console: JSON Object data from kinectv2
Here is some basic c# websocket code, it doesnt have to convert the data it receives to a string. I was just testing some stuff
C# simple websocket connection
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows;
public partial class MainWindow : Window
{
private Websocket_listen _listener;
public MainWindow()
{
_listener = new Websocket_listen("127.0.0.1", 13000);
_listener.StringReceived += _listener_StringReceived;
_listener.Start();
}
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
_running = false;
_listener.Stop();
}
private void _listener_StringReceived(string received)
{
}
}
public class Websocket_listen
{
public readonly int port = 13000;
public readonly IPAddress localAddr;
private TcpListener server = null;
private TcpClient client = null;
private NetworkStream stream = null;
private bool connected = false;
private byte[] bytes = new byte[2048];
private byte[] _last_key = new byte[4];
private int _last_message_length;
private bool read_more_message;
private Thread _current_thread;
private bool _running = true;
private int _received = 0;
private StringBuilder _results = new StringBuilder();
public event Action<string> StringReceived = null;
public Websocket_listen(string ipaddress, int port)
{
this.port = port;
localAddr = IPAddress.Parse(ipaddress);
server = new TcpListener(localAddr, port);
}
public void _running_loop()
{
while (_running)
{
try
{
server.Server.ReceiveTimeout = 5000;
server.Server.SendTimeout = 5000;
client = server.AcceptTcpClient();
// Get a stream object for reading and writing
stream = client.GetStream();
}
catch (Exception ex)
{
continue;
}
while (_running)
{
try
{
try
{
l.AcquireWriterLock(-1);
if (messsages.Count > 0)
{
byte[] msg = System.Text.Encoding.ASCII.GetBytes(messsages[0]);
//byte[] msg = System.Text.Encoding.ASCII.GetBytes("Connected to " + Environment.MachineName);
Array.Copy(msg, 0, bytes, 2, msg.Length);
bytes[0] = 0x81;
bytes[1] = (byte)msg.Length;
// Send back a response.
stream.Write(bytes, 0, msg.Length + 2);
messsages.RemoveAt(0);
}
}
finally
{
l.ReleaseWriterLock();
}
}
catch { }
try
{
_received = stream.Read(bytes, 0, bytes.Length);
}
catch
{
continue;
}
if (_received == 0)
continue;
if (!connected)
{
_is_connection();
continue;
}
if (!_parse_message())
break;
}
}
try
{
stream.Close();
client.Close();
}
catch (Exception ex)
{
}
}
private bool _parse_message()
{
int offset = 0;
int message_length = 0;
if (read_more_message)
{
_last_message_length -= bytes.Length;
message_length = _last_message_length;
if (message_length < bytes.Length)
message_length += 8;
}
else
{
_results.Clear();
var trigger = bytes[0];
var magic_byte = bytes[1];
bool is_text = (0x1 & trigger) != 0;
bool is_fin = (0x80 & trigger) != 0;
if (trigger == 0x88)
{
connected = false;
return false;
}
/*
text = 0x81
binary = 0x82
close 0x88
ping 0x89
pong -0x8A
*/
if (!is_fin)
{
return true;
}
if (!is_text)
{
return true;
}
//If the second byte minus 128 is between 0 and 125, this is the length of message.
//If it is 126, the following 2 bytes (16-bit unsigned integer), if 127, the following 8 bytes (64-bit unsigned integer) are the length.
var r = magic_byte - 128;
var key_starts_at = 0;
if (r <= 125)
{
key_starts_at = 2;
message_length = r;
}
else if (r == 126)
{
key_starts_at = 4;
message_length = BitConverter.ToUInt16(new byte[] { bytes[3], bytes[2] }, 0);
}
else if (r == 127)
{
key_starts_at = 10;
for (var m = 7; m >= 0; --m)
{
message_length += bytes[m] << (8 * (7 - m));
}
}
else
{
// not documented
}
//// because its encoded
_last_message_length = message_length;
Array.Copy(bytes, key_starts_at, _last_key, 0, 4);
offset = key_starts_at + 4;
}
for (var mx = 0; mx < message_length && offset + mx < bytes.Length; ++mx)
{
bytes[offset + mx] = (byte)(bytes[offset + mx] ^ _last_key[mx % 4]);
}
var new_result = System.Text.Encoding.ASCII.GetString(bytes, offset, Math.Min(message_length, bytes.Length - offset));
_results.Append(new_result);
read_more_message = message_length > bytes.Length;
if (!read_more_message)
{
try
{
StringReceived?.Invoke(_results.ToString());
}
catch (Exception ex)
{
}
}
return true;
}
private void _is_connection()
{
try
{
string data = System.Text.Encoding.ASCII.GetString(bytes, 0, _received);
if (!new Regex("^GET").IsMatch(data))
return;
Byte[] response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + Environment.NewLine
+ "Connection: Upgrade" + Environment.NewLine
+ "Upgrade: websocket" + Environment.NewLine
+ "Sec-WebSocket-Accept: " + Convert.ToBase64String(
SHA1.Create().ComputeHash(
Encoding.UTF8.GetBytes(
new Regex("Sec-WebSocket-Key: (.*)").Match(data).Groups[1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
)
)
) + Environment.NewLine
+ Environment.NewLine);
stream.Write(response, 0, response.Length);
connected = true;
}
catch (Exception ex)
{
}
}
public void Stop()
{
_running = false;
}
public void Start()
{
// Start listening for client requests.
server.Start();
_current_thread = new Thread(new ThreadStart(_running_loop));
_current_thread.Start();
}
ReaderWriterLock l = new ReaderWriterLock();
List<string> messsages = new List<string>();
internal void Send(string msg)
{
try
{
l.AcquireWriterLock(-1);
messsages.Add(msg);
}
catch
{
}
finally
{
l.ReleaseWriterLock();
}
}
}
not a very robust javascript simple websocket to connect to c# with the same port
try {
var isopen = false;
connection = new WebSocket('ws://127.0.0.1:13000');
// When the connection is open, send some data to the server
connection.onopen = function () {
isopen = true;
connection.send('Ping'); // Send the message 'Ping' to the server
$('#open_messages').html("connection made\r\n<br>");
$('#socket_errors').html("");
};
// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ', error);
$('#socket_errors').html(error.currentTarget.url + " failed\r\n<br><button id=\"reconnect\">Try to connect</button>");
};
// Log messages from the server
connection.onmessage = function (e) {
console.log('Server: ', e);
$('#messages').append(e.data + "\r\n<br>");
};
connection.onclose = function(x) {
console.log('closed ', x);
$('#open_messages').html("Disconnected\r\n<br>");
$('#socket_errors').html("<button id=\"reconnect\">Connect</button>");
};
} catch (err) {
console.log(err);
}
That should get you started sending data back and forth, but will probably need extra exception handling.
Not sure if sending strings across is efficient, by you could probably change the data later.

C#, tcpClient to Multiple IP Address but on the same port

Scenario:
I have multiple machines, each wit hit's own IP, that run a tcpServer, all on the same port. During each transaction data is sent if the tcpServer port is opened. It, looks for a client before opening the port.
What I Need:
I'm writing an app, that needs to:
1. Check through the list of IP's if they are availible
2. Open a tcpClient port to each machine IP, (all on the same ports)
3. After every specified time make sure the connection is open, if not reopen connection.
Future:
I use an XMl file to give the SQL data which is used to get the list of machines and the port to listen on. In this xml is a udp setting as well, if this is yes, then the data being sent, must be received and redirected to a specified UDP port.
The Class:
public static void tcpListen(IPAddress server, int port)
{
try
{
TcpListener listener = new TcpListener(server, port);
listener.AcceptTcpClient();
listener.Start();
while (true)
{
Socket client = listener.AcceptSocket();
var childSocketThread = new Thread(() =>
{
byte[] data = new byte[100];
int size = client.Receive(data);
for (int i = 0; i < size; i++)
feedback = server + ":" + port + ": " + Convert.ToChar(data[i]);
using (StreamWriter w = File.AppendText("TCPLog.log"))
{
Log(feedback, w);
}
client.Close();
});
childSocketThread.Start();
}
}
catch (Exception err)
{
using (StreamWriter w = File.AppendText("error.log"))
{
Log("tcpControl.tcpListen: " + err.Message, w);
}
}
}
The part of the code that repeats every few seconds:
private void ptoCheck()
{
IPAddress sourceIP;
int sourcePort;
int destinationPort;
string tcpStatus;
int oldCOunt = dgvWorkstations.RowCount;
int newCount = sqlScripts.posCount(sqlServer, sqlUser, sqlPassword, sqlDatabase);
if (newCount != oldCOunt)
{
getWorkstations();
}
try
{
foreach (DataGridViewRow row in dgvWorkstations.Rows)
{
int i = row.Index;
bool tcpState;
dgvWorkstations["Status", i].Value = "Checking";
dgvWorkstations.Refresh();
name = row.Cells["POS_Name"].Value.ToString();
sourceIP = IPAddress.Parse(row.Cells["LastKnownIP"].Value.ToString());
sourcePort = Convert.ToInt32(row.Cells["Receive_Port"].Value.ToString());
destinationPort = Convert.ToInt32(row.Cells["Send_Port"].Value.ToString());
tcpState = tcpControl.tcpCheck(sourceIP, sourcePort, name);
if (tcpState == false)
{
dgvWorkstations["Status", i].Value = "Connecting";
dgvWorkstations.Refresh();
tcpStatus = tcpControl.tcpConnect(sourceIP, sourcePort, name);
tcpControl.tcpListen(sourceIP, sourcePort);
dgvWorkstations["Status", i].Value = tcpStatus;
}
if (tcpState == true)
{
dgvWorkstations["Status", i].Value = "Connected";
dgvWorkstations.Refresh();
}
i = i + 1;
}
}
catch (Exception err)
{
using (StreamWriter w = File.AppendText("AError.log"))
{
Log("frmMain.ptoCheck: (" + name + ") " + err.Message, w);
}
}//End Catch
}
I got the following code toe work, from my class I can now make multiple connections, however. The part where I call another method to listen and receive the data blocks the first method and holds it untill the connection drops without making further connections.
My Class:
public void tcpTest2(IPAddress server, Int32 port, int x)
{
TcpClient client;
sendData("Connecting to Host: " + server + " on port: " + port.ToString() + "...");
sendStatus("Connecting", x);
try
{
client = new TcpClient(server.ToString(), port);
if (false)
{
}
if (true)
{
sendData("Connection to Host: " + server + " on port: " + port.ToString() + "..ESTABLISHED");
sendStatus("Connected", x);
receiveData(client, server, port);
}
}
catch (Exception)
{
sendData("Connection to Host: " + server + " on port: " + port.ToString() + "..FAILED");
sendStatus("Failed", x);
}
}
public void receiveData(TcpClient client, IPAddress server, int port)
{
Byte[] data = System.Text.Encoding.Default.GetBytes("|");
data = new byte[1024];
string stringData;
bool connected;
connected = true;
while (connected == true)
{
string fromC = client.Client.RemoteEndPoint.ToString();
NetworkStream ns = client.GetStream();
int recv = ns.Read(data, 0, data.Length);
stringData = Encoding.ASCII.GetString(data, 0, recv);
sendUpdate("{" + fromC + "}" + stringData);
connected = IsConnected(client);
}
if (connected == false)
{
sendData("Connection to Host: " + server + " on port: " + port.ToString() + "..LOST");
sendLost(server);
}
}
public bool IsConnected(TcpClient client)
{
try
{
if (client != null && client.Client != null && client.Client.Connected)
{
if (client.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (client.Client.Receive(buff, SocketFlags.Peek) == 0)
{
return false;
}
else
{
return true;
}
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
}
Here is the final code that worked for me:
My Class:
public void tcpConnect(object pos)
{
IPAddress hostIP = IPAddress.Parse(pos.ToString().Split(':')[0]);
int hostPort = Int32.Parse(pos.ToString().Split(':')[1]);
rowInd = Int32.Parse(pos.ToString().Split(':')[2]);
var client = new TcpClient();
if (!client.ConnectAsync(hostIP, hostPort).Wait(1000))
{
sendData("Connection to Host: " + hostIP + " on port: " + hostPort.ToString() + ".FAILED");
sendStatus("Failed", "", rowInd);
return;
}
if (true)
{
sendData("Connection to Host: " + hostIP.ToString() + " on port: " + hostPort.ToString() + "..ESTABLISHED");
Thread thread = new Thread(new ParameterizedThreadStart(ClientHandler));
thread.IsBackground = true;
Thread.FreeNamedDataSlot(hostIP.ToString() + rowInd.ToString());
thread.Name = hostIP.ToString() + rowInd.ToString();
thread.Start(client);
threadID = thread.ManagedThreadId.ToString();
sendStatus("Connected", threadID, rowInd);
}
}
public bool IsConnected(TcpClient client)
{
try
{
if (client != null && client.Client != null && client.Client.Connected)
{
if (client.Client.Poll(0, SelectMode.SelectRead))
{
byte[] buff = new byte[1];
if (client.Client.Receive(buff, SocketFlags.Peek) == 0)
{
return false;
}
else
{
return true;
}
}
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
public void ClientHandler(object c)
{
TcpClient client = (TcpClient)c;
NetworkStream netstream = client.GetStream();
string fromC = client.Client.RemoteEndPoint.ToString();
string fromIP = fromC.Split(':')[0];
bool connected = true;
while (connected)
{
Thread.Sleep(10);
try
{
byte[] data = new byte[client.ReceiveBufferSize];
data = System.Text.Encoding.Default.GetBytes("|");
data = new byte[1024];
string stringData;
NetworkStream ns = client.GetStream();
int recv = ns.Read(data, 0, data.Length);
stringData = Encoding.ASCII.GetString(data, 0, recv);
sendUpdate("|" + fromC + "|" + stringData);
connected = IsConnected(client);
}
catch (Exception err)
{
connected = false;
sendLost(fromIP);
using (StreamWriter w = File.AppendText("Arch-PTO.log"))
{
Log("tcpServices.ClientHandler: " + err.Message, w);
}
}
}
sendLost(fromIP);
}

Mono HTTPListener throws exception when using self signed SSL certificate

I wrote a little web server on Linux using the Mono HTTPListener class. It works fine for http requests. However, if I use a self-signed SSL certificate (created with openssl and installed with httpcfg) it will throw an un-catchable exception as soon as the request forom a browser comes in.
The exception is:
Unhandled Exception:
System.IO.IOException: The authentication or decryption has failed. ---> Mono.Security.Protocol.Tls.TlsException: The client stopped the handshake.
at Mono.Security.Protocol.Tls.SslServerStream.EndNegotiateHandshake (IAsyncResult asyncResult) <0xb4b079c8 + 0x001cf> in <filename unknown>:0
at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) <0xb4b07428 + 0x0005f> in <filename unknown>:0
Here is the complete code:
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Threading;
namespace SSLTest
{
class MainClass
{
static void Main ()
{
try
{
HttpListener l = new HttpListener ();
l.Prefixes.Add ("https://*:8443/");
l.Start ();
Console.WriteLine("Server is running.");
while (l.IsListening)
{
//create the worker thread
HttpListenerContext ctx = l.GetContext(); //.GetContext() blocks until something comes in
if(ctx != null)
{
if(ctx.Request.RemoteEndPoint != null)
{
Thread workerThread = new Thread(() => RunWorker(ctx));
workerThread.Start();
}
}
}
Console.WriteLine("Server is stopped.");
}
catch(Exception ex)
{
Console.WriteLine ("Exception in Main: " + ex);
}
}
static void RunWorker(HttpListenerContext ctx)
{
try
{
if(ctx.Request != null)
{
if(ctx.Request.RemoteEndPoint != null)
{
Console.WriteLine ("Got request from " + ctx.Request.RemoteEndPoint.ToString());
string rstr = "Test Website!\n" + DateTime.Now.ToString();
byte[] buf = Encoding.UTF8.GetBytes(rstr);
if(buf!=null)
{
ctx.Response.ContentLength64 = buf.Length;
ctx.Response.OutputStream.Write(buf, 0, buf.Length);
}
}
}
}
catch(Exception ex)
{
Console.WriteLine ("#Exception in RunWorker: " + ex.Message);
}
}
}
}
This is the case when I am using a browser for the first time. The browser will show something like "Unsafe certificate! Do you want to continue (not recommended)?". If I click on Yes and restart the crashed server app it will work from that moment on.
How can I fix this?
Also, I am not able to catch this exception with a try block. It will always terminate my application. How can I prevent that?
Should be fixed by an unreleased bug fix https://bugzilla.xamarin.com/show_bug.cgi?id=52675... although I have not had a chance to test.
I have seen this as well and am currently trying to find a way to handle the exception. This looks to be a bug in Mono.
It occurs when certificate verification fails in any way.
I obtained a CA signed cert which fixed the problem as long as the certificate common name (dns) is the same as the dns used in the URL I'm trying to send a get request to. If I instead specify the public IP address in the url (which the cert is not registered with) the mono app will crash with an unhandled exception.
One option we're considering is implementing a TCP based webserver which would use a TcpListener instead of the heavy HttpListener which would in turn fix other problems we're seeing with mono httplistener prefixes not working correctly when bound to the internal IP behind a NAT. This would mean the cert could be bound pro-grammatically as well, it just takes more work.
Below is a very rough version of what this might look like. By no means is this a finished product but it may serve to help others on this same path... I'll have to do this in two answers, this is the tcp web server.
using System;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
namespace Example.Lib.Net
{
internal class TcpWebServer : IDisposable
{
private TcpListener m_Listener = null;
private bool m_IsSSL = false;
private X509Certificate2 m_ServerCertificate = null;
internal X509Certificate2 ServerCertificate
{
get { return m_ServerCertificate; }
set { m_ServerCertificate = value; }
}
internal void Start(string ip, int port, bool useSsl = false)
{
if (useSsl) // for player streams always use ssl to
{
m_IsSSL = true;
m_ServerCertificate = new X509Certificate2("./cert/cert.pfx", "pass");
X509Store store = new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Add(m_ServerCertificate);
store.Close();
}
IPAddress ipAddr = IPAddress.Any;
if (ip != "*") IPAddress.TryParse(ip, out ipAddr);
try
{
m_Listener = new TcpListener(ipAddr, port);
m_Listener.Start();
m_Listener.BeginAcceptTcpClient(OnClientAccepted, m_Listener);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
private void OnClientAccepted(IAsyncResult ar)
{
TcpListener listener = ar.AsyncState as TcpListener;
if (listener == null)
return;
TcpClient client = listener.EndAcceptTcpClient(ar);
client.ReceiveBufferSize = 65535;
client.Client.ReceiveBufferSize = 65535;
TcpWebConnection con = new TcpWebConnection(client, this, m_IsSSL);
listener.BeginAcceptTcpClient(OnClientAccepted, listener);
}
}
}
This is the tcp web connection code.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Text;
using System.Threading;
using System.Web;
using Example.Lib.Common;
using Example.Lib.Models;
namespace Example.Lib.Net
{
internal enum RequestType
{
None = 0,
GET = 1,
POST = 2,
OPTIONS = 3
}
internal class TcpWebConnection : IDisposable
{
#region private members
private bool m_IsDisposed = false;
private bool m_IsSSL = false;
private bool m_HasHeaders = false;
private bool m_FileCreated = false;
private bool m_IsFileUpload = false;
private RequestType m_RequestType = RequestType.None;
private string m_ReadData = string.Empty;
private string m_Request = string.Empty;
private string m_RemoteIP = string.Empty;
private string m_AbsoluteURI = string.Empty;
private string m_ContentType = string.Empty;
private string m_TempFilename = string.Empty;
private byte[] m_EndBoundaryBytes = null;
private byte[] m_StartBoundaryBytes = null;
private int m_ContentLength = 0;
private long m_StartBoundaryIndex = -1;
private long m_EndBoundaryIndex = -1;
private long m_BytesRead = 0;
private NameValueCollection m_QueryString = null;
private string[] m_Segments = new string[1];
private string m_HttpVersion = "HTTP/1.1";
private byte[] m_PostData = null;
private byte[] m_Buffer = new byte[65535];
private ReadWriteBuffer m_TempBuffer;
private FileStream m_FileStream = null;
private MemoryStream m_FullBuffer = new MemoryStream();
private TcpClient m_Client = null;
private System.IO.Stream m_NetworkStream = null;
private TcpWebServer m_Parent = null;
private Thread m_Thread_Read = null;
private Timer m_Timer_Check = null;
private DateTime m_LastRead = DateTime.Now;
private AutoResetEvent m_WaitHandle_Write;
#endregion private members
#region constructors
internal TcpWebConnection(TcpClient client, TcpWebServer parent, bool ssl)
{
m_WaitHandle_Write = new AutoResetEvent(false);
m_TempBuffer = new ReadWriteBuffer(65535);
m_IsSSL = ssl;
m_Segments[0] = string.Empty;
m_Client = client;
m_Parent = parent;
m_RemoteIP = ((IPEndPoint)m_Client.Client.RemoteEndPoint).Address.ToString();
if (ssl)
{
m_NetworkStream = new SslStream(m_Client.GetStream(), false);
}
else
{
m_NetworkStream = m_Client.GetStream();
}
m_NetworkStream.ReadTimeout = 2000;
m_Timer_Check = new Timer(Timer_Check_Callback, this, 2000, 2000);
// start threads
m_Thread_Read = new Thread(DoRead);
m_Thread_Read.IsBackground = true;
m_Thread_Read.Start();
}
#endregion constructors
#region destructors
~TcpWebConnection()
{
try
{
if (m_Timer_Check != null) m_Timer_Check.Dispose();
m_Timer_Check = null;
}
catch { } // if the timer was
}
#endregion destructors
#region internal properties
internal bool IsLargeFileUpload { get; set; } = false;
internal string TempFilename
{
get { return m_TempFilename; }
set { m_TempFilename = value; }
}
/// <summary>
/// Remote IP
/// </summary>
internal string RemoteIP
{
get { return m_RemoteIP; }
}
internal string AbsoluteURI
{
get { return m_AbsoluteURI; }
}
internal string ContentType
{
get { return m_ContentType; }
}
internal string[] Segments
{
get { return m_Segments; }
}
internal NameValueCollection QueryString
{
get { return m_QueryString; }
}
internal Stream NetworkStream
{
get { return m_NetworkStream; }
}
internal int ContentLength
{
get { return m_ContentLength; }
}
#endregion internal properties
#region private methods
private void Timer_Check_Callback(object state)
{
if ((DateTime.Now - m_LastRead).TotalSeconds > 15)
{
try
{
Program.BlacklistIP(m_RemoteIP, "TcpWebConnection - Timer", "Connection Timed Out");
ProcessRequest(m_ReadData);
Dispose();
}
catch (Exception e) { }
}
}
private void DoRead()
{
if (m_IsSSL)
{
try
{
((SslStream)m_NetworkStream).AuthenticateAsServer(m_Parent.ServerCertificate, false, SslProtocols.Tls, false);
((SslStream)m_NetworkStream).BeginRead(m_Buffer, 0, m_Buffer.Length, new AsyncCallback(SslRead), m_NetworkStream);
m_NetworkStream.ReadTimeout = 5000;
m_NetworkStream.WriteTimeout = 5000;
}
catch (Exception e)
{
//Console.WriteLine("SSL Auth Error: " + e.Message);
}
}
else
{
NormalRead();
}
}
private void UpdatePostData()
{
m_FullBuffer.Position = 0;
byte[] fullBuffer = Common.Conversion.MemoryStreamToByteArray(m_FullBuffer);
m_FullBuffer.Dispose();
if (m_StartBoundaryIndex > -1 && m_EndBoundaryIndex > -1)
{
m_PostData = new byte[m_EndBoundaryIndex - m_StartBoundaryIndex];
Array.Copy(fullBuffer, m_StartBoundaryIndex, m_PostData, 0, m_EndBoundaryIndex - m_StartBoundaryIndex);
}
}
internal void SaveFile(string filepath)
{
try
{
UpdatePostData();
if (m_PostData == null) return;
if (!Directory.Exists(Path.GetDirectoryName(filepath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(filepath));
}
if (File.Exists(filepath))
{
File.Delete(filepath);
}
using (FileStream output = new FileStream(filepath, FileMode.Create, FileAccess.Write))
{
output.Write(m_PostData, 0, m_PostData.Length);
}
}
catch (Exception e)
{
// report error
}
}
private void AppendBuffer(byte[] newBuffer, int length)
{
// we need to keep a running buffer here, the last 1024 bytes? how best to find the end boundary? need to determine when the stream is finished!
m_TempBuffer.Write(newBuffer, length);
if (m_IsFileUpload)
{
if (m_EndBoundaryIndex < 0)
{
m_EndBoundaryIndex = StreamHelper.LastIndexOf(m_TempBuffer.RawBytes, m_TempBuffer.Count, m_EndBoundaryBytes);
if (!IsLargeFileUpload && m_EndBoundaryIndex > -1)
{
m_EndBoundaryIndex = (m_FullBuffer.Length + length) - (m_TempBuffer.Count - m_EndBoundaryIndex);
}
}
if (m_StartBoundaryIndex < 0)
{
m_StartBoundaryIndex = StreamHelper.IndexOf(m_FullBuffer, m_StartBoundaryBytes);
if (m_StartBoundaryIndex > -1)
{
m_StartBoundaryIndex = StreamHelper.IndexOf(m_FullBuffer, Encoding.UTF8.GetBytes("\r\n\r\n"), m_StartBoundaryIndex + m_StartBoundaryBytes.Length) + 4;
}
}
}
if (m_StartBoundaryIndex == -1 || !IsLargeFileUpload) // if this is not a file upload because no start boundary has been found then write buffer to memory
{
m_FullBuffer.Write(newBuffer, 0, length);
}
else
{
if (!m_FileCreated) // we have never written to the file, dump the contents of the full buffer now
{
bool exists = true;
while (exists)
{
m_TempFilename = Config.StaticConfig.TempFolder + "/" + Path.GetRandomFileName();
exists = File.Exists(m_TempFilename);
}
m_FileStream = new FileStream(m_TempFilename, FileMode.Create, FileAccess.Write);
m_FullBuffer.Position = m_StartBoundaryIndex;
m_FullBuffer.CopyTo(m_FileStream);
m_FileStream.Write(newBuffer, 0, length);
m_FileCreated = true;
}
else // we have previously written to the file, append new bytes
{
if (m_EndBoundaryIndex == -1)
{
m_FileStream.Write(newBuffer, 0, length);
}
else
{
m_FileStream.Write(newBuffer, 0, length - m_EndBoundaryBytes.Length);
}
}
}
}
private void NormalRead()
{
try
{
int bufferSize = m_Buffer.Length;
int bytesRead = m_Client.Client.Receive(m_Buffer, bufferSize, 0);
while (bytesRead > 0 && !m_IsDisposed)
{
m_LastRead = DateTime.Now;
m_BytesRead += bytesRead;
if (!m_HasHeaders || m_RequestType == RequestType.GET)
{
string sBuffer = Encoding.ASCII.GetString(m_Buffer, 0, bytesRead);
m_ReadData += sBuffer;
}
AppendBuffer(m_Buffer, bytesRead);
m_HasHeaders = UpdateUniqueHeaders();
if (!m_HasHeaders && m_BytesRead > 1024)
{
Program.BlacklistIP(m_RemoteIP, m_ReadData, "No HTTP headers found in the first 1024 bytes");
return;
}
if (m_RequestType != RequestType.POST)
{
break; // process the request
}
else if (m_EndBoundaryIndex != -1)
{
break; // process the request, we found our end boundary for posted data
}
bytesRead = m_Client.Client.Receive(m_Buffer, bufferSize, 0);
}
ProcessRequest(m_ReadData);
}
catch (Exception e)
{
// report error
}
}
private void SslRead(IAsyncResult ar)
{
if (m_IsDisposed) return;
try
{
int byteCount = -1;
int bufferSize = m_Buffer.Length;
m_LastRead = DateTime.Now;
byteCount = m_NetworkStream.EndRead(ar);
m_BytesRead += byteCount;
if (!m_HasHeaders || m_RequestType == RequestType.GET)
{
string sBuffer = Encoding.ASCII.GetString(m_Buffer, 0, byteCount);
m_ReadData += sBuffer;
}
AppendBuffer(m_Buffer, byteCount);
m_HasHeaders = UpdateUniqueHeaders();
if (!m_HasHeaders && m_BytesRead > 1024)
{
Program.BlacklistIP(m_RemoteIP, m_ReadData, "No HTTP headers found in the first 1024 bytes");
return;
}
if (byteCount > 0)
{
if (m_RequestType != RequestType.POST && m_RequestType != RequestType.None)
{
m_NetworkStream.BeginRead(m_Buffer, 0, bufferSize, new AsyncCallback(SslRead), m_NetworkStream);
}
else if (m_EndBoundaryIndex == -1) // as long as we haven't found the end of the stream continue reading
{
m_NetworkStream.BeginRead(m_Buffer, 0, bufferSize, new AsyncCallback(SslRead), m_NetworkStream);
return;
}
}
}
catch (Exception e)
{
return;
}
ProcessRequest(m_ReadData);
}
private bool UpdateUniqueHeaders()
{
if (m_RequestType == RequestType.None && m_ReadData.Length > 8)
{
m_RequestType = (m_ReadData.StartsWith("GET ") ? RequestType.GET : m_RequestType);
m_RequestType = (m_ReadData.StartsWith("POST ") ? RequestType.POST : m_RequestType);
m_RequestType = (m_ReadData.StartsWith("OPTIONS ") ? RequestType.OPTIONS : m_RequestType);
}
if (m_RequestType == RequestType.GET || m_RequestType == RequestType.POST)
{
string request = m_ReadData;
if (string.IsNullOrEmpty(m_HttpVersion)) m_HttpVersion = m_ReadData.Substring(request.IndexOf("HTTP", 1), 8);
if (string.IsNullOrEmpty(m_ContentType)) m_ContentType = GetHeader(request, "Content-Type");
if (m_ContentLength == 0)
{
int cLength = 0;
int.TryParse(GetHeader(request, "Content-Length"), out cLength);
m_ContentLength = cLength;
if (m_ContentLength / 1024 / 1024 > 20)
{
IsLargeFileUpload = true; // data is sent directly to a file instead of saving in memory
}
}
}
if (m_RequestType != RequestType.None && !string.IsNullOrEmpty(m_HttpVersion) && (!string.IsNullOrEmpty(m_ContentType) || m_RequestType != RequestType.POST))
{
if (m_RequestType == RequestType.POST)
{
try
{
if (m_IsFileUpload == false)
{
m_IsFileUpload = Segments[1].Replace("/", "") == "upload";
}
}
catch { }
if (m_RequestType == RequestType.POST && m_StartBoundaryBytes == null)
{
m_StartBoundaryBytes = Encoding.ASCII.GetBytes(GetStartBoundary());
m_EndBoundaryBytes = Encoding.ASCII.GetBytes(GetEndBoundary());
}
}
if (string.IsNullOrEmpty(m_Request) && m_Segments.Length <= 1 && m_QueryString == null)
{
// Extract the Requested Type and Requested file/directory
string m_Request = m_ReadData.Substring(0, m_ReadData.IndexOf("HTTP", 1) - 1);
//Replace backslash with Forward Slash, if Any
m_Request = m_Request.Replace("\\", "/");
m_Request = m_Request.Replace("GET ", "");
m_Request = m_Request.Replace("POST ", "");
Uri uri = new Uri("http://localhost" + m_Request);
NameValueCollection query = HttpUtility.ParseQueryString(uri.Query);
//SendHeader(sHttpVersion, "image/jpeg", Program.BlankImageBuffer.Length, " 200 OK");
m_AbsoluteURI = m_Request;
m_Segments = uri.Segments;
m_QueryString = query;
}
if (m_RequestType != RequestType.POST)
{
return true;
}
else if (m_ContentLength > 0 && m_EndBoundaryBytes != null)
{
return true;
}
}
return false;
}
private string GetStartBoundary()
{
return "--" + m_ContentType.Split(';')[1].Split('=')[1];
}
private string GetEndBoundary()
{
return "--" + m_ContentType.Split(';')[1].Split('=')[1] + "--\r\n";
}
private string GetHeader(string request, string key)
{
string result = string.Empty;
int iStartPos = request.IndexOf(key + ":", 0) + key.Length + 1;
if (request.IndexOf(key + ":", 0) > -1)
{
// Get the HTTP text and version e.g. it will return "HTTP/1.1"
int iEndPos = request.IndexOf("\r\n", iStartPos);
result = request.Substring(iStartPos, iEndPos - iStartPos).Trim();
}
return result;
}
private void CleanFile()
{
try
{
if (!string.IsNullOrEmpty(m_TempFilename) && File.Exists(m_TempFilename))
{
using (Stream stream = File.Open(m_TempFilename, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[1024];
stream.Read(buffer, 0, buffer.Length);
//stream.Position = 0;
//stream.Write(data, 0, data.Length);
}
}
}
catch { }
}
private void ProcessRequest(string request)
{
try
{
if (request.Length < 5) return;
List<string> headers = null;
if (request.StartsWith("OPTIONS"))
{
headers = GetCommonHeader("", 0);
headers.Add("Access-Control-Allow-Credentials: true");
headers.Add("Access-Control-Allow-Headers: Authorization, X-Mashape-Authorization, Accept, Content-Type, X-Requested-With, X-PINGOTHER, X-File-Name, Cache-Control");
headers.Add("Access-Control-Allow-Methods: PUT, POST, GET, OPTIONS");
headers.Add("Keep-Alive: timeout=15,max=100");
headers.Add("Access-Control-Allow-Origin: *");
headers.Add("Connection: close");
SendHeader(headers);
return;
}
UpdateUniqueHeaders();
CleanFile();
CloseFile();
if (m_Timer_Check != null) m_Timer_Check.Dispose();
string responseText = Program.ProcessRequest(this);
if (string.IsNullOrEmpty(responseText)) responseText = "\r\n";
byte[] buf = Encoding.ASCII.GetBytes(responseText);
headers = GetCommonHeader("text/html", buf.Length, " 200 OK");
headers.Add("Access-Control-Allow-Origin: *");
SendHeaderAndData(headers, buf);
}
catch (Exception e) { }
finally
{
Dispose();
}
}
private void CloseFile()
{
try
{
if (m_FileStream != null)
{
m_FileStream.Dispose();
m_FileStream = null;
}
}
catch { }
}
/// <summary>
/// This function send the Header Information to the client (Browser)
/// </summary>
/// <param name="sHttpVersion">HTTP Version</param>
/// <param name="sMIMEHeader">Mime Type</param>
/// <param name="iTotBytes">Total Bytes to be sent in the body</param>
/// <param name="mySocket">Socket reference</param>
/// <returns></returns>
public List<string> GetCommonHeader(string mimeHeader = "text/html", int length = -1, string sStatusCode = " 200 OK", string filename = "", bool chunked = false)
{
// if Mime type is not provided set default to text/html
List<string> headers = new List<string>();
headers.Add(m_HttpVersion + sStatusCode);
headers.Add("Server: ExampleTcpWebServer");
if (!string.IsNullOrEmpty(mimeHeader))
{
headers.Add("Content-Type: " + mimeHeader);
}
if (length > -1)
{
headers.Add("Content-Length: " + length);
}
headers.Add("Date: " + DateTime.Now.ToUniversalTime().ToString("ddd, d MMM yyyy HH:mm:ss") + " GMT");
if (!string.IsNullOrEmpty(filename))
{
headers.Add("Content-Disposition: attachment; filename=\"" + filename + "\"");
}
if (chunked)
{
headers.Add("Transfer-Encoding: chunked");
}
return headers;
}
public void SendHeader(List<string> headers)
{
string sHeader = string.Empty;
foreach (string header in headers)
{
sHeader += header + "\r\n";
}
sHeader += "\r\n";
byte[] bSendData = Encoding.ASCII.GetBytes(sHeader);
SendToBrowser(bSendData, bSendData.Length);
}
public void SendHeaderAndData(List<string> headers, byte[] data)
{
string sHeader = string.Empty;
foreach (string header in headers)
{
sHeader += header + "\r\n";
}
sHeader += "\r\n";
byte[] bHeader = Encoding.ASCII.GetBytes(sHeader);
byte[] combined = new byte[bHeader.Length + data.Length];
Array.Copy(bHeader, combined, bHeader.Length);
Array.Copy(data, 0, combined, bHeader.Length, data.Length);
SendToBrowser(combined, combined.Length);
}
/// <summary>
/// Sends data to the browser (client)
/// </summary>
/// <param name="bSendData">Byte Array</param>
/// <param name="mySocket">Socket reference</param>
public void SendToBrowser(byte[] bSendData, int length)
{
try
{
if (Common.TcpHelper.SocketConnected(m_Client.Client))
{
if (m_IsSSL)
{
m_NetworkStream.Write(bSendData, 0, length);
}
else
{
m_Client.Client.Send(bSendData, length, 0);
}
}
else
{
Dispose();
}
}
catch (Exception e)
{
//Console.WriteLine("Error Occurred : {0} ", e);
}
}
#endregion private methods
#region IDisposable
public void Dispose()
{
if (!m_IsDisposed)
{
m_IsDisposed = true;
try
{
if (!string.IsNullOrEmpty(m_TempFilename) && File.Exists(m_TempFilename))
{
File.Delete(m_TempFilename);
}
}
catch { }
CloseFile();
try
{
m_Client.Client.Close(5);
m_Client.Close();
m_Client.Client.Dispose();
}
catch { }
try
{
m_NetworkStream.Dispose();
}
catch { }
try
{
if (Thread.CurrentThread != m_Thread_Read && m_Thread_Read.IsAlive)
{
m_Thread_Read.Join(1000);
if (m_Thread_Read.IsAlive) m_Thread_Read.Abort();
}
}
catch { }
try
{
m_ReadData = null;
m_PostData = null;
m_Buffer = null;
m_TempBuffer = null;
if (m_FullBuffer != null) m_FullBuffer.Dispose();
if (m_Timer_Check != null) m_Timer_Check.Dispose();
m_Timer_Check = null;
}
catch { }
}
}
#endregion IDisposable
}
}

C# UDP communication ending connection when no answer received

I'm writing simple app for dynamic communicating with arduinos over UDP.
I'm stucked during writing UDP class in C# pc app.
I have problem with ending fuction after not receiving answer from client. If I'm connecting with client which is on, there is no problem, app is runing nice and smooth after receiving answer from it.
STRING_operations str = new STRING_operations();
static int communicationPort = 8888;
string[] arduinoPool = new string[64];
private void populateArduinoPool()
{
for (int i = 0; i < 25; i++)
{
arduinoPool[i] = "192.168.1." + Convert.ToString(170 + i);
}
}
private string mainCommunication(string vIPAdsress, string Message)
{
string answer = string.Empty;
int port = communicationPort;
Console.WriteLine("IP address: " + vIPAdsress);
Console.WriteLine("Message to sent: " + Message);
Byte[] sendBytes = Encoding.ASCII.GetBytes(str.sendString(Message));
Byte[] receiveBytes = null;
var IP = IPAddress.Parse(vIPAdsress);
var udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpClient.ReceiveTimeout = 1000;
udpClient.SendTimeout = 1000;
var sendEndPoint = new IPEndPoint(IP, port);
var receiveEndPoint = new IPEndPoint(IP, port);
var clientReturn = new UdpClient(port);
udpClient.SendTo(sendBytes, sendEndPoint);
Console.WriteLine("Message sent");
try {
receiveBytes = clientReturn.Receive(ref receiveEndPoint);
Console.WriteLine("Message is being receiving");
if (receiveBytes == null || receiveBytes.Length == 0)
{
Console.WriteLine("No answer");
;
}
Console.WriteLine(Encoding.ASCII.GetString(receiveBytes));
answer = str.trimString(Encoding.ASCII.GetString(receiveBytes));
Console.WriteLine("Trimed answer: " + answer);
udpClient.Disconnect(true);
return answer; }
catch (Exception e)
{
Console.WriteLine(e);
return e.ToString();
}
}
public void populateComboBox(ComboBox CB1)
{
Console.WriteLine("Populating arduino pool");
populateArduinoPool();
string message = str.sendString("HELLO");
for (int i = 0; i < 25; i++)
{
Console.WriteLine("Trying to communicate with: " + arduinoPool[i]);
if (mainCommunication(arduinoPool[i], message) == "YO")
{
Console.WriteLine("Established");
CB1.Items.Add(arduinoPool[i]);
}
}
}
public bool checkIfActive(ComboBox CB1)
{
string message = str.sendString("HELLO"); ;
if (mainCommunication(CB1.SelectedText.ToString(), message) == "YO")
return true;
else
return false;
}

Categories