I'm creating a chat client that has UDP for voice chat, but when I send the audio (in bytes) to the other clients, the client plays the audio everything is clear but I hear a random clicking sound in the back ground. I thought it might be because it's UDP and not checking if the data is correct, but no. Even when I send through TCP I can still hear the clicking sound in the background.
CODE to recreate:
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace QuestionStack
{
public partial class Form1 : Form
{
UdpClient UDPc;
private NAudio.Wave.WaveIn sourceStream;
IPEndPoint ep;//where the client will send the udp data from recording
public Form1()
{
InitializeComponent();
}
/// <summary>
/// client clicks when he wants to start connection with other client
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void StartAudioButton_Click(object sender, EventArgs e)
{
UDPc = new UdpClient(Int32.Parse(MyPortTextBox.Text));
ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), Int32.Parse(OtherUserTextBoxPort.Text)); // endpoint where other clienr is listening
UDPc.Connect(ep);
UDPc.BeginReceive(new AsyncCallback(ReceiveUdpMessage), null);
Thread.Sleep(100);
StartAudioRecording();
}
/// <summary>
/// where the client takes the audio in bytes, he got from otehr client to convert and play the audio
/// </summary>
/// <param name="ar"></param>
private void ReceiveUdpMessage(IAsyncResult ar)
{
try
{
byte[] bytesRead = UDPc.EndReceive(ar, ref ep);
BufferedWaveProvider provider = new BufferedWaveProvider(new WaveFormat(44100, 16, 2));
provider.DiscardOnBufferOverflow = true;
provider.AddSamples(bytesRead, 0, bytesRead.Length);
DirectSoundOut _waveOut = new DirectSoundOut();
_waveOut.Init(provider);
_waveOut.Play();
UDPc.BeginReceive(new AsyncCallback(ReceiveUdpMessage), null);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
/// <summary>
/// starts recording and sents to other client if check box to only listen is not on
/// </summary>
public void StartAudioRecording()
{
if (!checkBoxOnlyListen.Checked)
{
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = 0;
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, NAudio.Wave.WaveIn.GetCapabilities(0).Channels);
sourceStream.DataAvailable += new EventHandler<NAudio.Wave.WaveInEventArgs>(sourceStream_DataAvailable);
sourceStream.StartRecording();
}
}
/// <summary>
/// if got recording, sends it to other client
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)
{
if (sourceStream == null) return;
try
{
UDPc.Send(e.Buffer, e.BytesRecorded);//sending data UPD
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
FormsPicture
So if the data is ok, the way I'm translating and playing it is causing the problems.
I checked, it doesn't matter if the Wave out object is created outside of the method.
I tried a million different ways to fix it. I have no idea how to. If anyone knows a better way to translate or fix it, It would make my week.
Thanks in advance.
You should create a single output device and a single BufferedWaveProvider, and start playing before you receive any audio. Then in the receive function, the only thing you need to do is add received audio to the BufferedWaveProvider. However, you will still get clicks if the audio is not being received fast enough over the network which will mean you have dropouts in the received audio.
Related
In the following project, messages are sent to the server only through the client.
I need every time the client sends a message to the server, the server program responds to the client using the Console.ReadLine () function, without creating a new connection and using the same connection that was already created;
For example, when the client says hello, wait or the server will say answer!
Of course, after searching, I realized that I should probably use connection.SendObject(), but I could not use it properly :(
(Of course, if this answer is correct!)
Thank you for your help
server :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetworkCommsDotNet;
using NetworkCommsDotNet.Connections;
using System.Reflection;
namespace server
{
class Program
{
static void Main(string[] args)
{
NetworkComms.AppendGlobalIncomingPacketHandler<string>("Message", PrintIncomingMessage);
Connection.StartListening(ConnectionType.TCP, new System.Net.IPEndPoint(System.Net.IPAddress.Any, 1000));
Console.WriteLine("Server listening on:\n");
foreach (System.Net.IPEndPoint localEndPoint in Connection.ExistingLocalListenEndPoints(ConnectionType.TCP))
Console.WriteLine("{0}:{1}", localEndPoint.Address, localEndPoint.Port);
Console.WriteLine("\nPress any key to close server.");
Console.ReadKey(true);
NetworkComms.Shutdown();
}
/// <summary>
/// Writes the provided message to the console window
/// </summary>
/// <param name="header">The packet header associated with the incoming message</param>
/// <param name="connection">The connection used by the incoming message</param>
/// <param name="message">The message to be printed to the console</param>
private static void PrintIncomingMessage(PacketHeader header, Connection connection, string message)
{
Console.WriteLine(message);
}
}
}
client :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetworkCommsDotNet;
namespace client
{
class Program
{
static void Main(string[] args)
{
int loopCounter = 1;
while (true)
{
string messageToSend = Console.ReadLine();
NetworkComms.SendObject("Message", "192.168.1.1", 1000, messageToSend);
if (Console.ReadKey(true).Key == ConsoleKey.Q)
break;
else loopCounter++;
}
NetworkComms.Shutdown();
}
}
}
there are several ways to implement Real-time Application in .Net Such as:
1.SignalR (It uses WebSockets whenever possible)
2.Grpc (it uses http/2 and Streaming )
3.Also You can build An Application Using MeesageBrokers that implement pub-sub (publish-subscribe ) pattern like (Redis or kafka or ..)
I just started learning how to send and receive data from my hardware through the C# GUI.
Can anyone please write a detail how to read data from the serial port?
SerialPort (RS-232 Serial COM Port) in C# .NET
This article explains how to use the SerialPort class in .NET to read and write data, determine what serial ports are available on your machine, and how to send files. It even covers the pin assignments on the port itself.
Example Code:
using System;
using System.IO.Ports;
using System.Windows.Forms;
namespace SerialPortExample
{
class SerialPortProgram
{
// Create the serial port with basic settings
private SerialPort port = new SerialPort("COM1",
9600, Parity.None, 8, StopBits.One);
[STAThread]
static void Main(string[] args)
{
// Instatiate this class
new SerialPortProgram();
}
private SerialPortProgram()
{
Console.WriteLine("Incoming Data:");
// Attach a method to be called when there
// is data waiting in the port's buffer
port.DataReceived += new
SerialDataReceivedEventHandler(port_DataReceived);
// Begin communications
port.Open();
// Enter an application loop to keep this thread alive
Application.Run();
}
private void port_DataReceived(object sender,
SerialDataReceivedEventArgs e)
{
// Show all the incoming data in the port's buffer
Console.WriteLine(port.ReadExisting());
}
}
}
I spent a lot of time to use SerialPort class and has concluded to use SerialPort.BaseStream class instead. You can see source code: SerialPort-source and
SerialPort.BaseStream-source for deep understanding.
I created and use code that shown below.
The core function
public int Recv(byte[] buffer, int maxLen)
has name and works like "well known" socket's recv().
It means that
in one hand it has timeout for no any data and throws TimeoutException.
In other hand, when any data has received,
it receives data either until maxLen bytes
or short timeout (theoretical 6 ms) in UART data flow
.
public class Uart : SerialPort
{
private int _receiveTimeout;
public int ReceiveTimeout { get => _receiveTimeout; set => _receiveTimeout = value; }
static private string ComPortName = "";
/// <summary>
/// It builds PortName using ComPortNum parameter and opens SerialPort.
/// </summary>
/// <param name="ComPortNum"></param>
public Uart(int ComPortNum) : base()
{
base.BaudRate = 115200; // default value
_receiveTimeout = 2000;
ComPortName = "COM" + ComPortNum;
try
{
base.PortName = ComPortName;
base.Open();
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("Error: Port {0} is in use", ComPortName);
}
catch (Exception ex)
{
Console.WriteLine("Uart exception: " + ex);
}
} //Uart()
/// <summary>
/// Private property returning positive only Environment.TickCount
/// </summary>
private int _tickCount { get => Environment.TickCount & Int32.MaxValue; }
/// <summary>
/// It uses SerialPort.BaseStream rather SerialPort functionality .
/// It Receives up to maxLen number bytes of data,
/// Or throws TimeoutException if no any data arrived during ReceiveTimeout.
/// It works likes socket-recv routine (explanation in body).
/// Returns:
/// totalReceived - bytes,
/// TimeoutException,
/// -1 in non-ComPortNum Exception
/// </summary>
/// <param name="buffer"></param>
/// <param name="maxLen"></param>
/// <returns></returns>
public int Recv(byte[] buffer, int maxLen)
{
/// The routine works in "pseudo-blocking" mode. It cycles up to first
/// data received using BaseStream.ReadTimeout = TimeOutSpan (2 ms).
/// If no any message received during ReceiveTimeout property,
/// the routine throws TimeoutException
/// In other hand, if any data has received, first no-data cycle
/// causes to exit from routine.
int TimeOutSpan = 2;
// counts delay in TimeOutSpan-s after end of data to break receive
int EndOfDataCnt;
// pseudo-blocking timeout counter
int TimeOutCnt = _tickCount + _receiveTimeout;
//number of currently received data bytes
int justReceived = 0;
//number of total received data bytes
int totalReceived = 0;
BaseStream.ReadTimeout = TimeOutSpan;
//causes (2+1)*TimeOutSpan delay after end of data in UART stream
EndOfDataCnt = 2;
while (_tickCount < TimeOutCnt && EndOfDataCnt > 0)
{
try
{
justReceived = 0;
justReceived = base.BaseStream.Read(buffer, totalReceived, maxLen - totalReceived);
totalReceived += justReceived;
if (totalReceived >= maxLen)
break;
}
catch (TimeoutException)
{
if (totalReceived > 0)
EndOfDataCnt--;
}
catch (Exception ex)
{
totalReceived = -1;
base.Close();
Console.WriteLine("Recv exception: " + ex);
break;
}
} //while
if (totalReceived == 0)
{
throw new TimeoutException();
}
else
{
return totalReceived;
}
} // Recv()
} // Uart
Note that usage of a SerialPort.DataReceived event is optional. You can set proper timeout using SerialPort.ReadTimeout and continuously call SerialPort.Read() after you wrote something to a port until you get a full response.
Moreover, you can use SerialPort.BaseStream property to extract an underlying Stream instance. The benefit of using a Stream is that you can easily utilize various decorators with it:
var port = new SerialPort();
// LoggingStream inherits Stream, implements IDisposable, needed abstract methods and
// overrides needed virtual methods.
Stream portStream = new LoggingStream(port.BaseStream);
portStream.Write(...); // Logs write buffer.
portStream.Read(...); // Logs read buffer.
For more information:
Top 5 SerialPort Tips article by Kim Hamilton, BCL Team Blog
C# await event and timeout in serial port communication discussion on StackOverflow
This question already has answers here:
The calling thread cannot access this object because a different thread owns it
(15 answers)
Closed 6 years ago.
When ever I press the send button the TCP Client, it stops the TCP Server and throws me this error.
The calling thread cannot access this object because a different
thread owns it.
I've tried debugging it but couldnt find the issue.
How would I be able to fix this since it is bugging me alot and I am new to TCP / IP and threading aswell.
I know how it works but yeah.
In the listenerThread() method its this line that is throwing me this error.
lbConnections.Items.Add(handlerSocket.RemoteEndPoint.ToString() + " connected.");
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using System.Text;
namespace SimpleTCPServer
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ArrayList nSockets;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
IPHostEntry IPHost = Dns.GetHostByName(Dns.GetHostName());
lblStatus.Content = "My IP address is " + IPHost.AddressList[0].ToString();
nSockets = new ArrayList();
Thread thdListener = new Thread(new ThreadStart(listenerThread));
thdListener.Start();
}
public void listenerThread()
{
TcpListener tcpListener = new TcpListener(8080);
tcpListener.Start();
while (true)
{
Socket handlerSocket = tcpListener.AcceptSocket();
if (handlerSocket.Connected)
{
Control.CheckForIllegalCrossThreadCalls = false;
lbConnections.Items.Add(handlerSocket.RemoteEndPoint.ToString() + " connected.");
lock (this)
{
nSockets.Add(handlerSocket);
}
ThreadStart thdstHandler = new
ThreadStart(handlerThread);
Thread thdHandler = new Thread(thdstHandler);
thdHandler.Start();
}
}
}
public void handlerThread()
{
Socket handlerSocket = (Socket)nSockets[nSockets.Count - 1];
NetworkStream networkStream = new NetworkStream(handlerSocket);
int thisRead = 0;
int blockSize = 1024;
Byte[] dataByte = new Byte[blockSize];
lock (this)
{
// Only one process can access
// the same file at any given time
Stream fileStream = File.OpenWrite("c:\\my documents\\SubmittedFile.txt");
while (true)
{
thisRead = networkStream.Read(dataByte, 0, blockSize);
fileStream.Write(dataByte, 0, thisRead);
if (thisRead == 0) break;
}
fileStream.Close();
}
lbConnections.Items.Add("File Written");
handlerSocket = null;
}
}
}
TCP Client
using Microsoft.Win32;
using System.IO;
using System.Net.Sockets;
using System.Windows;
using System.Threading;
using System.Net;
using System.Text;
namespace SimpleTCPClient
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void browseButton_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
if (openFileDialog.ShowDialog() == true)
fileTextbox.Text = (openFileDialog.FileName);
}
private void btnSend_Click(object sender, RoutedEventArgs e)
{
Stream fileStream = File.OpenRead(fileTextbox.Text);
// Alocate memory space for the file
byte[] fileBuffer = new byte[fileStream.Length];
fileStream.Read(fileBuffer, 0, (int)fileStream.Length);
// Open a TCP/IP Connection and send the data
TcpClient clientSocket = new TcpClient(ipTextbox.Text, 8080);
NetworkStream networkStream = clientSocket.GetStream();
networkStream.Write(fileBuffer, 0, fileBuffer.GetLength(0));
networkStream.Close();
}
}
}
if lbConnections is a client control, you cannot modify it from a background thread - you must invoke a method that will do the updating on the GUI thread. There's effectively no thread safety around GUI controls, and all disabling Control.CheckForIllegalCrossThreadCalls does is make it less obvious when you shoot yourself in the foot.
In general, you have other problems. For example, your handler thread always tries to grab the last connection - there's a very real possibility that two connections could happen (and both be added to nSockets) before either of the handler threads try to grab the sockets - meaning one socket never gets grabbed and one gets grabbed twice. Plus, it looks like you never actually dispose any of the socket objects, or even allow them to be GCd, since I don't see any code that removes from nSockets.
You really have two good options - either pass the handler thread the data it needs, or use something like a queue and have the handler thread dequeue one socket and operate on it (of course all queue access must be synchronized). Either way you should be disposing of the sockets and not keeping them around forever.
When I select a bunch of files in Explorer and right click open them (or press enter) I want all the files to be passed to a single instance of my application. I've used named pipes before to pass arguments from secondary instances to an existing global instance, but it seems like doing this for hundreds of program instances simultaneously (not to mention actually loading the application hundreds of times) is far from optimal. Is there a way to get explorer to concatenate the arguments on its own?
edit: I found a copy of the Paint.net 3.36 source code and it uses a memory mapped file to communicate between instances. That seems even more bloated than named pipes though (although it's not as likely to open hundreds of images for editing).
You can do it with shell extension.
Check out Creating Shortcut Menu Handlers
and
Create Namespace Extensions for Windows Explorer with the .NET Framework
I couldn't figure out the shell extension so I went with the named pipes. It seems to perform reasonably well, especially since there seems to be a limit in Windows 7 of how many files you can open with multi-select (although this will solve that: open-more-than-15-files-at-once-on-windows-7)
It took me forever to figure out how to get the timeout behavior to work (had to use a manual signal instead of AsyncWaitHandle). Hopefully this will save somebody some time:
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// The Original Code is the IDPicker project.
//
// The Initial Developer of the Original Code is Matt Chambers.
//
// Copyright 2011 Vanderbilt University
//
// Contributor(s):
//
using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Threading;
using System.ComponentModel;
using System.Collections.Generic;
/// <summary>
/// A handler for an application to consolidate arguments from multiple instances
/// (within a Timeout period) into a single instance.
/// </summary>
public sealed class SingleInstanceHandler
{
/// <summary>
/// Occurs when the Timeout period has elapsed: the single instance is launched with the consolidated argument list.
/// </summary>
public event EventHandler<SingleInstanceEventArgs> Launching;
/// <summary>
/// Time to wait in milliseconds for additional instances to add their arguments to the first instance's.
/// </summary>
public int Timeout { get; set; }
/// <summary>
/// Constructs a handler for an application to consolidate arguments from multiple instances
/// (within a Timeout period) into a single instance.
/// </summary>
/// <param name="uniqueID">A unique string for the application.</param>
public SingleInstanceHandler (string uniqueID)
{
var rng = new Random(uniqueID.GetHashCode());
byte[] ipcMutexGuidBytes = new byte[16];
byte[] ipcNamedPipeGuidBytes = new byte[16];
rng.NextBytes(ipcMutexGuidBytes);
rng.NextBytes(ipcNamedPipeGuidBytes);
ipcMutexGuid = new Guid(ipcMutexGuidBytes).ToString().Trim('{', '}');
ipcNamedPipeGuid = new Guid(ipcNamedPipeGuidBytes).ToString().Trim('{', '}');
Timeout = 500;
}
/// <summary>
/// Launch a new instance using 'args' or consolidate 'args' into a recent instance.
/// </summary>
public void Connect (string[] args)
{
if (Launching == null)
return; // nothing to do
// create global named mutex
using (ipcMutex = new Mutex(false, ipcMutexGuid))
{
// if the global mutex is not locked, wait for args from additional instances
if (ipcMutex.WaitOne(0))
waitForAdditionalInstances(args);
else
sendArgsToExistingInstance(args);
}
}
private void waitForAdditionalInstances (string[] args)
{
var accumulatedArgs = new List<string>(args);
while (true)
{
var signal = new ManualResetEvent(false);
using (var pipeServer = new NamedPipeServerStream(ipcNamedPipeGuid, PipeDirection.In, -1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous))
{
pipeServer.BeginWaitForConnection(x =>
{
// if timed out, stop waiting for a connection
if (signal.WaitOne(0))
{
signal.Close();
return;
}
pipeServer.EndWaitForConnection(x);
signal.Set();
}, null);
// no client connected to the pipe within the Timeout period
if (!signal.WaitOne(Timeout, true))
{
signal.Set();
break;
}
using (var sr = new StreamReader(pipeServer))
{
int length = Convert.ToInt32(sr.ReadLine());
for (int i = 0; i < length; ++i)
accumulatedArgs.Add(sr.ReadLine());
}
}
// new args have been added to accumulatedArgs, continue loop to listen for another client
}
Launching(this, new SingleInstanceEventArgs(accumulatedArgs.ToArray()));
}
private void sendArgsToExistingInstance (string[] args)
{
var pipeClient = new NamedPipeClientStream(".", ipcNamedPipeGuid, PipeDirection.Out);
// try to connect to the pipe server for the Timeout period
try
{
var sb = new StringBuilder();
sb.AppendLine(args.Length.ToString());
foreach (string arg in args)
sb.AppendLine(arg);
byte[] buffer = Encoding.ASCII.GetBytes(sb.ToString());
pipeClient.Connect(Timeout);
// can this ever happen? if it does, don't handle it like a timeout exception
if (!pipeClient.IsConnected)
throw new Exception("did not throw exception");
pipeClient.Write(buffer, 0, buffer.Length);
}
catch (Exception e)
{
if (!e.Message.ToLower().Contains("time"))
throw;
// no server was running; launch a new instance
Launching(this, new SingleInstanceEventArgs(args));
}
}
private string ipcMutexGuid;
private string ipcNamedPipeGuid;
private Mutex ipcMutex;
}
/// <summary>
/// Stores the consolidated argument list from one or more instances of an application.
/// </summary>
public sealed class SingleInstanceEventArgs : EventArgs
{
public SingleInstanceEventArgs (string[] args) { Args = args; }
/// <summary>
/// The consolidated argument list from one or more instances of an application.
/// </summary>
public string[] Args { get; private set; }
}
How to use it:
static void Main (string[] args)
{
var singleInstanceHandler = new SingleInstanceHandler(Application.ExecutablePath) { Timeout = 200 };
singleInstanceHandler.Launching += (sender, e) =>
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm(e.Args));
};
singleInstanceHandler.Connect(args);
}
How can I check for an internet connection constantly in my application and respond if the connection is not available?
Currently I am using:
while(true) {
if(HasConnection()) {
//doSomething..
}
//stop app by 1sec
}
but it seems rather inelegant.
The accepted answer to this question on superuser describes the way the Windows determines if it has network access. You could use a similar method, but I would spawn a separate thread when your application starts that is responsible for doing the check. Have the separate thread perform the check in whatever manner you feel is the best and raise an event if the connection status changes.
You're looking for the NetworkAvailabilityChanged event.
To check for internet connectivity, you can ping a reliable website, such as Google.com.
Note that it is not possible to be notified of every change in internet connectivity (such as an ISP outage).
Use the following code:
public static class LocalSystemConnection
{
[DllImport("wininet.dll", SetLastError=true, CallingConvention = CallingConvention.ThisCall)]
extern static bool InternetGetConnectedState(out ConnectionStates lpdwFlags, long dwReserved);
/// <summary>
/// Retrieves the connected state of the local system.
/// </summary>
/// <param name="connectionStates">A <see cref="ConnectionStates"/> value that receives the connection description.</param>
/// <returns>
/// A return value of true indicates that either the modem connection is active, or a LAN connection is active and a proxy is properly configured for the LAN.
/// A return value of false indicates that neither the modem nor the LAN is connected.
/// If false is returned, the <see cref="ConnectionStates.Configured"/> flag may be set to indicate that autodial is configured to "always dial" but is not currently active.
/// If autodial is not configured, the function returns false.
/// </returns>
public static bool IsConnectedToInternet(out ConnectionStates connectionStates)
{
connectionStates = ConnectionStates.Unknown;
return InternetGetConnectedState(out connectionStates, 0);
}
/// <summary>
/// Retrieves the connected state of the local system.
/// </summary>
/// <returns>
/// A return value of true indicates that either the modem connection is active, or a LAN connection is active and a proxy is properly configured for the LAN.
/// A return value of false indicates that neither the modem nor the LAN is connected.
/// If false is returned, the <see cref="ConnectionStates.Configured"/> flag may be set to indicate that autodial is configured to "always dial" but is not currently active.
/// If autodial is not configured, the function returns false.
/// </returns>
public static bool IsConnectedToInternet()
{
ConnectionStates state = ConnectionStates.Unknown;
return IsConnectedToInternet(out state);
}
}
[Flags]
public enum ConnectionStates
{
/// <summary>
/// Unknown state.
/// </summary>
Unknown = 0,
/// <summary>
/// Local system uses a modem to connect to the Internet.
/// </summary>
Modem = 0x1,
/// <summary>
/// Local system uses a local area network to connect to the Internet.
/// </summary>
LAN = 0x2,
/// <summary>
/// Local system uses a proxy server to connect to the Internet.
/// </summary>
Proxy = 0x4,
/// <summary>
/// Local system has RAS (Remote Access Services) installed.
/// </summary>
RasInstalled = 0x10,
/// <summary>
/// Local system is in offline mode.
/// </summary>
Offline = 0x20,
/// <summary>
/// Local system has a valid connection to the Internet, but it might or might not be currently connected.
/// </summary>
Configured = 0x40,
}
if you only need to know if at least one connection is available you can try this:
InternetGetConnectedStateEx()
http://msdn.microsoft.com/en-us/library/aa384705%28v=vs.85%29.aspx
if you want to check continuously then use timer
private Timer timer1;
public void InitTimer()
{
timer1 = new Timer();
timer1.Tick += new EventHandler(timerEvent);
timer1.Interval = 2000; // in miliseconds
timer1.Start();
}
private void timerEvent(object sender, EventArgs e)
{
DoSomeThingWithInternet();
}
private void DoSomeThingWithInternet()
{
if (isConnected())
{
// inform user that "you're connected to internet"
}
else
{
// inform user that "you're not connected to internet"
}
}
public static bool isConnected()
{
try
{
using (var client = new WebClient())
using (client.OpenRead("http://clients3.google.com/generate_204"))
{
return true;
}
}
catch
{
return false;
}
}
I know this is an old question but this works great for me.
System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged;
private async void NetworkChange_NetworkAvailabilityChanged(object sender, System.Net.NetworkInformation.NetworkAvailabilityEventArgs e)
{
//code to execute...
}
I subscribe to the event to a listener and it constantly checks for connection. this you can add a If statement such as:
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
//Send Ping...
}
else
{
//other code....
}
How will you know if you have an Internet Connection? Is it enough that you can route packets to a nearby router? Maybe the machine has only a single NIC, a single gateway, and perhaps that Gateway's connection goes down but the machine can still route to the gateway and local network?
Maybe the machine has a single NIC and a dozen gateways; maybe they come and go all the time, but one of them is always up?
What if the machine has multiple NICs, but only a single gateway? Perhaps it can route to some subset of the Internet, but still has an excellent connection to a local network not connected to the Internet?
What if the machine has muliple NICs, multiple gateways, but for administrative policy reasons, still only portions of the Internet are routeble?
Do you really only care if clients have connectivity to your servers?
What kind of latency between packets is acceptable? (30ms is good, 300ms is pushing the limits of human endurance, 3000ms is intolerable long time, 960000ms is what would be required for a connection to a solar probe.) What kind of packet loss is acceptable?
What are you really trying to measure?
This would be a start but as sarnold has mentioned there are a lot of things you need to consider
You can test internet connectivity by pinging to some website like:
public bool IsConnectedToInternet
{
try
{
using (System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping())
{
string address = #"http://www.google.com";// System.Net.NetworkInformation.PingReply pingReplay = ping.Send(address);//you can specify timeout.
if (pingReplay.Status == System.Net.NetworkInformation.IPStatus.Success)
{
return true;
}
}
}
catch
{
#if DEBUG
System.Diagnostics.Debugger.Break();
#endif//DEBUG
}
return false;
}
This code will life-saving for you.. it not only checks real internet connection but also handle the exception with indication on the console window...
after every 2 seconds
using System;
using System.Net;
using System.Threading;
using System.Net.Http;
bool check() //Checking for Internet Connection
{
while (true)
{
try
{ var i = new Ping().Send("www.google.com").Status;
if (i == IPStatus.Success)
{ Console.WriteLine("connected");
return true;
}
else { return false; }
}
catch (Exception)
{
Console.WriteLine("Not Connected");
Thread.Sleep(2000);
continue;
}
}
};
check();
using the NetworkChange.NetworkAvailabilityChanged is the most misleading answer. It check the network availablity change not the internet connection change.
we can monitor the internet connection using Windows NLM API.
using System;
using System.Runtime.InteropServices.ComTypes;
using NETWORKLIST;
namespace Components.Network.Helpers
{
public class InternetConnectionChecker : INetworkListManagerEvents, IDisposable
{
private int _cookie;
private IConnectionPoint _connectionPoint;
private readonly INetworkListManager _networkListManager;
public InternetConnectionChecker()
{
_networkListManager = new NetworkListManager();
}
public bool IsConnected()
{
return _networkListManager.IsConnectedToInternet;
}
public void StartMonitoringConnection()
{
try
{
var container = _networkListManager as IConnectionPointContainer;
if (container == null)
throw new Exception("connection container is null");
var riid = typeof(INetworkListManagerEvents).GUID;
container.FindConnectionPoint(ref riid, out _connectionPoint);
_connectionPoint.Advise(this, out _cookie);
}
catch (Exception e)
{
}
}
public void ConnectivityChanged(NLM_CONNECTIVITY newConnectivity)
{
if (_networkListManager.IsConnectedToInternet)
{
// do something based on internet connectivity
}
}
public void Dispose()
{
_connectionPoint.Unadvise(_cookie);
}
}
}