Many TCPClients in benchmark do not close properly - c#

I'm currently programing a benchmark for my TCP-Socket Server.
The basic concept is the following:
The Client creates 10000 connections
There are 2500 connections concurrent
They all send 10 seconds ping-pong messages to the server and receive the pong
After the 10 seconds they all disconnect
When I use smaller numbers of connections (100 concurrent and 1000 connections) everything works fine, but with the setup above, some of the connections remain connected at the server.
This means that the close call never reaches the server at all.
Here is the code for the explanation above:
class Program {
static List<Thread> mConnectionThreads_ = new List<Thread>(); //!< The list of the Threads for all textloaders
static List<TCPConnection> mConnections_ = new List<TCPConnection>(); //!< The list of TextsXMLParser
static void Main(string[] args) {
int numConnections = 10000;
int numConcurrentConnections = 2500;
for( int k = 0; k < numConnections/numConcurrentConnections; ++k) {
for( int i = 0; i < numConcurrentConnections; ++i ) {
TCPConnection connection = new TCPConnection();
connection.connect(((k+1)*numConcurrentConnections)+i);
mConnections_.Add(connection);
mConnectionThreads_.Add(new Thread(connection.pingLoop));
}
Console.WriteLine(((k+1)*numConcurrentConnections) + "/" + numConnections + " Threads connected");
// start all threads
foreach (Thread t in mConnectionThreads_)
t.Start();
foreach (Thread t in mConnectionThreads_)
t.Join();
foreach (TCPConnection c in mConnections_)
c.disconnect();
Console.WriteLine(((k+1)*numConcurrentConnections) + "/" + numConnections + " Threads disconnected " + cnt + " calls");
mConnections_.Clear();
mConnectionThreads_.Clear();
}
}
}
The disconnect function looks like the following:
public void disconnect() {
if( mClient_.Client != null ) {
mClient_.Client.Disconnect(false);
//mClient_.GetStream().Close();
//mClient_.Close();
Console.WriteLine("closed " + mConnectionId_);
}
else if( mClient_.Client == null )
Console.WriteLine("closed invalid " + mConnectionId_);
}
As you can see I've already tried a lot of different close methods, but neighter works.
Is there anything I can do in this case? Anybody else having the same issue?

Maybe I'm missing something but what type has mClient_.Client?
Usually if you use TCP client (TCPClient class) you can call Close to close the connection. In the same fashion when using directly Socket or NetworkStream you can also call Close.
On the other hand you're detecting and debugging connection open/closed connections on the server, right? There can be the possibility that server code does not handle connection close properly and thus you get incorrect statistics.
Also under heavy load, server may not have enough CPU time to update the state for the connections so you can expect some delays. Does your server uses asynchronous I/O or connection per thread principle?

Related

How can I properly close a socket connection in C# / WPF

I implemented a little TCP connection to a program of mine, used for communication between a WPF application and a hosted Unity3D application.
I ran into a problem though when trying to re-open the window, the Unity3D application is hosted in.
public void SocketServer()
{
IPAddress ipAd = IPAddress.Parse("127.0.0.1");
// use local m/c IP address, and
// use the same in the client
/* Initializes the Listener */
myList = new TcpListener(ipAd, 8002);
/* Start Listeneting at the specified port */
myList.Start();
MsgHandler placeHolderClass = new MsgHandler();
Debug.WriteLine("The server is running at port 8001...");
Console.WriteLine("The local End point is :" + myList.LocalEndpoint);
Console.WriteLine("Waiting for a connection.....");
s = myList.AcceptSocket();
while (true)
{
byte[] b = new byte[100];
int k = s.Receive(b);
Console.WriteLine("Recieved...");
string recived = "";
for (int i = 0; i < k; i++)
{
recived += Convert.ToChar(b[i]);
}
Console.Write(recived);
//ASCIIEncoding asen = new ASCIIEncoding();
//s.Send(asen.GetBytes("Hey I Got This Msg" + recived));
MsgUpdate = recived;
placeHolderClass.GetInfosFromDB(recived);
}
// Console.WriteLine("\nSent Acknowledgement");
/* clean up */
}
Is just something I found online. If I keep it this way and re-open the window, it throws an exception that the port is already in use. Fair enough, I never closed the connection. I get that. Then I went ahead and added
void PageUnloaded(object sender, RoutedEventArgs e) {
if(s != null) {
s.Shutdown(SocketShutdown.Both);
s.Close();
}
myList.Stop();
}
But this doesn't work. If I do it without the if-check, it tells me that s is null, which doesn't make sense, because if I check if it is null it still throws me an exception,
A blocking operation was interrupted by a call to WSACancelBlockingCall.
A quick search leads me to believe, that the thread containing my socket is actually closed before I even call my PageUnloaded function.
But how do I fix this? Is this even a good approach? I read online that this implementation is very bad - but then five searches later this seems to be the best approach possible for my needs. I'm at a loss here, can anyone point me in the right direction? Thanks! :)

what is the best multi-threading technique in c#

I'm developing an application that is running a lot of TcpListener tasks
using c# with .net 3.5 on windows server 2008
the TcpListener task is:
listening
to get an xml message
read an ID
from it
send a command to a
specific camera based on the ID to
take a snapshot and store it in a
folder
This is meant to execute within 1 second so I can take a snapshot with the camera. I've got a delay in executing this task, using the following code:
private Thread listen_thread;
public void start_listen()
{
this.listen_thread = new Thread(new ThreadStart(save_data));
this.listen_thread.Priority = ThreadPriority.Normal;
this.listen_thread.Start();
}
private void save_data()
{
//work to be done
}
Is this the best multi-threading technique to use? This application is running on a on dell poweredge 2900
with 2 quad core prosessor, and I think it could go faster. How might I be able to improve the latency of this code?
thats the code for the tcplistener
Int32 port = controller_port;
try
{
//this server ip
IPAddress localAddr = IPAddress.Parse(this_ip);
server = new TcpListener(localAddr, port);
server.Start();
Byte[] bytes = new Byte[256];
String data = null;
while (true)
{
Console.Write("Waiting for a connection... ");
TcpClient client = server.AcceptTcpClient();
Console.Write("Connected!");
data = null;
NetworkStream stream = client.GetStream();
int i;
string add_data = "";
Console.Write("Waiting...!");
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
try
{
string full_row = "";
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.Write("Received from controller: " + data);
add_data += data;
}
catch{}
}
}
}
then i divide it to get the ID .
It's not clear at all
how you receive requests
upon what you parallelize the application
It seems that you listen on different sockets and assign a thread on each of them.
I think this is a poor choice, because you can't control the parallelism degree.
You could instead have just one thread that nondeterministically listens on all sockets and assigns the connection to a thread pool, configured to simultaneously run at most n threads, where n is the parallelism degree of your machine (if you have a dual quadcore, n is equal to 8).
These methods have strikingly wrong names. start_listen() doesn't start listening. save_data() cannot possibly save any data until at least a connection is established. Which requires the client code to start up first and make the connection. Sure, one second is quickly gone with that. Starting a thread doesn't take more than a fraction of a millisecond when there's a core available.
Focus on the code that's missing in your snippet.

C# server - is this good way for timeouting and disconnecting?

On my multithreaded server I am experiencincg troubles with connections that are not coming from the proper Client and so hang unathorized. I did not want to create new thread only for checking if clients are connected for some time without authorization. Instead of this, I have add this checking to RecieveData thread, shown on the code below. Do you see some performance issue or this is acceptable? The main point is that everytime client is connected (and Class client is instantionized) it starts stopwatch. And so I add to this thread condition - if the time is greater than 1 and the client is still not authorized, its added on the list of clients determinated for disconnection. Thanks
EDIT: This While(true) is RecieveData thread. I am using async. operations - from tcplistener.BeginAccept to threadpooling. I have updated the code to let you see more.
protected void ReceiveData()
{
List<Client> ClientsToDisconnect = new List<Client>();
List<System.Net.Sockets.Socket> sockets = new List<System.Net.Sockets.Socket>();
bool noClients = false;
while (true)
{
sockets.Clear();
this.mClientsSynchronization.TryEnterReadLock(-1);
try
{
for (int i = 0; i < this.mClientsValues.Count; i++)
{
Client c = this.mClientsValues[i];
if (!c.IsDisconnected && !c.ReadingInProgress)
{
sockets.Add(c.Socket);
}
//clients connected more than 1 second without recieved name are suspect and should be disconnected
if (c.State == ClientState.NameNotReceived && c.watch.Elapsed.TotalSeconds > 1)
ClientsToDisconnect.Add(c);
}
if (sockets.Count == 0)
{
continue;
}
}
finally
{
this.mClientsSynchronization.ExitReadLock();
}
try
{
System.Net.Sockets.Socket.Select(sockets, null, null, RECEIVE_DATA_TIMEOUT);
foreach (System.Net.Sockets.Socket s in sockets)
{
Client c = this.mClients[s];
if (!c.SetReadingInProgress())
{
System.Threading.ThreadPool.QueueUserWorkItem(c.ReadData);
}
}
//remove clients in ClientsToDisconnect
foreach (Client c in ClientsToDisconnect)
{
this.RemoveClient(c,true);
}
}
catch (Exception e)
{
//this.OnExceptionCaught(this, new ExceptionCaughtEventArgs(e, "Exception when reading data."));
}
}
}
I think I see what you are trying to do and I think a better way would be to store new connections in a holding area until they have properly connected.
I'm not positive but it looks like your code could drop a valid connection. If a new connection is made after the checking section and the second section takes more than a second all the timers would time out before you could verify the connections. This would put the new connections in both the socket pool AND the ClientsToDisconnect pool. Not good. You would drop a currently active connection and chaos would ensue.
To avoid this, I would make the verification of a connection a seperate thread from the using of the connection. That way you won't get bogged down in timing issues (well...you still will but that is what happens when we work with threads and sockets) and you are sure that all the sockets you are using won't get closed by you.
My gut reaction is that while (true) plus if (sockets.Count == 0) continue will lead to heartache for your CPU. Why don't you put this on a Timer or something so that this function is only called every ~.5s? Is the 1s barrier really that important?

"Unable to connect to remote server fail" in HttpWebRequest

I am using VSTS 2008 + C# + .Net 3.5 to develop a console application and I send request to another server (IIS 7.0 on Windows Server 2008). I find when the # of request threads are big (e.g. 2000 threads), the client will receive error "Unable to connect to remote server fail" when invoking response = (HttpWebResponse)request.GetResponse().My confusion is -- I have set timeout to be a large value, but I got such fail message within a minute. I think even if the connection are really larger than what IIS could serve, client should not get such fail message so soon, it should get such message after timeout period. Any comments? Any ideas what is wrong? Any ideas to make more number of concurrent connection being served by IIS 7.0?
Here is my code,
class Program
{
private static int ClientCount = 2000;
private static string TargetURL = "http://labtest/abc.wmv";
private static int Timeout = 3600;
static void PerformanceWorker()
{
Stream dataStream = null;
HttpWebRequest request = null;
HttpWebResponse response = null;
StreamReader reader = null;
try
{
request = (HttpWebRequest)WebRequest.Create(TargetURL);
request.Timeout = Timeout * 1000;
request.Proxy = null;
response = (HttpWebResponse)request.GetResponse();
dataStream = response.GetResponseStream();
reader = new StreamReader(dataStream);
// 1 M at one time
char[] c = new char[1000 * 10];
while (reader.Read(c, 0, c.Length) > 0)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
}
finally
{
if (null != reader)
{
reader.Close();
}
if (null != dataStream)
{
dataStream.Close();
}
if (null != response)
{
response.Close();
}
}
}
static void Main(string[] args)
{
Thread[] workers = new Thread[ClientCount];
for (int i = 0; i < ClientCount; i++)
{
workers[i] = new Thread((new ThreadStart(PerformanceWorker)));
}
for (int i = 0; i < ClientCount; i++)
{
workers[i].Start();
}
for (int i = 0; i < ClientCount; i++)
{
workers[i].Join();
}
return;
}
}
Kev answered you question already, I just want to add that creating so many threads is not really good design solution (just context switching overhead is a big minus) plus it won't scale good.
The quick answer would be: use asynchronous operations to read data instead of creating a bunch of threads. Or at least use thread pool (and lower worker thread count). Remember that more connections to one source will only speed things up till some degree. Try benchmarking it and you will see that probably 3-5 connections will work faster that 2000 you are using now.
You can read more about asynchronous client/server architecture (IOCP - input/output completion ports) and its advantages here. You can start from here:
MSDN - Using an Asynchronous Server Socket
MSDN - Asynchronous Server Socket Example
CodeProject - Multi-threaded .NET TCP Server Examples
All of these examples uses lower level TCP object, but it can be applied to WebRequest/WebResponse as well.
UPDATE
To try thread pool version, you can do something like this:
ManualResetEvent[] events = new ManualResetEvent[ClientCount];
for (uint cnt = 0; cnt < events.Length; cnt++)
{
events[cnt] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(obj => PerformanceWorker());
}
WaitHandle.WaitAll(events);
Not tested, may need some adjustment.
I reckon you've maxed out the web site's application pool queue. The default is 1000 requests, you're flooding the server with 2000 requests more or less all at once. Increasing the timeout isn't going to solve this.
Try increasing the Queue Length for the application pool the site resides in.
You should try and capture the underlying HTTP status, that'll give you a clue as to what is really going on.
Update:
When I run your code and try and download a sizeable file (200MB) I get (503) Server Unavailable.. Increasing the size of the Application Pool's request queue solves this (I set mine to 10000).
Only once did I see Unable to connect to remote server and sadly have been unable to replicate. This error sounds like there's something broken at the TCP/IP layer. Can you post the full exception?
Go to Smart Thread Pool and downlod the code. It is an instance thread pool that constrains the number of threads. The .Net Thread pool can be problematic in applications that connect to web servers and SQL servers.
Change the loop to this
static void Main(string[] args)
{
var stp = new SmartThreadPool((int) TimeSpan.FromMinutes(5).TotalMilliseconds,
Environment.ProcessorCount - 1, Environment.ProcessorCount - 1);
stp.Start();
for (var i = 0; i < ClientCount; i++)
{
stp.QueueWorkItem(PerformanceWorker);
}
stp.WaitForIdle();
stp.Shutdown();
return;
}
This constrains the thread pool to use 1 thread per proc. Adjust this up until performance starts to degrade. Too many threads are worse than too few. you many find that this is optimal.
Also add this to you config. The value of 100 is a default I use. There is a way to do this in code but the syntax escapes me now.
<system.net>
<connectionManagement>
<add address=“*“ maxconnection=“100“ />
</connectionManagement>
</system.net>
I am using Visual Studio 2005. How to send an SMS, here is my code:
IPHostEntry host;
host = Dns.GetHostEntry(Dns.GetHostName());
UriBuilder urlbuilder = new UriBuilder();
urlbuilder.Host = host.HostName;
urlbuilder.Port = 4719;
string PhoneNumber = "9655336272";
string message = "Just a simple text";
string subject = "MMS subject";
string YourChoiceofName = "victoria";
urlbuilder.Query = string.Format("PhoneNumber=%2B" + PhoneNumber + "&MMSFrom=" + YourChoiceofName + "&MMSSubject=" + subject + "&MMSText=" + message);//+ "&MMSFile=http://127.0.0.1/" + fileName
HttpWebRequest httpReq = (HttpWebRequest)WebRequest.Create(new Uri(urlbuilder.ToString(), false));
HttpWebResponse httpResponse = (HttpWebResponse)(httpReq.GetResponse());

Convert Ping application to multithreaded version to increase speed - C#

I have an application that pings every possible IP on your local subnet in order to compile a list of responsive IP addresses. Currently it pings all 255 one at a time. Is it possible to convert this app to use multiple threads to increase the speed by pinging more than one at a time? I am new to the concept of multiple threads and figure this would be a good way to learn(as long as it's possible of course).
also, any stylistic improvements you can educate me on would also be helpful.
thanks ahead of time
Here is the current pinging method in a backgroundWorker1_DoWork event.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
count = 0;
for (int i = 1; i < 255; i++)
{
Ping ping = new Ping();
PingReply pingreply = ping.Send(IPAddress.Parse(locip[0] + "." + locip[1] + "." + locip[2] + "." + i));
count += 1;
if (pingreply.Status == IPStatus.Success)
{
status = "o";
repAddress = pingreply.Address.ToString(); ;
repRoundtrip = pingreply.RoundtripTime.ToString();
repTTL = pingreply.Options.Ttl.ToString();
repBuffer = pingreply.Buffer.Length.ToString();
string[] lineBuffer = { status, repAddress, repRoundtrip, repTTL, repBuffer };
ipList.Rows.Add(lineBuffer);
}
progressBar.Invoke(new MethodInvoker(UpdateProgressBarByOne));
progressStatus.Text = ("Pinging IP " + count + " of 254");
}
button1.Enabled = true;
progressBar.Invoke(new MethodInvoker(ResetProgressBar));
}
It looks like Ping has a SendAsync function. This post (I know its vb, but just to get an idea) has an example. In summary, just change your Send to SendAsync and listen for the PingCompleted event
Well my advice is to look into your concurrency points.
Firstly you will hit a bug with any access to windows forms objects off the thread. i.e your access to button1 WILL throw an MDA in debug, and might crash at runtime randomly. You have to use a delegate and invoke the method back on the main thread using a pattern like this.
this.Invoke(delgatetomyupdatermethod)
Secondly, your time is spent in the ping itself. So I would recommend writing a threadsafe list (just write a method with a lock on it
private object locker = new object();
private void InsertIntoList(string linebuffer)
{
lock(locker)
{
ipList.Rows.Add(linebuffer);
}
}
I would recommend using the .Net threadpool to run your method instead to ping a given IP.
To do this write a function that will take in the IP to ping and to update the list with your result, then call it by queueing up items on the threadpool. Indeed if you pass in an object with a ManualResetEvent you can even write your code to say
System.Threading.WaitHandle[] waits = new System.Threading.WaitHandle[255];
//initialise the list of these and create the objects to ping.
foreach (var obj in mylistofobjectvalues)
{
System.Threading.Threadpool.QueueUserWorkItem(method, obj);
}
System.Threading.WaitHandle.WaitAll(waits);
where method is the ping method, obj contains an object with the manualresetevent and information your method needs to ping it's target.
Each time your waithandle completes you can update your state. With some more effort on your GUI you could even have the system working asynchronously, so that your gui is updated on each response, not just at the end.

Categories

Resources