Sending data over a socket using parallels - c#

I have an application that opens a socket and sends information over it. This functionality is encapsulated in a class.
I thought that it could be easy to work in parallel if I run this feature with Parallel.ForEach. In this way, each task would open/close a socket and send over it (to the same ip/port). This solution doesn't works.
Second way, I am implementing the socket operation in asynchronous way, and the behavior is that the server receives all data from first task and later the rest of data from other task. From the server side, there's no parallel behavior.
I am searching and reading information about this but I can't solve this problem.
Any ideas? Do you have a complete sample of using socket with Parallel library? Or any complete sample of using sockets in multithreading environment?
Complementary information:
I have a LINQ expression that returns a list of files. This list is processed as this:
Parallel.ForEach(AllFiles, new ParallelOptions { MaxDegreeOfParallelism = _maxDegreeOfParallelism }, currentFile =>
{
ProcessFiles(currentFile);
});
...
ProcessFiles sumarized:
void ProcessFile (string currentFile)
{
MyTcpClient client = null;
try
{
var AllLinesInFiles = // LINQ Expression that returns a list of strings
int port = 23000;
client = new MyTcpServer(ip, port);
foreach (string data in AllLinesInFiles)
{
if (data.Length > 0)
{
if (!client.IsOk)
{
client.Connect(false);
if (!client.IsOk)
break;
}
client.SendMessage(tmpLine2);
}
}
}
catch (Exception ex)
{
...
}
finally
{
if ((client != null) && (client.IsOk))
client.Close();
}
}
MyTcpClient, synchronous version is:
public class MyTcpClient : IDisposable
{
private static object objLock = new object();
public int Port = ...
public IPAddress IPAddress = ...
private string _Host;
private TcpClient _client = null;
private Stream _stream = null;
static MyTcpClient()
{
}
public MyTcpClient(string PassedIPAddress, Int32 PassedPort)
{
try
{
this.IPAddress = PassedIPAddress;
this.Port = PassedPort;
}
catch (Exception ex)
{
...
}
}
public TcpClient TcpClient
{
get { return _client; }
set { _client = value; }
}
public X509Certificate Certificate
{
get { return _certificate; }
set { _certificate = value; }
}
public bool IsOk
{
get
{
return ((_client != null) && (_client.Connected));
}
}
public void Connect(bool isSecure)
{
if (IsOk == false)
{
_client = new TcpClient(this.IPAddress.ToString(), this.Port);
_stream = null;
try
{
NetworkStream networkStream = _client.GetStream();
_stream = (NetworkStream)networkStream;
}
catch (AuthenticationException ex)
{
...
}
catch (Exception ex)
{
...
}
finally
{
}
}
}
public void SendMessage(string message)
{
if (_client != null && IsOk)
{
byte[] dgram = EncodingHelper.GetEncoding().GetBytes(message);
lock (MyTcpClient.objLock)
{
_stream.Write(dgram, 0, dgram.Length);
}
}
}
public void SendMessage(byte[] dgram)
{
if (_client != null && IsOk)
{
lock (MyTcpClient.objLock)
{
_stream.Write(dgram, 0, dgram.Length);
}
}
}
public void Close()
{
this.Dispose();
}
public void Dispose()
{
if (_stream != null)
{
_stream.Close();
}
if (_client != null)
{
_client.Close();
}
}
}
And for the Asynchronous version I have used the example here http://msdn.microsoft.com/en-us/library/bew39x2a.aspx
When I use asynchronous socket client, I update ProcessFile method but, the idea is open/close the socket in this method.

Related

How to Call an existing Class with Parameters?

I´ve got a Class wich is called Clients on my multi threaded server.
My Question is how do i send data to an specified Client from another Class?
Here is my Listen Function from ServerMain Class.
public static List<Client> clients;
public static List<Thread> threads;
private void Listen()
{
clients = new List<Client>();
threads = new List<Thread>();
int id = 0;
while (true)
{
listenerSocket.Listen(0);
Log.Status(" Waiting for a connection...");
var commands = new ServerCommands();
//commands.Wait();
Client c1 = new Client(id, listenerSocket.Accept());
clients.Add(c1);
Log.Status("New Client Connected!");
Thread t = new Thread(c1.Start);
c1.SetThread = t;
t.Start();
id++;
}
}
And My Client Class with just one send Example
public class Client : IDisposable
{
public int _id;
public string _guid;
public string Name;
public Socket clientSocket;
private Thread thread;
public Client(int id, Socket socket)
{
this._id = id;
this._guid = Guid.NewGuid().ToString();
this.clientSocket = socket;
}
public Thread SetThread
{
set
{
this.thread = value;
}
}
public int Id
{
get
{
return this._id;
}
}
public void Receive()
{
byte[] buffer;
int readBytes;
while (clientSocket != null && clientSocket.Connected)
{
try
{
buffer = new byte[clientSocket.SendBufferSize];
readBytes = clientSocket.Receive(buffer);
if (readBytes > 0)
{
Packet p = new Packet(buffer);
if (p.Type != PacketType.Disconnect)
{
new Task(() => Received(p)).Start();
}
else
{
CloseConnection();
}
}
}
catch (SocketException e)
{
Console.WriteLine(e);
CloseConnection();
}
}
}
////////// Example Send Fuction ////////////
private void Register(User user)
{
var res = Handler.RegisterDo(user);
clientSocket.Send(res.ToBytes());
}
}
I know i can send to all Connected Clients like this
foreach(Client item in ServerMain.clients) //Client clients
{
Console.WriteLine(item._id);
Console.WriteLine(item.Name);
Console.WriteLine(item._guid);
};
Am I missing something to identify?
The id Could do it (i think) but how do I call it then from outside?
In my understand of your code, you just wrapper the 'client' connection socket as the class client. you just need to call the 'this.clientSocket' field of the client class to send() or receive() data.

Multiple asyn calls in same method. The right way?

I need to fetch my public IP address from one of the IP address provider URLs. The catch is that these services are not reliable so I must have fallback to different URLs. To obtain maximum performance, I want to initiate WebRequest to all service providers at the same time and consider the result of the one who replies first.
This is the code i wrote. It works absolutely fine. But I have used EventWaitHandle. I just want to know if this is the right way to do it or is it possible to do the same without using WaitHandle (using async/await only)?
private static readonly string[] IpProviders = new string[] {
"http://ipinfo.io/ip", "http://canihazip.com/s",
"http://icanhazip.com", "http://bot.whatismyipaddress.com" };
private static string _publicIp = null;
public static string PublicIp
{
get
{
if (_publicIp == null)
{
_publicIp = FetchPublicIp();
}
return _publicIp;
}
}
private static string FetchPublicIp()
{
using (MyResetEvent manualEvent = new MyResetEvent())
{
foreach (string providerUrl in IpProviders)
{
FetchPublicIp(providerUrl).
ContinueWith(x => OnResult(x.Result, manualEvent));
}
int looped = 0;
do
{
manualEvent.WaitOne();
lock (manualEvent)
{
if (!string.IsNullOrWhiteSpace(manualEvent.Result))
{
return manualEvent.Result;
}
else
{
manualEvent.Reset();
}
looped = manualEvent.Count;
}
} while (looped < IpProviders.Length);
}
return null;
}
private static async Task<string> FetchPublicIp(string providerUrl)
{
string externalip;
try
{
externalip = await new WebClient().DownloadStringTaskAsync(providerUrl);
}
catch (WebException ex)
{
Debug.WriteLine(ex);
externalip = null;
}
if (!string.IsNullOrWhiteSpace(externalip))
{
System.Net.IPAddress ip;
if (System.Net.IPAddress.TryParse(externalip.Trim(), out ip))
{
return ip.ToString();
}
}
return null;
}
private static void OnResult(string s, MyResetEvent manualEvent)
{
try
{
lock (manualEvent)
{
if (manualEvent.Result == null)
{
manualEvent.Result = s;
}
manualEvent.Count++;
manualEvent.Set();
}
}
catch (ObjectDisposedException ex)
{
Debug.WriteLine(ex);
}
}
Here is the MyResetEvent class:
internal class MyResetEvent : EventWaitHandle
{
public MyResetEvent()
: base(false, EventResetMode.ManualReset)
{
}
public string Result { get; set; }
public int Count { get; set; }
}
You are overthinking this way too much. The TPL is there to help you, not fight you!
async Task<string> TakeFirstResponse(string[] urls)
{
return await await Task.WhenAny(
urls.Select(async url =>
await new WebClient().DownloadStringTaskAsync(url)));
}
Why the double await? The Task.WhenAny returns a Task<Task<T>> by design.
#Bas's answer is right on (you should probably accept it actually), but I wanted to offer an even more terse alternative that uses my Flurl library:
async Task<string> TakeFirstResponse(string[] urls)
{
return await await Task.WhenAny(urls.Select(url => url.GetStringAsync()));
}
Flurl.Http is backed by HttpClient, which is newer and generally preferable to WebClient, all other things being equal.

I get an Exception InvalidOperationException and I don't know why

This is a part of chat with multi users and I want to deserialize in loop so every message I am getting for each user I have a can publish (this is the server side)
public class ServerDLL
{
public TcpClient client { get; set; }
public TcpListener listner { get; set; }
public List<NetworkStream> clientStream = new List<NetworkStream>();
public List<TcpClient> clientsList = new List<TcpClient>();
string clientMsg;
BinaryFormatter formatter = new BinaryFormatter();
private object clientListLock = new object();
public void startConnection()
{
Thread listnerThread = new Thread(ListnerFunc);
listner.Start();
listnerThread.Start();
Thread waitForMeesage = new Thread(WaiterFunc);
waitForMeesage.Start();
}
public void ListnerFunc()
{
while (true)
{
client = listner.AcceptTcpClient();
clientStream.Add(client.GetStream());
if (client.Connected)
{
lock (clientListLock)
{
clientsList.Add(client);
}
}
}
}
public void WaiterFunc()
{
while (true)
{
lock (clientListLock)
{
foreach (NetworkStream stream in clientStream)
{
if (stream != null)
{
clientMsg = formatter.Deserialize(stream).ToString();
}
}
}
}
}
now the exception pops when I send the message from the client..
First, you really should put some sort of wait in your WaiterFunc(). Spinning the CPU like that is not a good idea.
That being said, you have a cross-thread shared resource in the clientStream collection. You can't modify a collection during enumeration (which your while loop does constantly), thus throwing the exception.
You need a lock around access to this list:
private object clientListLock = new object();
public void ListnerFunc()
{
while (true)
{
client = listner.AcceptTcpClient();
lock(clientListLock)
{
clientStream.Add(client.GetStream());
if (client.Connected)
{
clientsList.Add(client);
}
}
}
}
public void WaiterFunc()
{
while (true)
{
lock (clientListLock)
{
foreach (NetworkStream stream in clientStream)
{
clientMsg = formatter.Deserialize(stream).ToString();
}
}
}
}

How to create a wrapper for an async-await call?

From what I can tell, there is no built-in (or framework extension) support for ConnectAsync/AcceptAsync/SendAsync/ReceiveAsync, etc.. How would I write my own wrapper that would be supported by the async-await mechanism. For example, my current code which handles a ReceiveAsync both inline and on the callback (which is specified in the SocketAsyncEventArgs):
private void PostReceive(SocketAsyncEventArgs e)
{
e.SetBuffer(ReceiveBuffer.DataBuffer, ReceiveBuffer.Count, ReceiveBuffer.Remaining);
e.Completed += Receive_Completed;
// if ReceiveAsync returns false, then completion happened inline
if (m_RemoteSocket.ReceiveAsync(e) == false)
{
Receive_Completed(this, e);
}
}
.
private void Receive_Completed(object sender, SocketAsyncEventArgs e)
{
e.Completed -= Receive_Completed;
if (e.BytesTransferred == 0 || e.SocketError != SocketError.Success)
{
if (e.BytesTransferred > 0)
{
OnDataReceived(e);
}
Disconnect(e);
return;
}
OnDataReceived(e);
//
// we do not push the SocketAsyncEventArgs back onto the pool, instead
// we reuse it in the next receive call
//
PostReceive(e);
}
The trick is to use TaskCompletionSource to handle this scenario.
I blogged about this. For details, see Preparing Existing code For Await.
You can also write a custom awaitable, which I like better in this situation. This is a technique by Stephen Toub from Microsoft. You can read more about this technique here.
http://blogs.msdn.com/b/pfxteam/archive/2011/12/15/10248293.aspx
Here is the custom awaitable:
public sealed class SocketAwaitable : INotifyCompletion
{
private readonly static Action SENTINEL = () => { };
internal bool m_wasCompleted;
internal Action m_continuation;
internal SocketAsyncEventArgs m_eventArgs;
public SocketAwaitable(SocketAsyncEventArgs eventArgs)
{
if (eventArgs == null) throw new ArgumentNullException("eventArgs");
m_eventArgs = eventArgs;
eventArgs.Completed += delegate
{
var prev = m_continuation ?? Interlocked.CompareExchange(
ref m_continuation, SENTINEL, null);
if (prev != null) prev();
};
}
internal void Reset()
{
m_wasCompleted = false;
m_continuation = null;
}
public SocketAwaitable GetAwaiter() { return this; }
public bool IsCompleted { get { return m_wasCompleted; } }
public void OnCompleted(Action continuation)
{
if (m_continuation == SENTINEL ||
Interlocked.CompareExchange(
ref m_continuation, continuation, null) == SENTINEL)
{
Task.Run(continuation);
}
}
public void GetResult()
{
if (m_eventArgs.SocketError != SocketError.Success)
throw new SocketException((int)m_eventArgs.SocketError);
}
}
Some extension methods to add to the socket class and make it convenient:
public static class SocketExtensions
{
public static SocketAwaitable ReceiveAsync(this Socket socket,
SocketAwaitable awaitable)
{
awaitable.Reset();
if (!socket.ReceiveAsync(awaitable.m_eventArgs))
awaitable.m_wasCompleted = true;
return awaitable;
}
public static SocketAwaitable SendAsync(this Socket socket,
SocketAwaitable awaitable)
{
awaitable.Reset();
if (!socket.SendAsync(awaitable.m_eventArgs))
awaitable.m_wasCompleted = true;
return awaitable;
}
// ...
}
In use:
static async Task ReadAsync(Socket s)
{
// Reusable SocketAsyncEventArgs and awaitable wrapper
var args = new SocketAsyncEventArgs();
args.SetBuffer(new byte[0x1000], 0, 0x1000);
var awaitable = new SocketAwaitable(args);
// Do processing, continually receiving from the socket
while (true)
{
await s.ReceiveAsync(awaitable);
int bytesRead = args.BytesTransferred;
if (bytesRead <= 0) break;
Console.WriteLine(bytesRead);
}
}
For socket stuff there is a wrapper in .NET 4.5. If you are on .NET 4 I'd recommend to use the APM and not the event-based asynchronous pattern. It converts to Task's far more easily.

What's the best way to test SQL Server connection programmatically?

I need to develop a single routine that will be fired each 5 minutes to check if a list of SQL Servers (10 to 12) are up and running.
Is there a way to simply "ping" a SQL Server from C# one with minimal code and sql operational requirements?
I have had a difficulty with the EF when the connection the server is stopped or paused, and I raised the same question. So for completeness to the above answers here is the code.
/// <summary>
/// Test that the server is connected
/// </summary>
/// <param name="connectionString">The connection string</param>
/// <returns>true if the connection is opened</returns>
private static bool IsServerConnected(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
connection.Open();
return true;
}
catch (SqlException)
{
return false;
}
}
}
Execute SELECT 1 and check if ExecuteScalar returns 1.
See the following project on GitHub: https://github.com/ghuntley/csharp-mssql-connectivity-tester
try
{
Console.WriteLine("Connecting to: {0}", AppConfig.ConnectionString);
using (var connection = new SqlConnection(AppConfig.ConnectionString))
{
var query = "select 1";
Console.WriteLine("Executing: {0}", query);
var command = new SqlCommand(query, connection);
connection.Open();
Console.WriteLine("SQL Connection successful.");
command.ExecuteScalar();
Console.WriteLine("SQL Query execution successful.");
}
}
catch (Exception ex)
{
Console.WriteLine("Failure: {0}", ex.Message);
}
Wouldn't establishing a connection to the database do this for you? If the database isn't up you won't be able to establish a connection.
For what Joel Coehorn suggested, have you already tried the utility named tcping. I know this is something you are not doing programmatically. It is a standalone executable which allows you to ping every specified time interval. It is not in C# though. Also..I am not sure If this would work If the target machine has firewall..hmmm..
[I am kinda new to this site and mistakenly added this as a comment, now added this as an answer. Let me know If this can be done here as I have duplicate comments (as comment and as an answer) here. I can not delete comments here.]
Look for an open listener on port 1433 (the default port). If you get any response after creating a tcp connection there, the server's probably up.
You know, I first wrote this in 2010. Today, I'd just try to actually connect to the server.
public static class SqlConnectionExtension
{
#region Public Methods
public static bool ExIsOpen(
this SqlConnection connection, MessageString errorMsg = null)
{
if (connection == null) { return false; }
if (connection.State == ConnectionState.Open) { return true; }
try
{
connection.Open();
return true;
}
catch (Exception ex) { errorMsg?.Append(ex.ToString()); }
return false;
}
public static bool ExIsReady(
this SqlConnection connction, MessageString errorMsg = null)
{
if (connction.ExIsOpen(errorMsg) == false) { return false; }
try
{
using (var command = new SqlCommand("select 1", connction))
{ return ((int)command.ExecuteScalar()) == 1; }
}
catch (Exception ex) { errorMsg?.Append(ex.ToString()); }
return false;
}
#endregion Public Methods
}
public class MessageString : IDisposable
{
#region Protected Fields
protected StringBuilder _messageBuilder = new StringBuilder();
#endregion Protected Fields
#region Public Constructors
public MessageString()
{
}
public MessageString(int capacity)
{
_messageBuilder.Capacity = capacity;
}
public MessageString(string value)
{
_messageBuilder.Append(value);
}
#endregion Public Constructors
#region Public Properties
public int Length {
get { return _messageBuilder.Length; }
set { _messageBuilder.Length = value; }
}
public int MaxCapacity {
get { return _messageBuilder.MaxCapacity; }
}
#endregion Public Properties
#region Public Methods
public static implicit operator string(MessageString ms)
{
return ms.ToString();
}
public static MessageString operator +(MessageString ms1, MessageString ms2)
{
MessageString ms = new MessageString(ms1.Length + ms2.Length);
ms.Append(ms1.ToString());
ms.Append(ms2.ToString());
return ms;
}
public MessageString Append<T>(T value) where T : IConvertible
{
_messageBuilder.Append(value);
return this;
}
public MessageString Append(string value)
{
return Append<string>(value);
}
public MessageString Append(MessageString ms)
{
return Append(ms.ToString());
}
public MessageString AppendFormat(string format, params object[] args)
{
_messageBuilder.AppendFormat(CultureInfo.InvariantCulture, format, args);
return this;
}
public MessageString AppendLine()
{
_messageBuilder.AppendLine();
return this;
}
public MessageString AppendLine(string value)
{
_messageBuilder.AppendLine(value);
return this;
}
public MessageString AppendLine(MessageString ms)
{
_messageBuilder.AppendLine(ms.ToString());
return this;
}
public MessageString AppendLine<T>(T value) where T : IConvertible
{
Append<T>(value);
AppendLine();
return this;
}
public MessageString Clear()
{
_messageBuilder.Clear();
return this;
}
public void Dispose()
{
_messageBuilder.Clear();
_messageBuilder = null;
}
public int EnsureCapacity(int capacity)
{
return _messageBuilder.EnsureCapacity(capacity);
}
public bool Equals(MessageString ms)
{
return Equals(ms.ToString());
}
public bool Equals(StringBuilder sb)
{
return _messageBuilder.Equals(sb);
}
public bool Equals(string value)
{
return Equals(new StringBuilder(value));
}
public MessageString Insert<T>(int index, T value)
{
_messageBuilder.Insert(index, value);
return this;
}
public MessageString Remove(int startIndex, int length)
{
_messageBuilder.Remove(startIndex, length);
return this;
}
public MessageString Replace(char oldChar, char newChar)
{
_messageBuilder.Replace(oldChar, newChar);
return this;
}
public MessageString Replace(string oldValue, string newValue)
{
_messageBuilder.Replace(oldValue, newValue);
return this;
}
public MessageString Replace(char oldChar, char newChar, int startIndex, int count)
{
_messageBuilder.Replace(oldChar, newChar, startIndex, count);
return this;
}
public MessageString Replace(string oldValue, string newValue, int startIndex, int count)
{
_messageBuilder.Replace(oldValue, newValue, startIndex, count);
return this;
}
public override string ToString()
{
return _messageBuilder.ToString();
}
public string ToString(int startIndex, int length)
{
return _messageBuilder.ToString(startIndex, length);
}
#endregion Public Methods
}
Similar to the answer offered by Andrew, but I use:
Select GetDate() as CurrentDate
This allows me to see if the SQL Server and the client have any time zone difference issues, in the same action.
Here is my version based on the #peterincumbria answer:
using var scope = _serviceProvider.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
return await dbContext.Database.CanConnectAsync(cToken);
I'm using Observable for polling health checking by interval and handling return value of the function.
try-catch is not needed here because:
I normally do this by open a connection but I had some cases where a simple test via Open caused a AccessViolationException
using (SqlConnection db = new SqlConnection(conn))
{
db.Open(); // -- Access Violation caused by invalid Server in Connection String
}
So I did a TCP check before the open like recommanded by Joel Coehoorn. C# Code for this may be:
string targetAddress = "";
try
{
targetAddress = GetServerFromConnectionString();
IPAddress ipAddress = Dns.GetHostEntry(targetAddress).AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 1433);
using (TcpClient tcpClient = new TcpClient())
{
tcpClient.Connect(ipEndPoint);
}
}
catch (Exception ex)
{
LogError($"TestViaTcp to server {targetAddress} failed '{ex.GetType().Name}': {ex.Message}");
}

Categories