Related
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);
}
}
}
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);
}
On my server side I have set up a single thread code that creates a new Socket object every time a client connects. Then I pass whatever I get from the client along with the socket that is connected to a packet handler and do the calculations there. In my main form I have a listview that I populate via entity framework, and whenever a packet from a registered computer connects I update the listview. So my question is can I from the packet handler class pass the socket object to the tag property of my listview when I update it?
My server side code:
private void ReceivedCallback(IAsyncResult result)
{
Socket clientSocket = result.AsyncState as Socket;
SocketError ER;
try
{
int bufferSize = clientSocket.EndReceive(result, out ER);
if (ER == SocketError.Success)
{
byte[] packet = new byte[bufferSize];
Array.Copy(_buffer, packet, packet.Length);
Console.WriteLine("Handling packet from IP:" + clientSocket.RemoteEndPoint.ToString());
//Handle packet stuff here.
PacketHandler.Handle(packet, clientSocket);
_buffer = new byte[61144];
clientSocket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, ReceivedCallback, clientSocket);
//clientSocket.BeginReceive(new byte[] { 0 }, 0, 0, 0, ReceivedCallback, clientSocket);
}
else
{
Console.WriteLine("No bytes received, we're closing the connection.");
clientSocket.Close();
}
}catch(SocketException ex)
{
Console.WriteLine("We caught a socket exception:" + ex.Message);
clientSocket.Close();
}
}
And my packet handler class:
public static void Handle(byte[] packet, Socket clientSocket)
{
if (clientSocket.Connected)
{
if (packet.Length > 0)
{
IPEndPoint RemoteIP = (IPEndPoint)clientSocket.RemoteEndPoint;
ushort packetLength = BitConverter.ToUInt16(packet, 0);
ushort packetType = BitConverter.ToUInt16(packet, 2);
ushort packetID = BitConverter.ToUInt16(packet, 4);
Console.WriteLine("We received a packet of Type: {0}, ID: {1} FROM {2}", packetType, packetID, RemoteIP.ToString());
if (packetType == 1)
{
switch (packetID)
{
case 1://Check if computer is registered in the database
CheckRegisteredRequest request1 = new CheckRegisteredRequest(packet);
Console.WriteLine("We received (Case 1): " + request1.Text);
string Response = "";
bool found = false;
ServerDbContext database = new ServerDbContext();
foreach (computers pcs in database.computers)
{
if (pcs.name == request1.Text.Split(',')[0])
{
found = true;
if (pcs.computer_ip == request1.Text.Split(',')[1])
{
//We found a computer with that name and ip address
Response = "true";
CheckRegisteredResponse resp1 = new CheckRegisteredResponse(Response);
clientSocket.Send(resp1.Data);
computers registeredPC;
var name = request1.Text.Split(',')[0];
using (var ctx = new ServerDbContext())
{
registeredPC = ctx.computers.Where(c => c.name == name).FirstOrDefault<computers>();
}
if (registeredPC != null)
{
registeredPC.networkStatus = "online";
}
using (var ctx = new ServerDbContext())
{
ctx.Entry(registeredPC).State = System.Data.Entity.EntityState.Modified;
ctx.SaveChanges();
}
addNewLog("Computer: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1]);
RaiseFeedback("PC: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1]);
break;
}
else
{
//We found a computer with that name but a different ip address, update it
var name = request1.Text.Split(',')[0];
var registeredPC = new computers();
using (var ctx = new ServerDbContext())
{
registeredPC = ctx.computers.Where(c => c.name == name).FirstOrDefault<computers>();
}
if (registeredPC != null)
{
var ip = request1.Text.Split(',')[1];
registeredPC.computer_ip = ip;
registeredPC.networkStatus = "online";
}
using (var ctx = new ServerDbContext())
{
ctx.Entry(registeredPC).State = System.Data.Entity.EntityState.Modified;
ctx.SaveChanges();
}
Response = "true";
CheckRegisteredResponse resp1 = new CheckRegisteredResponse(Response);
clientSocket.Send(resp1.Data);
addNewLog("Computer: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1]);
RaiseFeedback("PC: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1]);
break;
}
}
}
if (!found)
{
//There is no computer with that name in the database so send false
Response = "false";
CheckRegisteredResponse resp1 = new CheckRegisteredResponse(Response);
clientSocket.Send(resp1.Data);
}
break;... and so on....
So I've tried via a handler:
this is my custom event handler Args:
public class TextArgs : EventArgs
{
#region Fields
private string szMessage;
private Socket _sockets123;
#endregion Fields
#region ConstructorsH
public TextArgs(string TextMessage,Socket sock)
{
if (sock != null)
{
_sockets123 = sock;
szMessage = TextMessage;
}
else
{
szMessage = TextMessage;
}
}
#endregion Constructors
#region Properties
public string Message
{
get { return szMessage; }
set { szMessage = value; }
}
public Socket _socket
{
get { return _sockets123; }
set { _sockets123 = value; }
}
#endregion Properties
}
This is how i define that handler at the PacketHandler class:
public static event LogsEventHandler Feedback;
private static void RaiseFeedback(string p, Socket sock)
{
LogsEventHandler handler = Feedback;
if (handler != null)
{
handler(null,new TextArgs(p,sock));
}
}
And whenever a computer registers or connects I do the following:
RaiseFeedback("PC: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1], clientSocket);
or
RaiseFeedback("PC: " + request1.Text.Split(',')[0] + " came online - IP: " + request1.Text.Split(',')[1], null);
And the event fires of these two methods in my main form:
private void OnFeedbackReceived(object sender, TextArgs e)
{
Invoke((MethodInvoker)delegate
{
UpdateComputers();
UpdateGUI(e.Message,e._socket);
}
);
}
public void UpdateGUI(string s, Socket sock)
{
LogBox.Text += s;
LogBox.AppendText(Environment.NewLine);
using (var context = new ServerDbContext())
{
var PCInfo = context.viewUsersInfo;
dataGridView1.DataSource = PCInfo.ToList();
}
if (sock != null)
{
ListViewItem item = ComputersList.FindItemWithText(s.Split(':')[1].ToString());
item.Tag = sock;
}
}
The Question: Yes, you can. Control.Tag is of type object and can hold pretty much anything you choose.
So you can write
Socket socket = someSocket;
ListViewItem item = listView1.FindItemWithText(someText);
if (item != null) item.Tag = socket; else Console.WriteLine(someText + " not found!);
And retrieve it as:
if (item.Tag != null) someSocket = item.Tag AS socket;
if (someSocket != null) ..
It is up to you to watch out for the success of the cast when retrieving it but also if the Socket still is alive and well..
The problem: The stackoverflow in your code is due to an erreanous, short-circuited property, which you have fixed by now. In general, you only need to write explicit getter and setters if they actually do more than just gettin and setting.
They could log out out test data, update other, dependent properties, do checks or conversiones or do other stuff.
But if none of it is needed, simply don't create the private fields and write the automatic getter and setters:
public Socket MySocket {get; set;}
Also note that the naming convention asks you to capitalize proprety names!
My problem is only happening when I try to use my socket connection under a windows service.
Basically I have a socket client which connect to a remote server.
When I use it in a client application I don't have any problem at all.
But when I try to use it under my windows service it doesn't work.
public abstract class SocketClient
{
public static readonly ILog log = LogManager.GetLogger(typeof(SocketClient));
private System.Net.Sockets.Socket fSocket;
private bool LocalsocketClientIsShutingDown;
private byte[] readbuf;
private byte[] sendbuf;
private string currentmessage = "";
public event EventHandler ConnectionDone;
public event EventHandler ConnectionFailed;
public event EventHandler MessageReceivingFailed;
public event EventHandler MessageSendingFailed;
public SocketClient()
{
log4net.Config.XmlConfigurator.Configure();
readbuf = new byte[16384];
this.ConnectionDone += new EventHandler(OnSocketConnectionDone);
this.ConnectionFailed += new EventHandler(OnSocketConnectionFailed);
this.MessageSendingFailed += new EventHandler(OnMessageSendingFailed);
this.MessageReceivingFailed += new EventHandler(OnMessageReceivingFailed);
}
public bool isConnected()
{
if (fSocket == null)
return false;
return fSocket.Connected;
}
protected abstract void OnSocketConnectionDone(object sender, EventArgs e);
protected abstract void OnSocketConnectionFailed(object sender, EventArgs e);
protected abstract void OnMessageSendingFailed(object sender, EventArgs e);
protected abstract void OnMessageReceivingFailed(object sender, EventArgs e);
protected void ConnectToServer(string ServerName, int Port)
{
try
{
log.Debug("SocketClient.ConnectToServer():" + ServerName);
if (this.fSocket == null || !this.fSocket.Connected)
{
this.fSocket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream
, ProtocolType.Tcp);
IPAddress[] ipadress;
log.Debug("ConnectToServer()1");
IPHostEntry he = Dns.GetHostEntry(ServerName); //Dns.Resolve(ServerName);
log.Debug("ConnectToServer()2" + he.HostName);
ipadress = he.AddressList;
//he.AddressList = he.AddressList.ToList().Where(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToArray();
IPEndPoint remoteEP = new IPEndPoint(ipadress[0], Port);
if (ServerName=="localhost")
{
IPHostEntry ipHostInfo = /*Dns.Resolve*/Dns.GetHostEntry(Dns.GetHostName()); //Dns.Resolve(Dns.GetHostName());
//dont take IPv6 IPs
//ipHostInfo.AddressList = ipHostInfo.AddressList.ToList().Where(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToArray();
IPAddress ipAddress = ipHostInfo.AddressList[0];
remoteEP = new IPEndPoint(ipAddress, Port);
}
log.Debug("ConnectToServer()3: start BeginConnect()");
this.fSocket.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback)
, this.fSocket);
Trace.WriteLine("Connecting to server");
}
else
{
Trace.WriteLine("Already connected to a Server");
}
}
catch (Exception ex)
{
Trace.WriteLine("Error connecting to server" + ex.ToString());
OnConnectionFailed();
}
}
private void ConnectCallback(IAsyncResult asyncResult)
{
string[] obj;
try
{
log.Debug("end BeginConnect with ConnectCallback()");
System.Net.Sockets.Socket socket = (System.Net.Sockets.Socket)asyncResult.AsyncState;
this.fSocket = socket;
socket.EndConnect(asyncResult);
this.LocalsocketClientIsShutingDown = false;
this.fSocket.BeginReceive(this.readbuf, 0, this.readbuf.Length, SocketFlags.None
, new AsyncCallback(ReceiveCallback), this.fSocket);
OnConnectionDone();
}
catch (SocketException ex)
{
Trace.WriteLine("Connection Failed: " + ex.Message);
OnConnectionFailed();
}
}
private void OnConnectionDone()
{
log.Debug("OnConnectionDone");
if (ConnectionDone != null)
{
ConnectionDone(this, new EventArgs());
}
}
private void OnConnectionFailed()
{
log.Debug("OnConnectionFailed");
if (ConnectionFailed != null)
ConnectionFailed(this, new EventArgs());
}
public void SendMessage(string message)
{
log.Debug(">>> Sending Message: " + message);
if (this.fSocket != null && this.fSocket.Connected)
{
log.Debug(">>> Sending Message: Begin send 1:" + message);
//Turn string into byte for network transfer
this.sendbuf = Encoding.ASCII.GetBytes(message);
log.Debug(">>> Sending Message: Begin send 2:" + message);
this.fSocket.BeginSend(this.sendbuf, 0, this.sendbuf.Length, SocketFlags.None, new AsyncCallback(SendCallback)
, this.fSocket);
}
else
{
log.Debug("Cant Send Message: " + message + " _ Not connected to socket");
Trace.WriteLine("Not connected to Server");
}
}
private void SendCallback(IAsyncResult asyncResult)
{
try
{
//On récupere le socket sur lequel on a envoyé les données
System.Net.Sockets.Socket socket = (System.Net.Sockets.Socket)asyncResult.AsyncState;
//on met fin à l'envois de données
int senda = socket.ReceiveBufferSize;
int send = socket.EndSend(asyncResult);
Trace.WriteLine(">>> Message Sent: " + send + " bytes");
log.Debug(">>> Message Sent: " + send + " bytes");
}
catch (SocketException ex)
{
log.Debug("!!! Message NOT Sent: " + ex.Message);
Trace.WriteLine("!!! Message NOT Sent: " + ex.Message);
OnMessageSendingFailed();
}
}
private void OnMessageSendingFailed()
{
log.Debug("OnMessageSendingFailed");
if (MessageSendingFailed != null)
MessageSendingFailed(this, new EventArgs());
}
public void ReceiveMessage()
{
try
{
log.Debug(">>> ReceiveMessage");
if (this.fSocket != null && this.fSocket.Connected)
this.fSocket.BeginReceive(this.readbuf, 0, this.readbuf.Length, SocketFlags.None
, new AsyncCallback(ReceiveCallback), this.fSocket);
else
{
log.Debug("Not Connected to Server");
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
OnMessageReceivingFailed();
}
}
private void OnMessageReceivingFailed()
{
log.Debug("OnMessageReceivingFailed");
if (MessageReceivingFailed != null)
MessageReceivingFailed(this, new EventArgs());
}
private void ReceiveCallback(IAsyncResult asyncResult)
{
string[] obj;
log.Debug("ReceiveCallback");
try
{
System.Net.Sockets.Socket socket = (System.Net.Sockets.Socket)asyncResult.AsyncState;
log.Debug("ReceiveCallback 2" + socket.ToString());
int read = socket.EndReceive(asyncResult);
if (read > 0)
{
currentmessage += Encoding.ASCII.GetString(this.readbuf, 0, read);
log.Debug("ReceiveCallback 3" + currentmessage);
char _charEOL = '\n';
if (currentmessage[currentmessage.Length - 1] != _charEOL)
{
this.fSocket.BeginReceive(this.readbuf, 0, this.readbuf.Length, SocketFlags.None
, new AsyncCallback(ReceiveCallback), this.fSocket);
return;
}
readPacket(currentmessage.ToString());
obj = new string[] { "\n\n Server says :" + currentmessage };
currentmessage = "";
Buffer.SetByte(this.readbuf, 0, 0);
this.fSocket.BeginReceive(this.readbuf, 0, this.readbuf.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), this.fSocket);
}
if (read == 0 && !this.LocalsocketClientIsShutingDown)
{
this.fSocket.Close();
obj = new string[] { "Close Remote Socket" };
log.Debug("ReceiveCallback:Exception1-" + obj);
}
}
catch (SocketException ex)
{
obj = new string[1] { ex.Message };
log.Debug("ReceiveCallback:Exception2-" + ex.Message);
}
}
public void readPacket(string aMessage)
{
log.Debug("readPacket:"+aMessage);
try
{
string _formattedMsg = aMessage.Replace("\n", "");
string[] _tabAllMessages = _formattedMsg.Split(new char[] { '}' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i <= _tabAllMessages.Length - 1; i++)
{
_tabAllMessages[i] = _tabAllMessages[i] + "}";
//Trace.WriteLine("<<< Message Received: " + aMessage);
readSingleMessage(_tabAllMessages[i]);
}
}
finally
{
}
}
public abstract void readSingleMessage(string aMessage);//TO REDEFINE
public void Close()
{
log.Debug("SocketClient:Close");
try
{
if (this.fSocket != null && this.fSocket.Connected)
{
this.LocalsocketClientIsShutingDown = true;
//On ferme le socket
this.fSocket.Shutdown(SocketShutdown.Both);
System.Threading.Thread.Sleep(500);
//On détruit le socket
this.fSocket.Close();
Trace.WriteLine("Disconnected");
}
}
finally
{
}
}
The problem seems to come from that line in ConnectCallBack():
this.fSocket.BeginReceive(this.readbuf, 0, this.readbuf.Length, SocketFlags.None
, new AsyncCallback(ReceiveCallback), this.fSocket);
I dont have any problem with that in a client application.
But when I use the socket in a windows service, it seems that if I keep that line, I will get a socket error a bit later.
If I dont keep the line, then both client and windows service wont be able to listen for some messages to read.
I m a bit lost as I used my windows application for a few month and never had an issue before I tried to turn it into a windows service.
Thanks!
EDIT: a few logs:
DEBUG2014-10-02 00:01:27 – Start Session
DEBUG2014-10-02 00:01:27 – Windows Service: Start Login
DEBUG2014-10-02 00:01:27 – ImgSocketClient:ConnectToServerAndSendPassword():xxxxxxxxx.com_23459
DEBUG2014-10-02 00:01:27 – SocketClient.ConnectToServer():xxxxxxxxx.com
DEBUG2014-10-02 00:01:27 – ConnectToServer()3: start BeginConnect()
DEBUG2014-10-02 00:01:27 – end BeginConnect with ConnectCallback()
DEBUG2014-10-02 00:01:27 – OnConnectionDone
DEBUG2014-10-02 00:01:28 – >>> Socket Connected - Sending Password
DEBUG2014-10-02 00:01:29 – >>> Sending Message: PASSWORD:xxx
DEBUG2014-10-02 00:01:29 – >>> Message Sent: 25 bytes
DEBUG2014-10-02 00:01:29 – ReceiveCallback
DEBUG2014-10-02 00:01:29 – **ReceiveCallback:Exception1-System.String[]**
DEBUG2014-10-02 00:01:29 – >>> Password Sent
DEBUG2014-10-02 00:01:29 – >>> Send Message to suscribe to updates
DEBUG2014-10-02 00:01:29 – >>> Sending Message: REQUEST:aaaaa
DEBUG2014-10-02 00:01:29 – Cant Send Message: REQUEST:aaaaa_ Not connected to socket
The problem is in lines:
if (read == 0 && !this.LocalsocketClientIsShutingDown)
{
this.fSocket.Close();
obj = new string[] { "Close Remote Socket" };
log.Debug("ReceiveCallback:Exception1-" + obj);
}
It is normal if You receive 0 bytes. Why did you close the socket in this case? After closing the socket you can't send the message "REQUEST:aaaaa"...
Remove these lines and try again.
I have a c# socket based server which serves TCP clients.
I use telnet based monitoring to see if the server is listening.
to versify clients are up i use server keep alive (sending a random string data), and if socket expection raises-i remove the client from a client's dictionary.
the probelm is: the telnet connections to the socket doesn't get removed from the list of connections and the number of clients is rising up slowly but surely.
i tried a telnet manually to the server through command line and than closing the telnet connection-nothing.the server just keep sending the keep alive to the telnet connection with no execptions.
this is my read call back:
protected void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the async state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.socket;
if (state.socket == null)
return;
if (!state.socket.Connected)
return;
int id = state.id;
try
{
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
string newAddedStr = string.Empty;
newAddedStr = Encoding.UTF8.GetString(state.buffer, 0, bytesRead);
//cut the new message and add it
if (state.sb == null)
state.sb = new StringBuilder();
state.sb.Append(newAddedStr);
// There might be more data, so store the data received so far.
//add data until end of XML
content = state.sb.ToString();
//IF GOT FULL MESSAGE FROM SOCKET
if ((content.Length > 0) /*&& (content.IndexOf("\0") > -1)*/)
{
String strh = String.Format("Client # {0} data: ", id);
strh += content.Replace("\0", "");
if (!strh.Contains("keepalive"))
LogWriter.Trace(strh, "");
// l(writeToGetTextBoxMsg), new object[] { strh });
if (state != null)
{
if (state.sb == null)
state.sb = new StringBuilder();
state.sb.Length = 0;
}
//add the rest of the xml
string objData = content.Replace("\0", "");
string xmlData = objData.ToString();
try
{
if (xmlData.Contains("Unsubscribe"))
{
RemoveSubscriber(xmlData);
}
else
{
if (xmlData.Contains("Subscribe"))
{
if (!state.IsInitiated)
{
state.Init();
state.socketClient.OnSocketError += new SocketErrorHandler(socketClient_OnSocketError);
state.socketClient.clientSocket = handler;
}
AddSubscriber(xmlData, state);
}
}
xmlData = null;
objData = null;
content = null;
}
catch (ArgumentOutOfRangeException ex)
{
LogWriter.Trace(newAddedStr,"ArgumentOutOfRangeException in ReadCallback");
}
catch (Exception ex)
{
LogWriter.TraceError(ex.Message + " " + ex.StackTrace + " " + newAddedStr);
}
#region oldCode
#endregion
}
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(this.ReadCallback), state);
}
}
catch (System.Net.Sockets.SocketException es)
{
closeSocket(state, false, "Execption:" + es.Message + "," + es.StackTrace);
if (es.ErrorCode != 64)
{
LogWriter.Trace(string.Format("Socket Exception: {0}, {1}.", es.ErrorCode, es.ToString()), "");
}
}
catch (Exception e)
{
closeSocket(state, false,"Execption:"+e.Message+","+e.StackTrace);
if (e.GetType().FullName != "System.ObjectDisposedException")
{
Console.WriteLine("Exception: " + e.StackTrace);
LogWriter.Trace("Exception Message: " + e.ToString() + e.StackTrace, "");
Console.WriteLine("Exception Message: " + e.ToString());
LogWriter.Trace("ReadCallback:" + e.Message + " " + e.StackTrace, "ERROR");
}
}
}
any ideas?
When you do a read of a socket and 0 is returned you know that the other side of the connection has closed. Are you doing that?