While loop keeps running after break - c#

I need to download a file and use it to connect to a server. If the connection fails, it restarts the loop. Somehow the while loop keeps running and downloading the file constantly. I think that something weird happens with the boolean Globals.sockRetry but I can't find what's really happening.
public class Globals
{
public static string serverIp;
public static int serverPort;
public static int sockConn = 0;
public static bool sockRetry = false;
public static TcpClient client;
public static NetworkStream nwStream;
public static StreamReader reader;
public static StreamWriter writer;
}
static void connect(Globals g)
{
Globals.sockConn = 1;
try
{
Globals.client = new TcpClient(Globals.serverIp, Globals.serverPort);
Globals.nwStream = Globals.client.GetStream();
Globals.reader = new StreamReader(Globals.nwStream);
Globals.writer = new StreamWriter(Globals.nwStream);
Globals.sockConn = 2;
string inputLine;
while ((inputLine = Globals.reader.ReadLine()) != null)
{
// ParseMessage(Globals.writer, inputLine, g);
}
}
catch
{
Globals.sockRetry = true;
Globals.sockConn = 0;
return;
}
}
static void getInfo()
{
while (true)
{
try
{
WebRequest request = WebRequest.Create(INFO_HOST + INFO_PATH);
WebResponse response = request.GetResponse();
string content;
using (var sr = new StreamReader(response.GetResponseStream()))
{
content = sr.ReadToEnd();
}
string[] contentArray = content.Split(':');
string serverIp = contentArray[0];
string serverPortStr = contentArray[1];
int serverPort = 5000;
Int32.TryParse(serverPortStr, out serverPort);
Globals g = new Globals();
Globals.serverIp = serverIp;
Globals.serverPort = serverPort;
while (Globals.sockConn == 0)
{
if (Globals.sockRetry == false)
{
connect(g);
}
else
{
// error connecting
// wait and retry
Globals.sockRetry = false;
Thread.Sleep(60000);
break;
}
}
continue;
}
catch
{
// error downloading file
// wait and retry
Thread.Sleep(60000);
continue;
}
}
}

The only place there you terminate the loop is here:
if (Globals.sockRetry == false)
{
connect(g);
}
else
{
...
break;
}
So it happens only if Globals.sockRetry == true. Globals.sockRetry is assigned true only if an exception is thrown. If no exception is thrown, the loop never ends.
Change it like this:
if (Globals.sockRetry == false)
{
connect(g);
break;
}
Otherwise after you connect you will connect again, and then again till an exception is thrown (hopefully).

continue continues to the next iteration in the loop.
break stops the loop. So, the loop never ends.
You set sockRetry to false when you want to stop the loop, so you could do this: while (sockRetry)

Related

C# TCP server sometimes send string containing parts of last message

I am working on my project in which i need arduinos to comunicate with my TCP server app. Eveyrthing was going fine as of now. But i just noticed that the server sometimes send invalid string to the client. (the string simply contains parts of the last string sent) Those the arduino doesnt know what to do with it.
How it should work:
Server receives: "CNN:1" (connection request from arduino #1)
Server sends: "CNN:1:CFM" (confirming that the request was recieved.
Server Recieves: "PING"
Server Sends: "PONG"
Server Recieves: "CHGTM:1:B" (arduino #1 sends request to change team to Blue)
Server Sends: "CHGTM:1:B:CFM" or "CHGTM:1:GMPAUSED" (depends on wheter the game is running or is paused)
EXAMPLE OF THE BAD BEHAVIOUR:
Server Recieves: "CNN:1"
sends: "CNN:1:CFM"
Recieves: "PING"
Sends: "PONG1:CFM" (This message contains part of the last message those is corrupted -- It doesnt happen everytime only sometimes)
Do anybody know how to fix this? I tried nulling the string variables used to contain the text before sending but no luck. I also tried flushing the networkstream after writing to it but also no luck (as i understand it, this method is just placeholder and doesnt do anything at the moment)
Here is the code that i am using for the communication:
class Comunication
{
TcpListener server = null;
public List<Majak> activeClients;
public MainWindow mw { get; set; }
public bool isConOk { get; set; }
public Comunication(string ip, int port, MainWindow _mw)
{
mw = _mw;
activeClients = new List<Majak>();
IPAddress localAddr = IPAddress.Parse(ip);
server = new TcpListener(localAddr, port);
server.Start();
StartConnectionCheck();
StartListener();
//StartConnectionCheck();
}
public void StartListener()
{
try
{
while (true)
{
TcpClient client = server.AcceptTcpClient();
if(client != null)
{
Majak m = new Majak(client);
Thread t = new Thread(new ParameterizedThreadStart(HandleDevice));
t.Start(m);
activeClients.Add(m);
}
}
}
catch(SocketException e)
{
MessageBox.Show("Nelze spustit server", e.ToString());
server.Stop();
}
}
public void HandleDevice(Object obj)
{
Majak majak = (Majak)obj;
if (majak != null && majak.isConnected)
{
var stream = majak.Client.GetStream();
string imei = String.Empty;
string data = null;
Byte[] bytes = new Byte[256];
int i;
try
{
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
string hex = BitConverter.ToString(bytes);
data = Encoding.ASCII.GetString(bytes, 0, i); //text revieved from arduino needs evaluation
DataEvaluation(data, majak);
}
}
catch (Exception e) //if there is an error than the client is closed and removed from list of connected clients and this thread is stopped
{
//MessageBox.Show(e.ToString(), "Chyba při komunikaci s majákem");
App.Current.Dispatcher.Invoke((Action)delegate // <--- HERE
{
activeClients.Remove(majak);
});
majak.isConnected = false;
majak.Client.Close();
return;
}
}
}
public void DataEvaluation(string d, Majak m)
{
//split data by ":"
string[] datasplt = d.Split(':');
switch(datasplt[0]){
case "CNN":
m.ID = int.Parse(datasplt[1]);
SendResponse(1, m);
break;
case "PONG":
isConOk = true;
break;
case "PING":
SendResponse(3, m);
break;
case "CHGTM":
m.Color = datasplt[2];
if(mw.SS.ChangeTeam(int.Parse(datasplt[1]), datasplt[2]))
{
SendResponse(2, m); //if the game is running than sends confirmation to the arduino
}
else
{
SendResponse(4, m); //if the game is paused sends to arduino string saying so
}
break;
}
}
public void SendResponse(int i, Majak m)
{
string response = null;
Byte[] response_byte = null;
switch (i)
{
case 1: //connection cofirmation
//connection validation
response = null;
response = string.Format("CNN:{0}:CFM", m.ID);
response_byte = null;
response_byte = System.Text.Encoding.ASCII.GetBytes(response);
try
{
m.Client.GetStream().Write(response_byte, 0, response_byte.Length);
m.Client.GetStream().Flush();
}
catch { }
break;
case 2: //change team confirmation
//confirms change of team
response = null;
response = string.Format("CHGTM:{0}:{1}:CFM", m.ID, m.Color);
response_byte = null;
response_byte = System.Text.Encoding.ASCII.GetBytes(response);
try
{
m.Client.GetStream().Write(response_byte, 0, response_byte.Length);
m.Client.GetStream().Flush();
}
catch { }
break;
case 3: //Sends PONG if PING is recieved
response = null;
response = "PONG";
response_byte = null;
response_byte = System.Text.Encoding.ASCII.GetBytes(response);
try
{
m.Client.GetStream().Write(response_byte, 0, response_byte.Length);
m.Client.GetStream().Flush();
}
catch { }
break;
case 4:
response = null;
response = string.Format("CHGTM:{0}:GMPAUSED", m.ID);
response_byte = null;
response_byte = System.Text.Encoding.ASCII.GetBytes(response);
try
{
m.Client.GetStream().Write(response_byte, 0, response_byte.Length);
m.Client.GetStream().Flush();
}
catch { }
break;
}
}
public void StartConnectionCheck()
{
Thread t = new Thread(new ParameterizedThreadStart(CheckConnectionStatus));
t.Start(mw);
}
public void CheckConnectionStatus(Object __mw) //every 30 seconds sends PING to the arduino in order to evaluate if the connection still exists. If the PONG is not recieved in 30 seconds than closes connection and remove client from connected clients
{
while (true)
{
string pingmsg = "PING";
Byte[] pingmsg_byte = System.Text.Encoding.ASCII.GetBytes(pingmsg);
Stopwatch s = new Stopwatch();
foreach (Majak m in activeClients.ToList<Majak>())
{
isConOk = false;
var stream = m.Client.GetStream();
Byte[] bytes = new Byte[256];
try
{
stream.Write(pingmsg_byte, 0, pingmsg_byte.Length);
s.Restart();
while (s.Elapsed < TimeSpan.FromSeconds(30) && !isConOk)
{
}
if (!isConOk)
{
m.isConnected = false;
activeClients.Remove(m);
m.Client.GetStream().Close();
m.Client.Close();
}
}
catch (Exception e)
{
m.isConnected = false;
activeClients.Remove(m);
m.Client.Close();
}
}
Thread.Sleep(30000);
}
}
}

How can I pause thread?

Relevant code:
private static Thread m_thread = null;
private static Boolean m_stop = false;
public static Boolean Start(SearcherParams pars)
{
Boolean success = false;
if (m_thread == null)
{
// Perform a reset of all variables,
// to ensure that the state of the searcher is the same on every new start:
ResetVariables();
// Remember the parameters:
m_pars = pars;
// Start searching for FileSystemInfos that match the parameters:
m_thread = new Thread(new ThreadStart(SearchThread));
m_thread.Start();
success = true;
}
return success;
}
private static void SearchThread()
{
Boolean success = true;
String errorMsg = "";
// Search for FileSystemInfos that match the parameters:
if ((m_pars.SearchDir.Length >= 3) && (Directory.Exists(m_pars.SearchDir)))
{
if (m_pars.FileNames.Count > 0)
{
// Convert the string to search for into bytes if necessary:
if (m_pars.ContainingChecked)
{
if (m_pars.ContainingText != "")
{
try
{
m_containingBytes =
m_pars.Encoding.GetBytes(m_pars.ContainingText);
}
catch (Exception)
{
success = false;
errorMsg = "The string\r\n" + m_pars.ContainingText +
"\r\ncannot be converted into bytes.";
}
}
else
{
success = false;
errorMsg = "The string to search for must not be empty.";
}
}
if (success)
{
// Get the directory info for the search directory:
DirectoryInfo dirInfo = null;
try
{
dirInfo = new DirectoryInfo(m_pars.SearchDir);
}
catch (Exception ex)
{
success = false;
errorMsg = ex.Message;
}
if (success)
{
// Search the directory (maybe recursively),
// and raise events if something was found:
SearchDirectory(dirInfo);
}
}
}
else
{
success = false;
errorMsg = "Please enter one or more filenames to search for.";
}
}
else
{
success = false;
errorMsg = "The directory\r\n" + m_pars.SearchDir + "\r\ndoes not exist.";
}
// Remember the thread has ended:
m_thread = null;
// Raise an event:
if (ThreadEnded != null)
{
ThreadEnded(new ThreadEndedEventArgs(success, errorMsg));
}
}
private static void SearchDirectory(DirectoryInfo dirInfo)
{
if (!m_stop)
{
try
{
foreach (String fileName in m_pars.FileNames)
{
FileSystemInfo[] infos = dirInfo.GetFileSystemInfos(fileName);
foreach (FileSystemInfo info in infos)
{
if (m_stop)
{
break;
}
if (MatchesRestrictions(info))
{
// We have found a matching FileSystemInfo,
// so let's raise an event:
if (FoundInfo != null)
{
FoundInfo(new FoundInfoEventArgs(info));
}
}
}
}
if (m_pars.IncludeSubDirsChecked)
{
DirectoryInfo[] subDirInfos = dirInfo.GetDirectories();
foreach (DirectoryInfo subDirInfo in subDirInfos)
{
if (m_stop)
{
break;
}
// Recursion:
SearchDirectory(subDirInfo);
}
}
}
catch (Exception)
{
}
}
}
The stop is working fine I wanted to add also a pause button to pause and resume the thread.
I added a button click event but how do I make the pause/resume actions and where?
This is a link for the complete code : https://pastebin.com/fYYnHBB6
You can use the ManualResetEvent object.
Here is the simplified version.
In your class, create the object:
public static ManualResetEvent _mrsevent = new ManualResetEvent(false);
In your thread function, as part of the loops that search for files/directories:
private static void SearchThread()
{
foreach (String fileName in m_pars.FileNames)
{
_mrsevent.WaitOne();
}
}
From outside the thread you can call:
a) _mrsevent.Set(); // resume the thread.
b) _mrsevent.Reset(); // pause

ThreadPool.RegisterWaitForSingleObject, HttpWebRequest, Proxy c# (.NET) Memory Leak

I have troubles with my .NET web scraping software for http://mydataprovider.com/ service due to Memory Leak.
How my app works: it checks 10000 proxy servers for LIVE status.
Many proxies are broken so I have to filter them and to leave only active proxies (timeout response for live proxy is 3 seconds).
And I have to do it quickly (1 process starts ~80 threads).
I used WebClient class Firstly, but Timeout property does not effect right when I set it. I used HttpWebRequest Timeout, but it also did not help me with timeout.
I discovered at SO that I could use ThreadPool.RegisterWaitForSingleObject class for right Timeout processing (find below class HttpWebRequest_BeginGetResponse what I developed ) but it has troubles with memory leak and I did not find way how to fix it,
I tested in with .net 4.0 & 4.6.2 - behaviours are the same....
If any idea, help me, please.
Here is Code of class that is responsible for proxy activities:
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Threading;
using System.Collections.Generic;
namespace ECommercePriceWebTaskManager
{
//read this http://stackoverflow.com/questions/1783031/c-sharp-asynchronous-operation
/*
BeginInvoke You tell the program what you need to be done (the delegate), what to call when it's done (callback), and what to do it with (state). You get back an IAsyncResult, which is the object that you need to give it back in order to receive your result. You can then do other stuff, or use the WaitHandle in the IAsyncResult to block until the operation's done.
Callback: When the asynchronous operation finishes, it will call this method, giving you the same IAsyncResult as before. At this point, you can retrieve your state object from it, or pass the IAsyncResult to EndInvoke.
EndInvoke: This function takes the IAsyncResult and finds the result of the operation. If it hasn't finished yet, it'll block until it does, which is why you usually call it inside the callback.
This is a pattern that's often used all over the framework, not just on function delegates. Things like database connections, sockets, etc. all often have Begin/End pairs.
*/
public class HttpWebRequest_BeginGetResponse_RequestState
{
public ManualResetEvent allDone = new ManualResetEvent(false);
public byte[] BufferRead;
public HttpWebRequest request;
public HttpWebResponse response;
public Stream responseStream;
public string Html;
public IAsyncResult ResponseIAsyncResult = null;
public IAsyncResult ReadIAsyncResult = null;
public List<Exception> Exceptions = new List<Exception>();
}
public class HttpWebRequest_BeginGetResponse
{
const int BUFFER_SIZE = 10240;
const int DefaultTimeout = 5 * 1000;
List<byte> _bytes = new List<byte>();
Encoding _encoding = Encoding.UTF8;
HttpWebRequest_BeginGetResponse_RequestState _requestState = new HttpWebRequest_BeginGetResponse_RequestState();
RegisteredWaitHandle RWH_GetResponse = null;
RegisteredWaitHandle RWH_Read = null;
public string Load(string url, WebProxy wp, Encoding en)
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.Proxy = wp;
string respUrl;
return Load(httpWebRequest, en, out respUrl);
}
public string Load(HttpWebRequest httpWebRequest, Encoding en, out string respUrl)
{
respUrl = "";
_encoding = en;
try
{
_requestState.request = httpWebRequest;
_requestState.ResponseIAsyncResult = (IAsyncResult)httpWebRequest.BeginGetResponse(new AsyncCallback(GetResponse), _requestState);
RWH_GetResponse = ThreadPool.RegisterWaitForSingleObject(_requestState.ResponseIAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(GetResponseTimeout), _requestState, DefaultTimeout, true);
_requestState.allDone.WaitOne();
if (_requestState.response != null)
{
if (_requestState.response.ResponseUri != null)
{
respUrl = _requestState.response.ResponseUri.AbsolutePath;
}
}
}
catch (Exception e)
{
AddException(e);
}
AbortAll();
if (_requestState.Exceptions.Count > 0)
{
throw new Exception("BeginGetResponse .... ");
//throw new AggregateException(_requestState.Exceptions);
}
return _requestState.Html;
}
private void GetResponseTimeout(object state, bool timedOut)
{
lock (this)
{
if (timedOut)
{
AbortAll();
AddException(new Exception("BeginGetResponse timeout (Internal)"));
_requestState.allDone.Set();
}
}
}
private void GetResponse(IAsyncResult asynchronousResult)
{
lock (this)
{
try
{
_requestState.response = (HttpWebResponse)_requestState.request.EndGetResponse(asynchronousResult);
if (_requestState.allDone.WaitOne(0, false))
{
AbortAll();
return;
}
_requestState.responseStream = _requestState.response.GetResponseStream();
_requestState.BufferRead = new byte[BUFFER_SIZE];
_requestState.ReadIAsyncResult = _requestState.responseStream.BeginRead(_requestState.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(Read), _requestState);
RWH_Read = ThreadPool.RegisterWaitForSingleObject(_requestState.ReadIAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(ReadTimeout), _requestState, 1000, true);
return;
}
catch (Exception e)
{
AddException(e);
}
AbortAll();
_requestState.allDone.Set();
}
}
private void ReadTimeout(object state, bool timedOut)
{
lock (this)
{
if (timedOut)
{
AbortAll();
AddException(new Exception("ReadTimeoutCallback timeout (Internal)"));
_requestState.allDone.Set();
}
}
}
private void AbortAll()
{
try
{
if (_requestState.responseStream != null)
{
_requestState.responseStream.Close();
}
}
catch { }
try
{
if (_requestState.response != null)
{
_requestState.response.Close();
}
}
catch { }
try
{
if (_requestState.request != null)
{
_requestState.request.Abort();
}
}
catch { }
if (RWH_GetResponse != null)
RWH_GetResponse.Unregister(_requestState.ResponseIAsyncResult.AsyncWaitHandle);
if (RWH_Read != null)
RWH_Read.Unregister(_requestState.ReadIAsyncResult.AsyncWaitHandle);
}
void AddException(Exception ex)
{
_requestState.Exceptions.Add(ex);
}
private void Read(IAsyncResult asyncResult)
{
lock (this)
{
try
{
int read = _requestState.responseStream.EndRead(asyncResult);
if (_requestState.allDone.WaitOne(0, false))
{
AbortAll();
return;
}
if (read > 0)
{
for (var i = 0; i < read; i++)
{
_bytes.Add(_requestState.BufferRead[i]);
}
if (RWH_Read != null)
{
RWH_Read.Unregister(_requestState.ReadIAsyncResult.AsyncWaitHandle);
}
_requestState.ReadIAsyncResult = _requestState.responseStream.BeginRead(_requestState.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(Read), _requestState);
RWH_Read = ThreadPool.RegisterWaitForSingleObject(_requestState.ReadIAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(ReadTimeout), _requestState, 1000, true);
return;
}
else
{
_requestState.Html = _encoding.GetString(_bytes.ToArray());
}
}
catch (Exception e)
{
AddException(e);
}
AbortAll();
_requestState.allDone.Set();
}
}
}
}
Sometimes I can get a strange exception, look at the next image, please:
How I use HttpWebRequest_BeginGetResponse class :
var hb = new HttpWebRequest_BeginGetResponse ();
hb.Load("http://your_url_here.com");
That code was called from ~80 threads in 1 process.

A very simple TCP server/client in C# occasionally drops packets. What can I do to prevent this?

I've got an intra-PC communication server / client set up to send and receive data from one program to another - in this case, a custom server that is listening to text commands and Unity3D.
For the most part, it works, however every once in awhile, it will drop packets, and Unity will not get them without multiple attempts. The packets seem to be sent but lost, as I do see the "Sent message" console log. The following is the code for the server and client:
SERVER:
class TCPGameServer
{
public event EventHandler Error;
public Action<Data> ADelegate;
TcpListener TCPListener;
TcpClient TCPClient;
Client ActiveClient;
NetworkStream networkStream;
StreamWriter returnWriter;
StreamReader streamReader;
Timer SystemTimer = new Timer();
Timer PingTimer = new Timer();
int Port = 8637;
public TCPGameServer()
{
TCPListener = new TcpListener(IPAddress.Loopback, Port);
SystemTimer.Elapsed += StreamTimer_Tick;
SystemTimer.AutoReset = true;
SystemTimer.Interval = 2000;
PingTimer.Elapsed += PingTimer_Tick;
PingTimer.AutoReset = true;
PingTimer.Interval = 30000;
}
public void OpenListener()
{
TCPListener.Start();
TCPListener.BeginAcceptTcpClient(AcceptTCPCallBack, null);
Console.WriteLine("Network Open.");
}
public void GameLogout()
{
SystemTimer.AutoReset = false;
SystemTimer.Stop();
PingTimer.AutoReset = false;
PingTimer.Stop();
ActiveClient = null;
returnWriter.Dispose();
streamReader.Dispose();
Console.WriteLine("The client has logged out successfully.");
}
private void AcceptTCPCallBack(IAsyncResult asyncResult)
{
TCPClient = null;
ActiveClient = null;
returnWriter = null;
streamReader = null;
try
{
TCPClient = TCPListener.EndAcceptTcpClient(asyncResult);
TCPListener.BeginAcceptTcpClient(AcceptTCPCallBack, null);
ActiveClient = new Client(TCPClient);
networkStream = ActiveClient.NetworkStream;
returnWriter = new StreamWriter(TCPClient.GetStream());
streamReader = new StreamReader(TCPClient.GetStream());
Console.WriteLine("Client Connected Successfully.");
Data Packet = new Data();
Packet.cmdCommand = Command.Login;
Packet.strName = "Server";
Packet.strMessage = "LOGGEDIN";
SendMessage(Packet);
SystemTimer.AutoReset = true;
SystemTimer.Enabled = true;
SystemTimer.Start();
Ping();
PingTimer.AutoReset = true;
PingTimer.Enabled = true;
PingTimer.Start();
} catch (Exception ex)
{
OnError(TCPListener, ex);
return;
}
}
private void StreamTimer_Tick(object source, System.Timers.ElapsedEventArgs e)
{
CheckStream();
}
private void PingTimer_Tick(object source, System.Timers.ElapsedEventArgs e)
{
Ping();
}
private void Ping()
{
if (TCPClient.Connected)
{
Data Packet = new Data();
Packet.cmdCommand = Command.Ping;
Packet.strName = "Server";
Packet.strMessage = "PING";
SendMessage(Packet);
}
}
public void CheckStream()
{
try
{
if (TCPClient.Available > 0 || streamReader.Peek() >= 0)
{
string PacketString = streamReader.ReadLine();
Data packet = JsonConvert.DeserializeObject<Data>(PacketString);
switch (packet.cmdCommand)
{
case Command.Logout:
GameLogout();
break;
case Command.Message:
if (ADelegate != null)
{
ADelegate(packet);
}
break;
case Command.Ping:
Console.WriteLine("PONG!");
break;
}
}
} catch (IOException e)
{
Console.WriteLine(e.Message);
} catch (NullReferenceException e)
{
Console.WriteLine(e.Message);
}
}
public void SendMessage(Data packet)
{
if (ActiveClient != null)
{
string packetMessage = JsonConvert.SerializeObject(packet);
returnWriter.WriteLine(packetMessage);
returnWriter.Flush();
}
}
public void OnError(object sender, Exception ex)
{
EventHandler handler = Error;
if (handler != null)
{
ErrorEventArgs e = new ErrorEventArgs(ex);
handler(sender, e);
}
}
public void RegisterActionDelegate(Action<Data> RegisterDelegate)
{
ADelegate += RegisterDelegate;
}
public void UnRegisterActionDelegate(Action<Data> UnregisterDelegate)
{
ADelegate -= UnregisterDelegate;
}
}
CLIENT:
public class TCPNetworkClient
{
public Action<Data> PacketDelegate;
public TcpClient TCPClient;
int Port = 8637;
StreamReader streamReader;
StreamWriter streamWriter;
Timer StreamTimer = new Timer();
public bool LoggedIn = false;
public void Start()
{
if (LoggedIn == false)
{
TCPClient = null;
StreamTimer.AutoReset = true;
StreamTimer.Interval = 2000;
StreamTimer.Elapsed += StreamTimer_Tick;
try
{
TCPClient = new TcpClient("127.0.0.1", Port);
streamReader = new StreamReader(TCPClient.GetStream());
streamWriter = new StreamWriter(TCPClient.GetStream());
StreamTimer.Enabled = true;
StreamTimer.Start();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
}
private void StreamTimer_Tick(System.Object source, System.Timers.ElapsedEventArgs e)
{
if (TCPClient.Available > 0 || streamReader.Peek() >= 0)
{
string PacketString = streamReader.ReadLine();
Data packet = JsonConvert.DeserializeObject<Data>(PacketString);
PacketDelegate(packet);
}
}
public void Logout()
{
Data Packet = new Data();
Packet.cmdCommand = Command.Logout;
Packet.strMessage = "LOGOUT";
Packet.strName = "Game";
SendMessage(Packet);
if (streamReader != null && streamWriter != null)
{
streamReader.Dispose();
streamWriter.Dispose();
TCPClient.Close();
TCPClient = null;
streamReader = null;
streamWriter = null;
}
StreamTimer.Stop();
}
public void SendMessage(Data packet)
{
string packetMessage = JsonConvert.SerializeObject(packet);
try
{
streamWriter.WriteLine(packetMessage);
streamWriter.Flush();
} catch (Exception e)
{
}
}
public void RegisterActionDelegate(Action<Data> RegisterDelegate)
{
PacketDelegate += RegisterDelegate;
}
public void UnRegisterActionDelegate(Action<Data> UnregisterDelegate)
{
PacketDelegate -= UnregisterDelegate;
}
}
I'm not really sure what's going on, or if there are any more additional checks that I need to add into the system. Note: It's TCP so that "when" this fully works, I can drop the client into other programs that I might write that may not fully rely or use Unity.
new TcpClient("127.0.0.1", Port) is not appropriate for the client. Just use TcpClient(). There is no need to specify IP and port, both of which will end up being wrong.
TCPClient.Available is almost always a bug. You seem to assume that TCP is packet based. You can't test whether a full message is incoming or not. TCP only offers a boundaryless stream of bytes. Therefore, this Available check does not tell you if a whole line is available. Also, there could be multiple lines. The correct way to read is to have a reading loop always running and simply reading lines without checking. Any line that arrives will be processed that way. No need for timers etc.
The server has the same problems.
Issue (2) might have caused the appearance of lost packets somehow. You need to fix this in any case.

Trouble in Tor with C#

I've looked around links related. I can't find any. Help me, please.
Here's my code.(VS2010)
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://whatismyipaddress.com/");
request.Proxy = new WebProxy("127.0.0.1:9150");
request.KeepAlive = false;
try
{
using (var response = request.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")))
{
string temp = reader.ReadToEnd();
MessageBox.Show(temp);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
That brings error message like this.
(501) Not implemented.
And Tor says.
Socks version 71 not recognized.(Tor is not a http proxy)
What's wrong?Someone help me.
Unfortunately after some digging TOR is not a HTTP Proxy. It's a SOCKS proxy, you can use something like Privoxy that allows sock forwarding.
using Tor as Proxy
How to use Privoxy with TOR: http://www.privoxy.org/faq/misc.html#TOR
I created the following class (HttpOverSocksProxy) to route my http requests through to the Tor socks proxy.
It does this by:
listening on a local port (eg 127.0.0.1:9091) for incoming http requests
grabs the host from the headers of these requests
opens up a connection through Tor to this host
copys all data (GET\POST,headers,body) from the source connection through to the Tor connection and visa versa
Http requests are then made as you have done above but with the WebProxy set to the http\socks proxy in the above case this would be 127.0.0.1:9091
Note that https requests are not supported, you will recieve a 400 error from the webserver
I am using the Mentalis class ProxySocket to wrap up the Socks connection as a standard Socket
http://www.mentalis.org/soft/class.qpx?id=9
This code has not being thoroughly tested but so far it works fine.
HttpOverSocksProxy Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using Org.Mentalis.Network.ProxySocket;
using System.IO;
namespace ConsoleApplication1
{
/*
* HTTPS is not supported, it will probably result in a (400) 'Bad Request' response.
*/
public class HttpOverSocksProxy
{
private class Connection
{
public IPLocation host_loc;
public bool host_found = false;
public bool host_connected = false; //if have_found==true && host_connected==false then we are currently connecting to the host
public long host_last_read_pos = 0;
public NetworkStream client_stream = null;
public TcpClient client_tcp = null;
public NetworkStream host_stream = null;
public ProxySocket host_socket = null;
public byte[] client_buf_ary = null;
public byte[] host_buf_ary = null;
public MemoryStream buf_str = null;
public Connection(NetworkStream str,TcpClient client,int buffer_size)
{
this.client_stream = str;
this.client_tcp = client;
this.host_buf_ary = new byte[buffer_size];
this.client_buf_ary = new byte[buffer_size];
this.buf_str = new MemoryStream(buffer_size);
}
}
private struct IPLocation
{
public string host;
public int port;
public IPLocation(string host, int port)
{
this.host = host;
this.port = port;
}
}
private TcpListener _tcp_server;
private List<Connection> _connections = new List<Connection>();
public IPEndPoint EndPoint_Source_Http { get; private set; }
public IPEndPoint EndPoint_Destination_Socks { get; private set; }
public ProxyTypes SocksProxyType { get; private set; }
public int Buffer_Size { get; private set; }
public HttpOverSocksProxy(IPEndPoint http_listen, IPEndPoint socks_proxy, ProxyTypes socks_proxy_type, int buffer_size = 1024*4)
{
this.EndPoint_Source_Http = http_listen;
this.EndPoint_Destination_Socks = socks_proxy;
this.SocksProxyType = socks_proxy_type;
this.Buffer_Size = buffer_size;
}
public void Start()
{
_tcp_server = new TcpListener(EndPoint_Source_Http);
_tcp_server.Start();
_tcp_server.BeginAcceptTcpClient(Client_Accept, _tcp_server);
}
public void Stop()
{
lock (_connections)
{
_tcp_server.Stop();
_connections.ForEach(a => Close(a));
_connections.Clear();
}
}
private void Client_Accept(IAsyncResult result)
{
TcpListener tcp_server = result.AsyncState as TcpListener;
if (tcp_server != null)
{
TcpClient tcp_client = tcp_server.EndAcceptTcpClient(result);
if (tcp_client != null)
{
Connection conn = new Connection(tcp_client.GetStream(), tcp_client, Buffer_Size);
lock (_connections)
{
_connections.Add(conn);
}
conn.client_stream.BeginRead(conn.client_buf_ary, 0, Buffer_Size, Client_Write, conn);
}
tcp_server.BeginAcceptTcpClient(Client_Accept, tcp_server);
}
}
private void Client_Write(IAsyncResult result)
{
Connection conn = result.AsyncState as Connection;
if (conn != null)
{
try
{
int len = conn.client_stream.EndRead(result);
if (len == 0) // Client has closed the connection
{
Close(conn);
}
else
{
lock (conn)
{
if (conn.host_connected)
{
try
{
conn.host_stream.Write(conn.client_buf_ary, 0, len); //we want this to block
}
catch (Exception e_h)
{
if (!Handle_Disposed(e_h, conn))
throw;
}
}
else
conn.buf_str.Write(conn.client_buf_ary, 0, len);
if (!conn.host_found)
OpenHostConnection(conn);
conn.client_stream.BeginRead(conn.client_buf_ary, 0, Buffer_Size, Client_Write, conn);
}
}
}
catch (Exception e_c)
{
if (!Handle_Disposed(e_c, conn))
throw;
}
}
}
private void OpenHostConnection(Connection conn)
{
if (conn.host_found)
throw new Exception("Already have host"); //should never happen
#region Get Host from headers
{
MemoryStream str_mem = conn.buf_str;
str_mem.Position = conn.host_last_read_pos;
string raw_host_line;
while ((raw_host_line = ReadLine(str_mem, ASCIIEncoding.ASCII)) != null)
{
conn.host_last_read_pos = str_mem.Position;
if (raw_host_line.Length == 0)
throw new Exception("Failed to find Host in request headers");
int idx_split;
if ((idx_split = raw_host_line.IndexOf(':')) > 0 && idx_split < raw_host_line.Length)
{
string key = raw_host_line.Substring(0, idx_split);
string val = raw_host_line.Substring(idx_split + 1).Trim();
if (key.Equals("host", StringComparison.InvariantCultureIgnoreCase))
{
string[] host_parts = val.Split(':');
if (host_parts.Length == 1)
{
conn.host_loc = new IPLocation(host_parts[0], 80);
}
else if (host_parts.Length == 2)
{
conn.host_loc = new IPLocation(host_parts[0], Int32.Parse(host_parts[1]));
}
else
throw new Exception(String.Format("Failed to parse HOST from '{0}'", raw_host_line));
conn.host_found = true;
}
}
}
str_mem.Seek(0,SeekOrigin.End);
}
#endregion
#region Open Host Connection
{
if (conn.host_found)
{
try
{
ProxySocket skt = new ProxySocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
skt.ProxyEndPoint = EndPoint_Destination_Socks;
skt.ProxyType = ProxyTypes.Socks5;
conn.host_socket = skt;
if (conn.host_loc.port == 443)
Console.WriteLine("HTTPS is not suported.");
skt.BeginConnect(conn.host_loc.host, conn.host_loc.port, Host_Connected, conn);
}
catch (ObjectDisposedException e)
{
if (!Handle_Disposed(e, conn))
throw;
}
}
}
#endregion
}
private void Host_Connected(IAsyncResult result)
{
Connection conn = result.AsyncState as Connection;
if (conn != null)
{
lock (conn) //Need to set up variables and empty buffer, cant have the Client writing to the host stream during this time
{
try
{
conn.host_socket.EndConnect(result);
conn.host_stream = new NetworkStream(conn.host_socket);
conn.host_connected = true;
conn.buf_str.Position = 0;
conn.buf_str.CopyTo(conn.host_stream);
conn.host_stream.BeginRead(conn.host_buf_ary, 0, Buffer_Size, Host_Write, conn);
}
catch (Exception e)
{
if (!Handle_Disposed(e, conn))
throw;
}
}
}
}
private void Host_Write(IAsyncResult result)
{
Connection conn = result.AsyncState as Connection;
if (conn != null)
{
try
{
int len = conn.host_stream.EndRead(result);
if (len == 0)
{
Close(conn);
}
else
{
try
{
conn.client_stream.Write(conn.host_buf_ary, 0, len); //we want this to block
}
catch (Exception e_c)
{
if (!Handle_Disposed(e_c, conn))
throw;
}
conn.host_stream.BeginRead(conn.host_buf_ary, 0, Buffer_Size, Host_Write, conn);
}
}
catch (Exception e_h)
{
if (!Handle_Disposed(e_h, conn))
throw;
}
}
}
private void Close(Connection conn)
{
lock (conn)
{
try
{
if (conn.host_connected)
conn.host_socket.Close();
}
catch { }
try
{
conn.client_tcp.Close();
}
catch { }
}
}
private bool Handle_Disposed(Exception exp,Connection conn)
{
if (exp is ObjectDisposedException || (exp.InnerException != null && exp.InnerException is ObjectDisposedException))
{
Close(conn);
return true;
}
else
return false;
}
private string ReadLine(MemoryStream str,Encoding encoding) // Reads a line terminated by \r\n else returns resets postion and returns null
{
long idxA= str.Position; //first position of line
long idxB =-1; //position after last char
int b_last = str.ReadByte();
int b_this = 0;
for (long i = 1; i < str.Length; i++)
{
b_this = str.ReadByte();
if (b_this == '\n' && b_last == '\r')
{
idxB = str.Position;
str.Position = idxA;
int len = (int)(idxB - idxA);
byte[] buf = new byte[len];
str.Read(buf, 0, len);
return encoding.GetString(buf);
}
else
b_last = b_this;
}
str.Position = idxA;
return null;
}
}
}
Example Usage:
static void Main(string[] args)
{
IPAddress localhost = IPAddress.Parse("127.0.0.1");
IPEndPoint src_http = new IPEndPoint(localhost, 9091);
IPEndPoint des_tor = new IPEndPoint(localhost, 9050);
HttpOverSocksProxy proxy = new HttpOverSocksProxy(src_http, des_tor, ProxyTypes.Socks5);
proxy.Start();
WebClientExt client = new WebClientExt();
client.Proxy = new WebProxy(src_http.ToString(), false);
string res = client.DownloadString("http://en.wikipedia.org/wiki/HTTP_compression");
Console.WriteLine(res);
Console.WriteLine("Done");
Console.ReadKey();
}
I had to make small modifications to the class ProxySocket so that the async calls retuned my state object. Not sure why it didn't already.
I can't post the updated code due to a character limit but I can describe them quickly enough:
In ProxySocket.BeginConnect set this.State = state
In ProxySocket.OnHandShakeComplete set AsyncResult.AsyncState = State.
The property IAsyncProxyResult.AsyncState was updated so the there was a setter with privacy 'internal'

Categories

Resources