How to check net TCP wcf service is connected - c#

Command to check whether net TCP wcf Windows service is running?
I was trying with proxy to the wcf and getting timeout exception while calling a contract. So unable to confirm whether service is running or not

The following ways could achieve you want.
1. Use the Netstat windows command to check whether the port is listening over TCP.
For example, Check whether port 1900 is listening over TCP.
https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/netstat
2. OnlineAnnouncement/offlineAnnouncement notification by using UDP discovery endpoint.
When server is online, it could send online announcement by using UDP discovery endpoint.
I have made an example, wish it is useful to you.
Server.
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("net.tcp://localhost:1900");
NetTcpBinding binding = new NetTcpBinding();
using (ServiceHost sh=new ServiceHost(typeof(MyService),uri))
{
sh.AddServiceEndpoint(typeof(IService), binding, "");
ServiceMetadataBehavior smb;
smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior()
{
};
sh.Description.Behaviors.Add(smb);
}
ServiceDiscoveryBehavior sdb = new ServiceDiscoveryBehavior();
sdb.AnnouncementEndpoints.Add(new UdpAnnouncementEndpoint());
sh.Description.Behaviors.Add(sdb);
sh.AddServiceEndpoint(new UdpDiscoveryEndpoint());
Binding binding1 = MetadataExchangeBindings.CreateMexTcpBinding();
sh.AddServiceEndpoint(typeof(IMetadataExchange), binding1, "mex");
sh.Open();
Console.WriteLine("Service is ready...");
Console.ReadLine();
sh.Close();
}
}
}
[ServiceContract(Namespace ="mydomain")]
public interface IService
{
[OperationContract(Name ="AddInt")]
int Add(int x, int y);
}
public class MyService : IService
{
public int Add(int x, int y)
{
return x + y;
}
}
Client.
static void Main(string[] args)
{
Console.Title = "Start client first";
AnnouncementService annsvc = new AnnouncementService();
annsvc.OnlineAnnouncementReceived += OnlineRec;
annsvc.OfflineAnnouncementReceived += OfflineRec;
using (ServiceHost host = new ServiceHost(annsvc))
{
host.AddServiceEndpoint(new UdpAnnouncementEndpoint());
host.Open();
Console.Read();
}
}
private static void OfflineRec(object sender, AnnouncementEventArgs e)
{
Console.WriteLine($"\nService is offline, service address:{e.EndpointDiscoveryMetadata.Address.Uri}");
}
private static void OnlineRec(object sender, AnnouncementEventArgs e)
{
Console.WriteLine($"\nService is online, service address:{e.EndpointDiscoveryMetadata.Address.Uri}");
}
Result.
Official document.
https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/dd483353(v=vs.100)
Actually, we could get the service status by the service metadata address. for the above example, we could detect the service status with inputting net.tcp://localhost:1900/mex in Adding service reference dialog.
3. Use notepad to log the status. Please refer to my example.
Uri uri = new Uri("http://localhost:1000");
BasicHttpBinding binding = new BasicHttpBinding();
ServiceHost sh = null;
protected override void OnStart(string[] args)
{
sh = new ServiceHost(typeof(MyService), uri);
ServiceMetadataBehavior smb;
smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb==null)
{
smb = new ServiceMetadataBehavior
{
HttpGetEnabled = true
};
sh.Description.Behaviors.Add(smb);
}
sh.Open();
WriteLog($"Service is ready at {DateTime.Now.ToString("hh-mm-ss")}");
}
protected override void OnStop()
{
if (sh!=null&&sh.State==CommunicationState.Opened)
{
sh.Close();
WriteLog($"Service is closed at {DateTime.Now.ToString("hh-mm-ss")}");
}
}
public static void WriteLog(string text)
{
using (StreamWriter sw=File.AppendText(#"D:\log.txt"))
{
sw.WriteLine(text);
sw.Flush();
}
}
Feel free to let me know if there is anything I can help with.

Related

Losing messages with MQTT with C# uPLibrary.Networking.M2Mqtt

I have a problem that I lose messages with MQTT although I send them with "QOS_LEVEL_EXACTLY_ONCE".
The loss is only when the receiver is not running and then starts later.
These messages are then not collected.
Version of M2Mqtt is 4.3.0
If both clients, i.e. receiver and transmitter, are running, no messages are lost.
Only if the receiver is not running, the messages are prefetched during this time and do not arrive at the receiver.
I can't find any setting on the server(broker) for how long messages should be saved
sender
public class Programm
{
static MqttClient mqttClient;
static async Task Main(string[] args)
{
var locahlost = true;
var clientName = "Sender 1";
Console.WriteLine($"{clientName} Startet");
var servr = locahlost ? "localhost" : "test.mosquitto.org";
mqttClient = new MqttClient(servr);
mqttClient.Connect(clientName);
Task.Run(() =>
{
if (mqttClient != null && mqttClient.IsConnected)
{
for (int i = 0; i < 100; i++)
{
var Message = $"{clientName} ->Test {i}";
mqttClient.Publish("Application1/NEW_Message", Encoding.UTF8.GetBytes($"{Message}"), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, true);
Console.WriteLine(Message);
Thread.Sleep(i * 1000);
}
}
});
Console.WriteLine($"{clientName} End");
}
}
Server
public class Programm
{
static async Task Main(string[] args)
{
Console.WriteLine("Server");
MqttServerOptionsBuilder options = new MqttServerOptionsBuilder()
// set endpoint to localhost
.WithDefaultEndpoint()
// port used will be 707
.WithDefaultEndpointPort(1883);
// handler for new connections
// creates a new mqtt server
IMqttServer mqttServer = new MqttFactory().CreateMqttServer();
// start the server with options
mqttServer.StartAsync(options.Build()).GetAwaiter().GetResult();
// keep application running until user press a key
Console.ReadLine();
}
}
Receiver
public class Programm
{
static MqttClient mqttClient;
static async Task Main(string[] args)
{
var clientName = "Emfänger 1";
var locahlost = true;
Console.WriteLine($"Start of {clientName}");
Task.Run(() =>
{
var servr = locahlost ? "localhost" : "test.mosquitto.org";
mqttClient = new MqttClient(servr);
mqttClient.MqttMsgPublishReceived += MqttClient_MqttMsgPublishReceived;
mqttClient.Subscribe(new string[] { "Application1/NEW_Message" }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
mqttClient.Connect(clientName);
});
// client.UseConnecedHandler(e=> {Console.WriteLine("Verbunden") });
Console.ReadLine();
Console.WriteLine($"end of {clientName}");
Console.ReadLine();
}
private static void MqttClient_MqttMsgPublishReceived(object sender, uPLibrary.Networking.M2Mqtt.Messages.MqttMsgPublishEventArgs e)
{
var message = Encoding.UTF8.GetString(e.Message);
Console.WriteLine(message);
}
}
The default value for the Clean session flag when connecting to the broker with M2MQTT is true.
This means that the broker will discard any queued messages.
https://m2mqtt.wordpress.com/using-mqttclient/
You need to set this to false to ensure the client receives the queued messages.
mqttClient.Connect(clientName, false);
I found the error, saving was missing.
Here is the new code from the server
static async Task Main(string[] args)
{
Console.WriteLine("Server");
MqttServerOptionsBuilder options = new MqttServerOptionsBuilder()
.WithDefaultEndpoint()
.WithDefaultEndpointPort(1883)
.WithConnectionValidator(OnNewConnection)
.WithApplicationMessageInterceptor(OnNewMessage)
.WithClientMessageQueueInterceptor(OnOut)
.WithDefaultCommunicationTimeout(TimeSpan.FromMinutes(5))
.WithMaxPendingMessagesPerClient(10)
.WithPersistentSessions()
.WithStorage(storage);
// creates a new mqtt server
IMqttServer mqttServer = new MqttFactory().CreateMqttServer();
// start the server with options
mqttServer.StartAsync(options.Build()).GetAwaiter().GetResult();
// keep application running until user press a key
Console.ReadLine();
}

System Error when getting a value from a database using WCF (IIS 7.5)

I have an Android Application which connects to a database through WCF service hosted in IIS 7.5. I based it from here: Walkthrough - Working with WCF. I'm only using my localhost and I haven't configured the remote access. The problem is every time I click the button (which upon clicking will pass the value of the inputted number then process the sql statement then it will return the result which will appear in the textview beside the button), a dialog box appears saying System Error. I am running this app in Android emulator which should be fine since I only connect through a localhost.
Here are my codes:
MainActivity.cs
btnCheck = FindViewById<ImageButton>(Resource.Id.imageButton1);
btnCheck.Click += GetEmployeeDataOnClick;
private void InitializeEmployeeServiceClient()
{
BasicHttpBinding binding = CreateBasicHttp();
_client = new EmployeeServiceClient(binding, EndPoint);
_client.DisplayEmployeeCompleted += ClientOnDisplayEmployeeCompleted;
}
private static BasicHttpBinding CreateBasicHttp()
{
BasicHttpBinding binding = new BasicHttpBinding
{
Name = "basicHttpBinding",
MaxBufferSize = 2147483647,
MaxReceivedMessageSize = 2147483647
};
TimeSpan timeout = new TimeSpan(0, 0, 30);
binding.SendTimeout = timeout;
binding.OpenTimeout = timeout;
binding.ReceiveTimeout = timeout;
return binding;
}
private void GetEmployeeDataOnClick(object sender, EventArgs eventArgs)
{
empNumber = FindViewById<EditText>(Resource.Id.editText1);
EmployeeNo employee = new EmployeeNo();
employee.EmpNo = empNumber.Text;
_client.DisplayEmployeeAsync(employee);
}
private void ClientOnDisplayEmployeeCompleted(object sender, DisplayEmployeeCompletedEventArgs displayEmployeeCompletedEventArgs)
{
empName = FindViewById<TextView>(Resource.Id.textView9);
string msg = null;
if (displayEmployeeCompletedEventArgs.Error != null)
{
msg = displayEmployeeCompletedEventArgs.Error.Message;
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.SetMessage(msg);
alert.SetPositiveButton("OK", (senderAlert, args) => {});
RunOnUiThread(() => {
alert.Show();});
}
else if (displayEmployeeCompletedEventArgs.Cancelled)
{
msg = "Request was cancelled.";
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.SetMessage(msg);
alert.SetPositiveButton("OK", (senderAlert, args) => {});
RunOnUiThread(() => {
alert.Show();
});
}
else
{
msg = displayEmployeeCompletedEventArgs.Result;
RunOnUiThread(() => empName.Text = msg);
}
}
IService.cs (WCF)
[ServiceContract]
public interface IEmployeeService
{
[OperationContract]
string DisplayEmployee(EmployeeNo empNo);
}
[DataContract]
public class EmployeeNo
{
string empNumber = string.Empty;
[DataMember]
public string EmpNo
{
get { return empNumber; }
set { empNumber = value; }
}
}
Service.svc.cs (WCF)
public string DisplayEmployee(EmployeeNo empNo)
{
// sql connection, statement (inputted empNo which corresponds to an EmpName)
return EmpName;
}
Am I doing this correctly? What is the problem here?
I am a total newbie here btw.
Change the IP addess to connect to your IIS to the actual IP address of your server (the host of your emulator in this case).
You can also use the hostname like "http://user-pc:8080/DataService".

EWS streaming notifications not received

Afternoon all,
I have a windows service which subscribes to an Office365 email account and awaits new emails, when they arrive it processes their attachments, and all is well with the world.
But... for some reason, the applications stops receiving notifications after an undetermined amount of time.
I have handled the 'OnDisconnect' event and reestablish a connection as shown in the below code, but that doesnt seem to be fixing this issue. The windows service continues to run fine, and if I restart the service everything is good again, until is failed again.
This is the my class for running exchange:
public class ExchangeConnection
{
static readonly ExchangeService Service = Exchange.Service.ConnectToService(UserDataFromConsole.GetUserData(), new TraceListener());
public event EmailReceivedHandler OnEmailReceived;
public ExchangeConnection()
{
}
public void Open()
{
SetStreamingNotifications(Service);
var signal = new AutoResetEvent(false);
signal.WaitOne();
}
private void SetStreamingNotifications(ExchangeService service)
{
var streamingsubscription = service.SubscribeToStreamingNotifications(new FolderId[] { WellKnownFolderName.Inbox }, EventType.NewMail);
var connection = new StreamingSubscriptionConnection(service, 30);
connection.AddSubscription(streamingsubscription);
connection.OnNotificationEvent += OnEvent;
connection.OnSubscriptionError += OnError;
connection.OnDisconnect += OnDisconnect;
connection.Open();
}
public void MoveEmail(ItemId id, String folderName = "Archived Emails")
{
var rootFolder = Folder.Bind(Service, WellKnownFolderName.Inbox);
var archivedFolder = rootFolder.FindFolders(new FolderView(100)).FirstOrDefault(x => x.DisplayName == folderName);
if (archivedFolder == null)
{
archivedFolder = new Folder(Service) { DisplayName = folderName };
archivedFolder.Save(WellKnownFolderName.Inbox);
}
Service.MoveItems(new List<ItemId> {id}, archivedFolder.Id);
}
#region events
private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
//The connection is disconnected every 30minutes, and we are unable to override this,
//so when we get disconnected we just need to reconnect again.
var connection = (StreamingSubscriptionConnection)sender;
connection.Open();
}
private void OnEvent(object sender, NotificationEventArgs args)
{
var subscription = args.Subscription;
// Loop through all item-related events.
foreach (var notification in args.Events)
{
switch (notification.EventType)
{
case EventType.NewMail:
if (notification is ItemEvent)
{
var email = Item.Bind(Service, new ItemId(((ItemEvent) notification).ItemId.UniqueId));
OnEmailReceived(new EmailReceivedArgs((EmailMessage)email));
}
break;
}
}
}
private void OnError(object sender, SubscriptionErrorEventArgs args)
{
var e = args.Exception;
Logger.LogException(e,LogEventType.Error);
}
#endregion events
}
Any help would be great, thanks.
EDIT:
After improving the error logging I have found this exception occuring:
Exception: The specified subscription was not found.
Any ideas what is causing this?
With Office365 you need to make sure you deal with affinity see http://msdn.microsoft.com/en-us/library/office/dn458789(v=exchg.150).aspx . Adding those headers will ensure your requests will always routed to the correct servers.
Cheers
Glen

TCP error in case wrong IP Address specified in WCF although the IP Address is correct

I have application that host WCF service.
I am opening the connection via BackgroundWorker
private bool isConnected;
private BackgroundWorker asyncWorker = new BackgroundWorker();
InitializeComponent();
asyncWorker.WorkerReportsProgress = true;
asyncWorker.WorkerSupportsCancellation = true;
asyncWorker.ProgressChanged += new ProgressChangedEventHandler
(bwAsync_ProgressChanged);
asyncWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler
(bwAsync_RunWorkerCompleted);
asyncWorker.DoWork += new DoWorkEventHandler(bwAsync_DoWork);
btnConnect.BackColor = Color.ForestGreen;
This is my Connect button click event:
private void btnConnect_Click(object sender, EventArgs e)
{
btnConnect.Enabled = false;
Interface.interfaceNumber = interfaceNumber;
asyncWorker.RunWorkerAsync();
}
And DoWork:
private void bwAsync_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bwAsync = sender as BackgroundWorker;
try
{
if (!isConnected)
{
// Returns a list of ipaddress configuration
IPHostEntry ips = Dns.GetHostEntry(Dns.GetHostName());
// Get machine ipaddress
IPAddress _ipAddress = IPAddress.Parse(tbServerIp.Text);
// Create the url that is needed to specify where the service should be started
urlService = "net.tcp://" + _ipAddress.ToString() + ":8000/MyService";
// Instruct the ServiceHost that the type that is used is a ServiceLibrary.service1
//host = new ServiceHost(typeof(ServiceLibrary.service1));
ServiceLibrary.service1 serviceInstance = new ServiceLibrary.service1();
serviceInstance.CapturingEvent += yourServiceInstance_StartCapturingEvent;
serviceInstance.OnProcessExitedEvent += serviceInstance_OnProcessExitedEvent;
host = new ServiceHost(serviceInstance);
host.Opening += new EventHandler(host_Opening);
host.Opened += new EventHandler(host_Opened);
host.Closing += new EventHandler(host_Closing);
host.Closed += new EventHandler(host_Closed);
// The binding is where we can choose what transport layer we want to use. HTTP, TCP ect.
NetTcpBinding tcpBinding = new NetTcpBinding();
tcpBinding.TransactionFlow = false;
tcpBinding.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
tcpBinding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
tcpBinding.Security.Mode = SecurityMode.None; // <- Very crucial
// Add a endpoint
host.AddServiceEndpoint(typeof(ServiceLibrary.IService1), tcpBinding, urlService);
// A channel to describe the service. Used with the proxy scvutil.exe tool
ServiceMetadataBehavior metadataBehavior;
metadataBehavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metadataBehavior == null)
{
// Create the proxy object that is generated via the svcutil.exe tool
metadataBehavior = new ServiceMetadataBehavior();
metadataBehavior.HttpGetUrl = new Uri("http://" + _ipAddress.ToString() + ":8001/MyService");
metadataBehavior.HttpGetEnabled = true;
metadataBehavior.ToString();
host.Description.Behaviors.Add(metadataBehavior);
urlMeta = metadataBehavior.HttpGetUrl.ToString();
}
host.Open();
isConnected = true;
}
else
{
if (asyncWorker.IsBusy)
{
//bnAsync.Enabled = false;
this.Invoke((MethodInvoker)delegate { lblStatus.Text = "Cancelling..."; });
// Notify the worker thread that a cancel has been requested.
// The cancel will not actually happen until the thread in the
// DoWork checks the bwAsync.CancellationPending flag, for this
// reason we set the label to "Cancelling...", because we haven't
// actually cancelled yet.
asyncWorker.CancelAsync();
}
host.Close();
isConnected = false;
}
}
catch (Exception ex)
{
isConnected = false;
MessageBox.Show(ex.Message);
return;
}
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Lock\Release buttons
}
My application connect successfully and all works fine but in case i am specified wrong IP Address i get TCP error that requested Ip Address is not valid which is OK but in case i fix this wrong IP Address to the correct Ip Address i still get the same error unless my application is restarted.
Maybe my thread is still running and this is why i cannot connect ?
First off don't use IP addresses unless your just doing localhost dev, it's always a bad idea, use DNS names or hosts file name entries. Secondly, I assume that your host variable is a class member variable (code you didn't include above). After you open the host, it's bindings are going to remain active in server memory until you restart the application which is standard practice.
The other issue with that code is that in the else block of bwAsync_DoWork you close the host after the form button is clicked but you are not re-binding/re-opening the host with the updated form data. Consider doing the following to fix this.
Move the code that does the actual host binding out of bwAsync_DoWork into its own method.
Call this method at the very end of bwAsync_DoWork to ensure the new binding is turned on.
code:
private void bwAsync_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bwAsync = sender as BackgroundWorker;
if (asyncWorker.IsBusy)
{
this.Invoke((MethodInvoker)delegate { lblStatus.Text = "Cancelling..."; });
asyncWorker.CancelAsync();
}
else
{
if(isConnected)
{
host.Close();
isConnected = false;
}
BindHost();
}
}
private void BindHost()
{
...
isConnected = true;
}

Publishing a Wcf service using BasicHttpBinding for remote clients

I've created 3 projects:
WcfServer -- The default WCF Service Library project, unchanged.
WcfServerConsole -- Console Application:
static void Main(string[] args)
{
try
{
var baseAddress = "http://localhost:9000/WcfTest/";
Type contract = typeof(IService1);
Type implementation = typeof(Service1);
var address = baseAddress + implementation.Name;
var binding = new BasicHttpBinding();
var service = new ServiceHost(implementation, new Uri[] { new Uri(address) });
service.AddServiceEndpoint(contract, binding, address);
AddBehaviors(service);
service.Open();
Console.WriteLine("Server ready. Press ENTER to terminate.");
Console.ReadLine();
service.Close();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
private static void AddBehaviors(ServiceHost service)
{
var smb = service.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
{
smb = new ServiceMetadataBehavior();
service.Description.Behaviors.Add(smb);
}
smb.HttpGetEnabled = true;
var sdb = service.Description.Behaviors.Find<ServiceDebugBehavior>();
if (sdb == null)
{
sdb = new ServiceDebugBehavior();
service.Description.Behaviors.Add(sdb);
}
sdb.IncludeExceptionDetailInFaults = true;
}
WcfClientConsole -- Console Application:
static void Main(string[] args)
{
Thread.Sleep(1000);
var proxy = new Service1Client();
proxy.Open();
var response = proxy.GetData(42);
proxy.Close();
Console.WriteLine(response);
Console.ReadLine();
}
Everything works fine locally. When I run the server, I can see http://localhost:9000/WcfTest/Service1 in my browser, and communication works as expected (run server, run client, see "You entered: 42" in WcfClientConsole). Now I want to do this remotely. I change baseAddress to "http://0.0.0.0:9000/WcfTest/" and run the server on another machine (192.168.150.140). On that machine, in a browser I can open http://localhost:9000/WcfTest/Service1 and http://127.0.0.1:9000/WcfTest/Service1 and http://192.168.150.140:9000/WcfTest/Service1 no problems. On my machine, my browser can't connect to http://192.168.150.140:9000/WcfTest/Service1, nor can Add Service Reference, and changing proxy to new Service1Client("BasicHttpBinding_IService1", "http://192.168.150.140:9000/WcfTest/Service1"); also fails ("There was no endpoint listening at http://192.168.150.140:9000/WcfTest/Service1 that could accept the message.").
Am I going about this the wrong way?
Check your firewall. That's usually the top cause of this kind of issue.

Categories