Connection Refused to Server when using SOCKS5 Proxy and Tor C# - 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);
}
}
}

Related

C# Server using TcpListener connects the first Client, but second Client timeouts and fails to connect, why?

I tried switching code to following async calls for Server.
I still am getting same issue. First client connects and interacts fine.
The Second client get stuck with SocketException 10060 (Timeout)
Despite switching over to Async calls, second client is still timing out
Any hints or suggestions are welcomed.
Server code
Console.WriteLine("Initialized Server Data");
Console.WriteLine("Starting Server......");
tcpListener = new TcpListener(IPAddress.Any, Port);
tcpListener.Start();
Console.WriteLine($"Server Started on Port: {Port}.");
tcpListener.BeginAcceptTcpClient(ConnectionCallback, null);
ConnectionCallback
TcpClient _client = tcpListener.EndAcceptTcpClient(_result);
//add client to server list
int i = 0;
for (i = 1; i <= MaxPlayers; i++)
{
if (Clients[i].tcp.socket == null)
{
//found empty client slot on server add client
Clients[i].Connect(_client, this);
i = MaxPlayers * 2;
}
}
if (i < MaxPlayers + 2)
{
Program.WriteConsoleLine($"{_client.Client.RemoteEndPoint} failed to connect: Server is full.", ConsoleColor.Red, ConsoleColor.Black);
}
tcpListener.BeginAcceptTcpClient(ConnectionCallback, null);
Clients[i].Connect(...)
public void Connect(TcpClient _socket, Server _actveServer)
{
ActiveServer = _actveServer;
socket = _socket;
socket.ReceiveBufferSize = dataBufferSize;
socket.SendBufferSize = dataBufferSize;
netStream = socket.GetStream();
ReceivedData = new Packet();
receiveBuffer = new byte[dataBufferSize];
Program.WriteConsoleLine($"{_socket.Client.RemoteEndPoint} connect success!!", ConsoleColor.Cyan, ConsoleColor.Black);
Program.WriteConsoleLine($"Sending IntialWelcome as a hello to {_socket.Client.RemoteEndPoint}", ConsoleColor.DarkCyan, ConsoleColor.Black);
ActiveServer.Packer.Send_InitialWelcome(id);
netStream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveDataCallback, null);
}
ReceiveDataCallback
private void ReceiveDataCallback(IAsyncResult _result)
{
try
{
int _byteLen = netStream.EndRead(_result);
if (_byteLen <= 0)
{
ActiveServer.Clients[id].Disconnect();
return;
}
byte[] _data = new byte[_byteLen];
Array.Copy(receiveBuffer, _data, _byteLen);
ReceivedData.Reset(HandleData(_data));
}
catch (Exception _err)
{
Program.WriteConsoleLine($"Error receiving TCP data: {_err}", ConsoleColor.Red, ConsoleColor.Black);
ActiveServer.Clients[id].Disconnect();
}
netStream.BeginRead(receiveBuffer, 0, dataBufferSize, ReceiveDataCallback, null);
}
Send Packet function and callback
public void SendPacket(Packet _packet)
{
try
{
if(socket != null)
{
netStream.BeginWrite(_packet.ToArray(), 0, _packet.Length(), EndPackagingData, netStream);
}
}
catch(Exception err)
{
Program.WriteConsoleLine($"Error sending data to Player {id}, via TCP: {err}", ConsoleColor.Red, ConsoleColor.Black);
}
}
private void EndPackagingData(IAsyncResult _result)
{
netStream.EndWrite(_result);
}

C# - Multithreaded TCP Server/Client

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();
}
}
}

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);
}

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