Updated question for Ping Async: Large amount of pings in async task - getting Exception "An asynchronous call is already in progress."
I've got a Windows Service that grabs a list of hosts from a MySQL Database and reports back if the host was pingable. This works great for small amounts of IP's, but I'm expecting about 200+ IP's at a time, and one or two hosts being down is causing a lot of lag. My quick and dirty solution was opening the ping's in a thread, so that the loop can continue to run if one host is down or has a slow network... It works.. but not well. I'm new at this, but I know enough to realize this can't be the best way to do it. Any help/guidance would be greatly appreciated!
try
{
MySqlConnection Connection = new MySqlConnection(ConnectionString);
Connection.Open();
MySqlCommand query = Connection.CreateCommand();
query.CommandText = "SELECT obj_id AS id,ip FROM objects LIMIT 200";
MySqlDataReader Nodes = query.ExecuteReader();
// Record in log that a NEW iteration is starting - for tracking issues with pings
Library.WriteErrorLog("######################## New Iteration ########################");
int i = 1;
while(Nodes.Read())
{
// Open a new thread for each ping. There are over 2000 host objects in the database - if we do not open in seperate threads we will never finish
// each thread will ping the hosts and results will be logged in log.txt and MySQL
string Host = (i == 5 ? "google.com" : Nodes["ip"].ToString());
Host = (i == 4 ? "lindevenv" : Host);
int HostID = int.Parse(Nodes["id"].ToString()); // Obj -> string -> int because super awesome .NET logic
Thread thread = new Thread(() => UpdateStatus(Host, HostID, ConnectionString, i));
thread.Start();
i++;
}
Connection.Close();
}
catch(Exception ee)
{
Library.WriteErrorLog("Error: " + ee.ToString());
}
and...
// Called by the thread as the worker method inside CheckStatus Method below
private void UpdateStatus(string Host, int HostID, string ConnectionString, int loopID)
{
try
{
Ping pinger = new Ping();
PingReply reply = pinger.Send(Host, 3000);
if (reply.Status == IPStatus.Success)
{
Library.WriteErrorLog("(" + loopID + ") " + Host + " is UP!");
}
else
{
Library.WriteErrorLog("(" + loopID + ") " + Host + " is DOWN!");
Library.ReportDown(HostID, ConnectionString);
}
}
catch (PingException e)
{
// Do not throw exception - a pingexception is thrown when there is a timeout/dns/other issue - report as down
Library.WriteErrorLog("(" + loopID + ") " + Host + " is DOWN!");
Library.ReportDown(HostID, ConnectionString);
}
}
In addition to being extemely memory heavy, some information gets left out/duplicated between threads which makes it very unreliable.
Related
I am testing both service broker external activator and polling based client on behalf of process speed performances of each.
For external activator, I have built a command line application which is being notified when any change occur some table and writes to the same db. Code inside exe looks like as follows
private static void ProcessRequest()
{
using (var connection = new SqlConnection(ServiceConstant.ConnectionString))
{
connection.Open();
do
{
using (var tran = connection.BeginTransaction())
{
//Get a message from the queue
byte[] message = QueueProcessorUtil.GetMessage(ServiceConstant.QueueName, connection, tran, ServiceConstant.WaitforTimeout);
if (message != null)
{
MessageReceiving = true;
try
{
//Write it to the db
ProcessMessage(message);
}
catch (Exception ex)
{
logger.Write("Fail: " + ex);
}
tran.Commit();
}
else
{
tran.Commit();
MessageReceiving = false;
}
}
}
while (MessageReceiving);
}
}
When I insert 20 messages to the queue, total duration of insertion of all the messages is approx 10ms
When I extract the ProcessMessage function above which writes the messages to the db to an another separate console application and then call this function 20 times as follows, this time it takes approx 50ms
class Program
{
static void Main(string[] args)
{
for (var i = 1; i <= 20; i++)
{
string message = "mm";
ProcessMessaage(message);
}
}
}
ProcessMessage function
string sql = #"INSERT INTO [Workflow].[dbo].[TestOrderLog]([OrderId],[RecordTime])
VALUES (#orderId, GETDATE()) SELECT SCOPE_IDENTITY()";
using (SqlConnection con = new SqlConnection(ConfigurationManager.AppSettings["SqlConnection"].ToString()))
using (SqlCommand com = new SqlCommand(sql, con))
{
con.Open();
com.CommandType = CommandType.Text;
com.Parameters.AddWithValue("#orderId", 1);
try
{
var result = com.ExecuteScalar();
var id = (result != null) ? Convert.ToInt32(result) : 0;
}
catch (Exception ex)
{
throw ex;
}
con.Close();
}
I don't understand and am surprised although there are costly processing blocks (query a message) inside the loop of external activator code, it takes faster to write db than pure loop in console app code.
Why would pure insertion in a loop be slower than insertion inside the external activator exe instance's code?
Side note, in EAService.config file, <Concurrency min="1" max="1" />
It was an absurd mistake of mine, first one is compiled and deployed running code
and the second one is running with debugger inside visual studio, so the intervals became normal running without debugger.
I have implemented SqlClient connecting function with timeout parameter. It means, that connection.open() is in another thread and after thread is started, I'm checking elapsed time. If the time had reached timeout, thread is aborted and no connection is established.
The thing is, that if I have timeout bigger then default connection.open() timeout, open() throws SqlException, which isn't caught in my Catch(SqlException) block.
I'm starting whole connecting process in another thread:
public void connect()
{
Thread connectThread = new Thread(waitForTimeout);
connectThread.Start();
}
Connecting thread -> starts another thread for timeout waiting
public void waitForTimeout()
{
connection = new SqlConnection(connectString);
Thread timeoutThread = new Thread(openConnection);
timeoutThread.Start();
DateTime quitTime = DateTime.Now.AddMilliseconds(timeout);
while (DateTime.Now < quitTime)
{
if (connection.State == ConnectionState.Open)
{
transac = connection.BeginTransaction();
command = connection.CreateCommand();
command.Transaction = transac;
break;
}
}
if (connection.State != ConnectionState.Open)
timeoutThread.Interrupt();
}
Here exception isn't caught after open() default timeout:
private void openConnection()
{
try
{
connection.Open();
}
catch(SqlException ex)
{
// This isn't caught anytime
}
}
Thank you for any ideas!
Isn't it caught or isn't it thrown? Thread.start only schedules the thread for running but doesn't mean it will start immediately. Maybe code runs till threadTimeout interruption, then openConnection starts and always succeed to open the connection within default timeout.
---edit
In this case maybe could you try to:
replace SqlException by Exception and check if you catch something such as ThreadInterruptedException instead
put the content of openConnection method in your waitForTimeout method right after connection = new SqlConnection(connectString); (and comment the rest of the code) and see if exception is still not handled. If not, then put it in the connect() method and check again.
After comments I tried to implement new solution, and here it is:
Constructor:
/* ------------------------------------------------------------------------- */
public Database(string source, string database, string user, string password,
int timeout, DelegateConnectionResult connectResult)
{
this.timeout = timeout;
this.connectResult = connectResult;
connectString = "server=" + source +
";database=" + database +
";uid=" + user +
";pwd=" + password +
";connect timeout=" + Convert.ToInt16(timeout / 1000);
}
Asynchonous connect:
/* ------------------------------------------------------------------------- */
public void connectAsync()
{
connectThread = new Thread(connectSync);
connectThread.Start();
}
Synchronous connect:
/* ------------------------------------------------------------------------- */
public void connectSync()
{
connection = new SqlConnection(connectString);
try
{
connection.Open();
transac = connection.BeginTransaction();
command = connection.CreateCommand();
command.Transaction = transac;
if (connection.State == ConnectionState.Open)
connectResult(true);
else
connectResult(false);
}
catch
{
connectResult(false);
}
}
And I found the solution for original problem witch SqlException from this post: it has something to do with Exceptions settings in debugger of Visual Studio. If I unchecked "throw" choice at SqlException in Exceptions list (CTRL + D + E in Visual Studio), I'm finally able to catch exception.
I have written code for server and multiple client using threads and sockets. Normally the clients exits by sending the 'exit' keyword to server but I want the server to also detect situation when the clients exits forcefully without sending 'exit' keyword to server, for example when user in middle of sending message to server presses cross button of client window. What I want is that server should detect this situation and displays some error code and continue receiving message from other clients connected to it.
Second problem I am facing how can I disconnect server even if multiple clients are connected to it. In my code I am using tcpListener.Stop() but when i use this method error message "server failed to start at ipaddress" is displayed and number of such windows opens is equivalent to number of clients server is listening. For example if server is listening to 1000 clients then 1000 such windows will open showing the earlier mentioned error message which doesn't look good from the point of person using this software. So How can I handle this situation? Also in this situation if clients again starts sending message to the server then is also starts receiving messages even though I have disconnected the server. The server should remain disconnected until the user restarts server.
Following is my code for server.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
// Constants IP address of server and maximum number of clients server can connect.
static class Constants
{
public const string IP = "127.0.0.1";
public const int No_Of_Clients = 2;
}
// server port number
int port_number;
static IPAddress ipAddress = IPAddress.Parse(Constants.IP);
TcpListener tcpListener;
public Form1()
{
InitializeComponent();
button1.Click += button1_Click;
button2.Click += button2_Click;
//this.FormClosing += Form1_FormClosing;
}
//Socket socketForClient;
private void button1_Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(textBox1.Text.Trim()))
{
System.Windows.Forms.MessageBox.Show("Port Number Empty", "Error");
}
else
{
port_number = int.Parse(textBox1.Text);
createserver(Constants.No_Of_Clients);
serveripaddress();
infoBox1.Text = string.Format("The server is now listening at port {0} at ip address {1}", port_number, Constants.IP);
infoBox1.Text = infoBox1.Text + "\r\n" + string.Format("The server can listen to maximum {0} number of clients", Constants.No_Of_Clients);
}
}
// this code disconnects the server
private void button2_Click(object sender, EventArgs e)
{
try
{
tcpListener.Stop();
}
catch (Exception f)
{
MessageBox.Show(f.Message);
}
}
public void serveripaddress()
{
serverip.Text = "Server IP : " + Constants.IP;
//serverport.Text = "Port Number : " + port.ToString();
}
// Starts server
private void createserver(int no_of_clients)
{
tcpListener = new TcpListener(ipAddress, port_number);
tcpListener.Start();
for (int i = 0; i < no_of_clients; i++)
{
Thread newThread = new Thread(new ThreadStart(Listeners));
newThread.Start();
}
} // end of createserver();
//listen to client receiving messages
public void Listeners()
{
Socket socketForClient;
try
{
socketForClient = tcpListener.AcceptSocket();
}
catch
{
System.Windows.Forms.MessageBox.Show(string.Format("Server failed to start at {0}:{1}", Constants.IP, port_number), "Error");
return;
}
if (socketForClient.Connected)
{
//System.Windows.Forms.MessageBox.Show("hello");
string string1 = string.Format("Client : " + socketForClient.RemoteEndPoint + " is now connected to server.");
infoBox1.Text = infoBox1.Text + "\r\n" + string1;
NetworkStream networkStream = new NetworkStream(socketForClient);
System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(networkStream);
System.IO.StreamReader streamReader = new System.IO.StreamReader(networkStream);
string theString = "";
while (true)
{
try
{
theString = streamReader.ReadLine();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
// if (streamReader.ReadLine() == null )
//{
// System.Windows.Forms.MessageBox.Show(string.Format("Server failed to start at {0}:{1}", Constants.IP, port_number), "Error");
// }
if (theString != "exit")
{
textBox2.Text = textBox2.Text + "\r\n" + "-----------------------------------------------------------------------------------";
string string2 = string.Format("Message recieved from client(" + socketForClient.RemoteEndPoint + ") : " + theString);
textBox2.Text = textBox2.Text + "\r\n" + string2;
// ASCII code for the message from client
string string3 = string.Format("ASCII Code for message is : ");
textBox2.Text = textBox2.Text + "\r\n" + string3;
string string4 = "";
foreach (char c in theString)
{
string4 += string.Format(System.Convert.ToInt32(c) + " ");
}
textBox2.Text = textBox2.Text + string4;
// Hex value of message from client
string hex = "";
foreach (char c in theString)
{
int tmp = c;
hex += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
}
string string5 = string.Format("Hex Code for the message from client : " + hex);
textBox2.Text = textBox2.Text + "\r\n" + string5;
//sending acknowledgement to client
try
{
socketForClient.Send(new ASCIIEncoding().GetBytes("The string was recieved from Client(" + socketForClient.RemoteEndPoint + ") : " + theString));
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
} // end of if loop
// if exit from client
else
{
string string7 = string.Format("Client " + socketForClient.RemoteEndPoint + " has exited");
infoBox1.Text = infoBox1.Text + "\r\n" + string7;
break;
}
} // end of while loop
streamReader.Close();
networkStream.Close();
streamWriter.Close();
} // end of if loop
socketForClient.Close();
}
}
}
To be informed about closed client connections you have to send periodically a 'heartbeat' message to the client. If the client connection died the tcp/ip mechanism will inform you after the timeout that the connection died (can't remember the name of the exception).
If the client wants to know if the connection died he has also to send a heartbeat message.
This is needed as the tcp connection recognizes lost connections only if data is sent over this connection.
For the second problem you should keep a list of all the active clients (your variable socketForClient). When you want to end your server you close all the client connections (the clients in the list).
Hey guys this is my first attempt at using the Task libraries in 4.0 so if you see anything else I'm besides my problem that is not correct please do let me know.
My problem is that when I schedule a bunch of task which inside use a webclient to make a request, the first few make it through just fine, but after a certain time my webclient starts throwing an exception. It as if it creates the webclient then sticks in the Task and waits for a thread to pick it up but by that time the timeout time is reached .. that's just my assumption.
Here is the code :
var TmsThread = Task.Factory.StartNew(() => UpdateTmsNullPackages(), TaskCreationOptions.LongRunning);
that runs in the Form1_Load of the windows app. This is what it calls
public void UpdateTmsNullPackages()
{
Parallel.ForEach(TmsNullPackages, Package =>
{
try
{
Task<string> task = Task.Factory.StartNew(() => Package.GetPackageTmsId(), TaskCreationOptions.AttachedToParent);
task.ContinueWith(t =>
{
if (!String.IsNullOrEmpty(t.Result))
{
Package.TMSID = t.Result;
NowTmsIdFoundPackages.Add(Package);
}
});
}
catch(Exception ex){}
});
}
which in turn, runs this
public static string GetPackageTmsId(this TwcPackage Package)
{
string TMSID = null;
if (!(String.IsNullOrEmpty(Package.movie_Provider)) && !(String.IsNullOrEmpty(Package.movie_Product)) && !(String.IsNullOrEmpty(Package.movie_Provider_ID)) && !(String.IsNullOrEmpty(Package.movie_Asset_ID)))
{
try
{
using (WebClient client = new WebClient())
{
client.Credentials = new NetworkCredential(TMSID_Recheck.Properties.Settings.Default.WebRequestUser, TMSID_Recheck.Properties.Settings.Default.WebRequestProdUserPassWord);
XmlDocument xmlDoc = new XmlDocument();
string URLToBeRequested = TMSID_Recheck.Properties.Settings.Default.RequestProdBaseURL + TMSID_Recheck.Properties.Settings.Default.RequestAPIVersion + "/" + TMSID_Recheck.Properties.Settings.Default.RequestAPIProgramServiceCall + TMSID_Recheck.Properties.Settings.Default.RequestAPIProgramAssociationServiceCall + Package.movie_Provider + ':' + Package.movie_Product + ':' + Package.movie_Provider_ID + "::" + Package.movie_Asset_ID;
try
{
xmlDoc.LoadXml(client.DownloadString(URLToBeRequested));
XmlNodeList Program = xmlDoc.DocumentElement.SelectNodes("program");
if (Program.Count > 0) TMSID = Program[0].Attributes["TMSId"].Value.ToString();
}
catch (WebException ex)
{
if (ex.Status != WebExceptionStatus.Timeout)
{
if (((HttpWebResponse)ex.Response).StatusCode != HttpStatusCode.NotFound) { }
}
else { }
}
}
}
catch (Exception ix) { }
}
return TMSID;
}
the issue happens when downloadstring is called after a couple hundred tasks it throws a timeout exception.
the issue happens when downloadstring is called after a couple hundred tasks
And how many tasks have completed in that time slice?
It looks like you are simply queuing too many requests. Your system and the remote server probably have policies in place to limit the number of simultaneous connections.
The solution (and a quick diagnosis test) would be to use MaxDegreeOfParallelism in the ForEach.
Here is a similar question with some good answers.
I am creating a networking library in C# that I can use in any application, and as part of this library I have a TCP client/server setup. This setup works perfectly in almost every situation; it connects, sends/receives data, and disconnects flawlessly when under minimal and medium stress loads. However, when I send large amounts of data from the client to the server, the client socket works for a varied amount of time (sometimes short, sometimes long) and then just refuses to send data for a while. Specifically, my data rate goes from the 550-750 KBps range to 0 KBps, and sits there for again a varied amount of time. Then the socket will start sending again for a very short time, and get "throttled" again. During the throttling, i was assuming that the socket was disconnected because I couldn't send anything, but Polling returns that the socket IS connected using this code:
public bool IsConnected(Socket socket)
{
try
{
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
}
catch (SocketException) { return false; }
}
I just took a networking class at my college, so I started thinking about the congestion control and flow control mechanisms in TCP, but it seems to me that neither would cause this problem; congestion control only slows the data rate, and a full buffer on the receiver's side wouldn't last nearly the length of time I am getting a 0 KBps data rate. The symptom seems to point towards either some type of heavy data throttling or mass scale dropping of packets.
My question is this: does anyone have any idea what might be causing this data "throttling", for lack of a better term? Also, is it possible that the packets I send are going further than just my router even though they are addressed to a host in the same subnet?
Edit: Just so it is clear, the reason I am trying to fix this problem is because I want to send files over TCP at the highest possible data rate. I understand that UDP can be used as well, and I will also be making a solution using it, but I want TCP to work first.
Specific Information:
I am using blocking read/write operations, and the server is multi-threaded. The client runs on its own thread as well. I am testing on my local subnet, bouncing all packets through my router, which should have a throughput of 54 Mbps. The packets are 8 KB each in size, and at maximum would be sent 1000 times a second (sending thread sleeps 1 ms), but obviously are not reaching that rate. Reducing the size of the packets so the data rate is lower causes the throttling to disappear. Windows 7 machines, 1 server, 1 client. The send operation always completes, it is the receive operation that errors out.
The send operation is below:
//get a copy of all the packets currently in the queue
IPacket[] toSend;
lock (packetQueues[c])
{
if (packetQueues[c].Count > SEND_MAX)
{
toSend = packetQueues[c].GetRange(0, SEND_MAX).ToArray();
packetQueues[c].RemoveRange(0, SEND_MAX);
}
else
{
toSend = packetQueues[c].ToArray();
packetQueues[c].RemoveRange(0, toSend.Length);
}
}
if (toSend != null && toSend.Length > 0)
{ //write the packets to the network stream
try
{
writer.Write(toSend.Length);
}
catch (Exception e)
{
Logger.Log(e);
if (showErrorMessages)
MessageBox.Show("Client " + (int)c + ": " + e, "Error", MessageBoxButtons.OK);
}
for (int i = 0; i < toSend.Length; i++)
{
try
{
toSend[i].Write(writer);
if (onSend != null)
{
object[] args = new object[2];
args[0] = c;
args[1] = toSend[i];
onSend(args);
}
}
catch (Exception e)
{
Logger.Log(e);
if (showErrorMessages)
MessageBox.Show("Client " + (int)c + ": " + e, "Error", MessageBoxButtons.OK);
}
}
}
And this is the receive code:
try
{
//default buffer size of a TcpClient is 8192 bytes, or 2048 characters
if (client.Available > 0)
{
int numPackets = reader.ReadInt32();
for (int i = 0; i < numPackets; i++)
{
readPacket.Clear();
readPacket.Read(reader);
if (owner != null)
{
owner.AcceptPacket(readPacket, c); //application handles null packets itself.
if (onReceive != null)
{
object[] args = new object[2];
args[0] = c;
args[1] = readPacket;
onReceive(args);
}
}
}
timestamps[c] = TimeManager.GetCurrentMilliseconds();
}
else
{
double now = TimeManager.GetCurrentMilliseconds();
if (now - timestamps[c] >= timeToDisconnect)
{ //if timestamp is old enough, check for connection.
connected[c] = IsConnected(client.Client);
if (!connected[c])
{
netStream.Close();
clients[c].Close();
numConnections--;
if (onTimeout != null) onTimeout(c);
}
else
{
timestamps[c] = now;
}
}
}
}
catch (Exception s)
{
Logger.Log(s);
if (showErrorMessages)
MessageBox.Show("Client " + (int)c + ": " + s, "Error", MessageBoxButtons.OK);
}
Packet send/receive:
public void Write(BinaryWriter w)
{
w.Write(command); //byte
w.Write(data.Type); //short
w.Write(data.Data.Length); //int
w.Write(data.Data); //byte array
w.Flush();
}
/// <summary>
/// Reads a command packet from data off a network stream.
/// </summary>
/// <param name="r">The stream reader.</param>
public void Read(BinaryReader r)
{
command = r.ReadByte();
short dataType = r.ReadInt16();
int dataSize = r.ReadInt32();
byte[] bytes = r.ReadBytes(dataSize);
data = new PortableObject(dataType, bytes);
}
Full Server Communication Loop:
public void Communicate(object cl)
{
int c = (int)cl;
timestamps[c] = TimeManager.GetCurrentMilliseconds();
try
{
//Console.Out.WriteLine("Thread " + Thread.CurrentThread.ManagedThreadId + " has started up. c = " + (int)c);
TcpClient client = clients[c];
client.ReceiveTimeout = 100;
NetworkStream netStream = client.GetStream();
BinaryReader reader = new BinaryReader(netStream);
BinaryWriter writer = new BinaryWriter(netStream);
while (client != null && connected[c])
{
#region Receive
try
{
//default buffer size of a TcpClient is 8192 bytes, or 2048 characters
if (client.Available > 0)
{
int numPackets = reader.ReadInt32();
for (int i = 0; i < numPackets; i++)
{
readPacket.Clear();
readPacket.Read(reader);
if (owner != null)
{
owner.AcceptPacket(readPacket, c); //application handles null packets itself.
if (onReceive != null)
{
object[] args = new object[2];
args[0] = c;
args[1] = readPacket;
onReceive(args);
}
}
}
timestamps[c] = TimeManager.GetCurrentMilliseconds();
}
else
{
double now = TimeManager.GetCurrentMilliseconds();
if (now - timestamps[c] >= timeToDisconnect)
{ //if timestamp is old enough, check for connection.
connected[c] = IsConnected(client.Client);
if (!connected[c])
{
netStream.Close();
clients[c].Close();
numConnections--;
if (onTimeout != null) onTimeout(c);
}
else
{
timestamps[c] = now;
}
}
}
}
catch (Exception s)
{
Logger.Log(s);
if (showErrorMessages)
MessageBox.Show("Client " + (int)c + ": " + s, "Error", MessageBoxButtons.OK);
}
#endregion
Thread.Sleep(threadLatency);
#region Send
//get a copy of all the packets currently in the queue
IPacket[] toSend;
lock (packetQueues[c])
{
if (packetQueues[c].Count > SEND_MAX)
{
toSend = packetQueues[c].GetRange(0, SEND_MAX).ToArray();
packetQueues[c].RemoveRange(0, SEND_MAX);
}
else
{
toSend = packetQueues[c].ToArray();
packetQueues[c].RemoveRange(0, toSend.Length);
}
}
if (toSend != null && toSend.Length > 0)
{ //write the packets to the network stream
try
{
writer.Write(toSend.Length);
}
catch (Exception e)
{
Logger.Log(e);
if (showErrorMessages)
MessageBox.Show("Client " + (int)c + ": " + e, "Error", MessageBoxButtons.OK);
}
for (int i = 0; i < toSend.Length; i++)
{
try
{
toSend[i].Write(writer);
if (onSend != null)
{
object[] args = new object[2];
args[0] = c;
args[1] = toSend[i];
onSend(args);
}
}
catch (Exception e)
{
Logger.Log(e);
if (showErrorMessages)
MessageBox.Show("Client " + (int)c + ": " + e, "Error", MessageBoxButtons.OK);
}
}
}
#endregion
}
}
catch (ThreadAbortException tae)
{
Logger.Log(tae);
MessageBox.Show("Thread " + (int)cl + " was aborted.", "Error", MessageBoxButtons.OK);
}
}
It is probably your code, but it's difficult for us to say as it's incomplete.
I wrote up my own set of best practices in a .NET TCP/IP FAQ - after many, many years of TCP/IP experience. I recommend you start with that.
P.S. I reserve the term "packet" for packets on-the-wire. A TCP app has no control over packets. I use the term "message" for application-protocol-level messages. I think this reduces confusion, especially for newcomers.
If you are trying to create a
networking library in C# that I can use in any application
were you aware of any existing open source libraries out there? networkComms.net is possibly a good start. If you can recreate the same problem with that i'd be very surprised. I've personally used it to maintain over 1000 concurrent connections each sending about 10 packets a second. Otherwise if you want to keep using your code perhaps looking at the source of networkComms.net can point out where you might be going wrong.
Didn't look closely at your code snippets, but I see you have allocation in there - have you checked what pressure you're putting on the garbage collector?
PS: (sending thread sleeps 1 ms) - keep in mind that Sleep() without timeBeginPeriod() isn't going to get your 1ms resolution - probably closer to 10-20ms depending on Windows version and hardware.
Don't really know about C# and this code is incomplete. If I get it right, then
readPacket.Read(reader);
will read whatever is available, and your receiver end for loop will be knocked over. Where are you checking the read amount of bytes ?
Anyway, a good way to check on what's happening at TCP level and lower is wireshark