I am trying to send message through sockets in 5 seconds intervals.
In order to test it, I have basic server socket (which will listen to incoming calls) implementation:
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// Dns.GetHostName returns the name of the
// host running the application.
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// Create a TCP/IP socket.
Socket listener = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and
// listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
// Start listening for connections.
while (true)
{
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
data = null;
// An incoming connection needs to be processed.
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
//if (data.IndexOf("<EOF>") > -1)
//{
break;
//}
}
// Show the data on the console.
Console.WriteLine("Text received : {0}", data);
// Echo the data back to the client.
//byte[] msg = Encoding.ASCII.GetBytes(data);
// handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("\nPress ENTER to continue...");
Console.Read();
}
And the socket, which sends messages I implemented in many ways, none of them worked, I finally was advised to connect and close sockets every time I use them (not every 5 second it will be used - some conditions need to be satisfied in order to make a connection). Anyway, I end up with something like this:
private static void CheckDbAndSendMessage()
{
var entities = // custom ORM read from DB ;
// no new records
if (entities.Count == 0)
return;
HashSet<string> messages = new HashSet<string>();
foreach (var entity in entities)
{
messages.Add(entity.Description + " --- " + entity.Operator);
entity.Status = 10;
}
try
{
SendMessage(messages);
}
catch(Exception ex)
{
//implemented error handling
}
}
/// <summary>
/// Sends messages over specified channel.
/// </summary>
/// <param name="messages"></param>
/// <exception cref="Exception">Thrown when socket connections fails.</exception>
private static void SendMessage(HashSet<string> messages)
{
_sender.Connect(_remoteEP);
foreach (var message in messages)
{
_sender.Send(System.Text.Encoding.ASCII.GetBytes(message));
}
// When app stops, it will be released.
_sender.Shutdown(SocketShutdown.Both);
_sender.Close();
}
When I run it like this, _sender.Close()
will destroy socket, as stated here. So, first connection will be made, but then I will get an ObjectDisposedexception
on another call. Ok, so I removed that line, and used only _sender.Shutdown(SocketShutdown.Both)
and got exception on second connection saying:
After disconnecting the socket, you can reconnect only asynchronously from a different EndPoint.
So, what is the right way to solve it? I spent hours and got nowhere...