C# - Sockets: Port Forwarding [closed] - c#

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 6 years ago.
Improve this question
I am working at a Network Program but when I testing the code I find out that my friends (they are not in my local network) cant connect to the server. Now I found out that port forwarding could be the probleme but I dont know how I can change my code, that my friends can connect (when port forwarding the problem is than how can I implement port forwarding in my code).
Here my Classes:
Server class:
static Socket listenerSocket;
static List<ClientData> clients;
static List<ClientName> clientNames;
static List<ClientName> clientReady;
private int port;
public Server(int port)
{
InitializeComponent();
this.port = port;
}
private void Server_Load(object sender, EventArgs e)
{
Start();
}
private void Start()
{
consoleList.Items.Add("Starting Server on " + Packet.GetIP4Address() + ":" + port);
listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
clients = new List<ClientData>();
clientNames = new List<ClientName>();
clientReady = new List<ClientName>();
IPEndPoint point = new IPEndPoint(IPAddress.Parse(Packet.GetIP4Address()), port);
try
{
listenerSocket.Bind(point);
}
catch (Exception)
{
MessageBox.Show("Port ist schon benutzt!");
Close();
}
Thread listenThread = new Thread(ListenThread);
listenThread.Start();
}
static void ListenThread()
{
for (;;)
{
listenerSocket.Listen(0);
ClientData data = new ClientData(listenerSocket.Accept());
clients.Add(data);
}
}
public static void ResetReadyClientList()
{
ResetReadyClientList_Server();
}
private static void ResetReadyClientList_Server()
{
clientReady.Clear();
}
public static List<ClientName> GetReadyClientList()
{
return clientReady;
}
public static List<ClientName> GetClientList()
{
return clientNames;
}
public static void Data_IN(object cSocket)
{
Socket clientScoket = (Socket)cSocket;
byte[] buffer;
int readBytes;
for (;;)
{
buffer = new byte[clientScoket.SendBufferSize];
readBytes = clientScoket.Receive(buffer);
if(readBytes > 0)
{
Packet packet = new Packet(buffer);
DataManager(packet);
}
}
}
static List<String> packetsReceived = new List<string>();
static List<String> clientsHasDownloaded = new List<string>();
static String path;
public static void DataManager(Packet p)
{
switch (p.packetType)
{
case PacketType.OutWindow:
String name = GetName(p.senderID);
MessageBox.Show(name + " hat aus dem Fenster geklickt!");
break;
case PacketType.RegisterName:
ClientName cName = new ClientName(p.senderID, p.gData[0]);
clientNames.Add(cName);
break;
case PacketType.Answer:
String senderName = GetName(p.senderID);
String answer = p.gData[0];
MessageBox.Show("Spieler " + senderName + " hat " + answer + " getippt!");
ClientName c = new ClientName(p.senderID, GetName(p.senderID));
if (clientReady.Contains(c)) clientReady.Remove(c);
clientReady.Add(c);
break;
case PacketType.HasDownloaded:
clientsHasDownloaded.Add(p.senderID);
if (clientsHasDownloaded.Count == clients.Count)
{
SoundHostForm form = new SoundHostForm();
form.ShowDialog();
path = p.gData[0];
}
break;
}
}
static ClientData GetClientData(String id)
{
foreach (ClientData c in clients)
{
if(c.id == id)
{
return c;
}
}
return null;
}
public static void SendFileToAll(String path)
{
Thread t = new Thread(() => SendFile(path));
t.Start();
}
private static void SendFile(String path)
{
clientsHasDownloaded.Clear();
Uri downloadLink = FileTransfer.UploadFile(path);
Packet p = new Packet(PacketType.CanDownload, "server");
p.gData.Add(downloadLink.ToString());
foreach (ClientData data in clients)
{
data.clientSocket.Send(p.ToBytes());
}
}
public static void SendPacketToAll(Packet p)
{
foreach(ClientData data in clients)
{
data.clientSocket.Send(p.ToBytes());
}
}
static String GetName(String id)
{
foreach (ClientName c in clientNames)
{
if (c.id == id)
{
return c.name;
}
}
return null;
}
}
class ClientData
{
public Socket clientSocket;
public Thread clientThread;
public String id;
public ClientData()
{
id = Guid.NewGuid().ToString();
clientThread = new Thread(Server.Data_IN);
clientThread.Start(clientSocket);
SendRegisterationPacket();
}
public ClientData(Socket clientSocket)
{
this.clientSocket = clientSocket;
id = Guid.NewGuid().ToString();
clientThread = new Thread(Server.Data_IN);
clientThread.Start(clientSocket);
SendRegisterationPacket();
}
public void SendRegisterationPacket()
{
Packet p = new Packet(PacketType.Registration, "server");
p.gData.Add(id);
clientSocket.Send(p.ToBytes());
}
}
public class ClientName
{
public String id;
public String name;
public ClientName(String id, String name)
{
this.id = id;
this.name = name;
}
}
Client:
public static Socket master;
public string username;
public static string id;
private String ip;
private int port;
public Client(String username, String ipPortString)
{
InitializeComponent();
this.username = username;
ip = ipPortString.Split(':')[0];
port = Convert.ToInt32(ipPortString.Split(':')[1]);
}
private void Client_Load(object sender, EventArgs e){}
public void Start()
{
master = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint point = new IPEndPoint(IPAddress.Parse(ip), port);
try
{
master.Connect(point);
}
catch
{
MessageBox.Show("Fehler beim Verbinden! Code: 0x156f237" + "\n" + "Der Server konnte nicht gefunden werden!");
Thread.Sleep(1000);
Start();
}
Thread t = new Thread(Data_IN);
t.Start();
}
void Data_IN()
{
byte[] buffer;
int readBytes;
for (;;)
{
buffer = new byte[master.SendBufferSize];
readBytes = master.Receive(buffer);
if (readBytes > 0)
{
DataManager(new Packet(buffer));
}
}
}
static List<String> packetsReceived = new List<string>();
static TippForm tippFormCache;
void DataManager(Packet p)
{
PacketType type = p.packetType;
switch (type)
{
case PacketType.Registration:
id = p.gData[0];
Packet rp = new Packet(PacketType.RegisterName, id);
rp.gData.Add(username);
master.Send(rp.ToBytes());
break;
case PacketType.Window:
String windowID = p.gData[0];
if (windowID == ABCDForm.SERIALAZIE_ID)
{
if (p.senderID == "server")
{
if (!packetsReceived.Contains(p.packetID))
{
ABCDForm form = new ABCDForm(id, p.gData[1], p.gData[2], p.gData[3], p.gData[4], p.gData[5]);
if (!IsOpened(form))
{
form.ShowDialog();
packetsReceived.Add(p.packetID);
}
}
}
}
else if (windowID == OpenAnswerForm.SERIALIZE_ID)
{
if (p.senderID == "server")
{
if (!packetsReceived.Contains(p.packetID))
{
OpenAnswerForm form = new OpenAnswerForm(id, p.gData[1]);
if (!IsOpened(form))
{
form.ShowDialog();
packetsReceived.Add(p.packetID);
}
}
}
}
else if (windowID == TippForm.SERIALIZE_ID)
{
if (p.senderID == "server")
{
if (!packetsReceived.Contains(p.packetID))
{
tippFormCache = new TippForm(id, p.gData[1], p.gData[2], p.gData[3], p.gData[4], p.gData[5]);
if (!IsOpened(tippFormCache))
{
tippFormCache.ShowDialog();
packetsReceived.Add(p.packetID);
}
}
}
}
else if (windowID == SoundForm.SERIALAZIE_ID)
{
if (p.senderID == "server")
{
if (!packetsReceived.Contains(p.packetID))
{
SoundForm form = new SoundForm(id, p.gData[1]);
if (!IsOpened(form))
{
form.ShowDialog();
packetsReceived.Add(p.packetID);
}
}
}
}
else if (windowID == VideoPlayerForm.SERIALIZE_ID)
{
if (p.senderID == "server")
{
if (!packetsReceived.Contains(p.packetID))
{
playerForm = new VideoPlayerForm(id);
if (!IsOpened(playerForm))
{
Thread t = new Thread(() => OpenVideoPlayerWithSTA(p));
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
}
}
}
break;
case PacketType.OpenNewTipp:
if(tippFormCache != null)
{
tippFormCache.OpenNewTipp();
}
break;
case PacketType.CanDownload:
if(p.senderID == "server")
{
Uri downloadLink = new Uri(p.gData[0]);
String uri = FileTransfer.DownloadFile(downloadLink);
Packet replyPacket = new Packet(PacketType.HasDownloaded, id);
replyPacket.gData.Add(uri);
master.Send(replyPacket.ToBytes());
}
break;
case PacketType.Play:
if (IsOpened(playerForm))
{
playerForm.Start();
}
break;
case PacketType.TogglePause:
if (IsOpened(playerForm))
{
playerForm.Pause();
}
break;
case PacketType.Stop:
if (IsOpened(playerForm))
{
playerForm.Stop();
}
break;
}
}
private static void OpenVideoPlayerWithSTA(Packet p)
{
playerForm.ShowDialog();
packetsReceived.Add(p.packetID);
}
private static VideoPlayerForm playerForm;
private static bool IsOpened(Form form)
{
FormCollection fc = Application.OpenForms;
foreach(Form f in fc)
{
if(f == form)
{
return true;
}
}
return false;
}
And my Packet Class / Server Data:
[Serializable]
public class Packet
{
public List<String> gData;
public int packetInt;
public bool packetBool;
public string senderID;
public PacketType packetType;
public string packetID;
public Packet(PacketType packetType, string senderID)
{
gData = new List<String>();
this.senderID = senderID;
this.packetType = packetType;
packetID = Guid.NewGuid().ToString();
}
public Packet(byte[] bytes)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream(bytes);
ms.Position = 0;
Packet p = (Packet)bf.Deserialize(ms);
ms.Close();
gData = p.gData;
packetBool = p.packetBool;
packetInt = p.packetInt;
packetType = p.packetType;
senderID = p.senderID;
packetID = Guid.NewGuid().ToString();
}
public byte[] ToBytes()
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
ms.Position = 0;
bf.Serialize(ms, this);
byte[] bytes = ms.ToArray();
ms.Close();
return bytes;
}
public static string GetIP4Address()
{
IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
foreach(IPAddress ip in ips)
{
if(ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return ip.ToString();
}
}
return "127.0.0.1";
}
}
public enum PacketType
{
Registration,
Window,
/*[0] = FormID
*
* ABCD:
* [1] = Frage
* [2] = A
* [3] = B
* [4] = C
* [5] = D
*
* OPEN:
* [1] = Frage
*
* TIPP:
* [1] = 1. Tipp
* [2] = 2. Tipp
* [3] = 3. Tipp
* [4] = 4. Tipp
* [5] = 5. Tipp
*
* SOUND:
* [1] = Uri
*/
Answer,//[0] = Antwort
OutWindow,
RegisterName,
Play,
TogglePause,
Stop,
OpenNewTipp,
CanDownload,
HasDownloaded
}
I hope you can help me guys.

You activate port forwarding in the router/NAT that connects you to the Internet. Then your friends'clients should have your public IP address (the one of the router to the Internet Provider, you can see this address logging into the router/NAT) and should send the messages to a specific port. You go to the router and configure port forwarding. This assuming local network means your network is behind a router that connects you to the Internet.

Related

Why has the server stopped responding after a change in source code?

I need to implement HTTP protocol through TCP. I already had a TCP/IP client-server program which had been working absolutely fine.
Now, I have done some minor change in the source code so that it behaves as an HTTP client-server. But, unfortunately it stopped working.
The following code ...
public void Write(string str)
{
if (IsConnected)
{
byte[] strBytes = Encoding.UTF8.GetBytes(str);
byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
Array.Reverse(lenBytes);
writer.Write(lenBytes);
writer.Write(strBytes);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
byte[] lenBytes = reader.ReadBytes(4);
Array.Reverse(lenBytes);
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] bytes = reader.ReadBytes(len);
string str = Encoding.UTF8.GetString(bytes);
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
is changed to:
public void Write(string str)
{
if (IsConnected)
{
byte[] send = Encoding.ASCII.GetBytes(str);
writer.Write(send);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
StreamReader sr = new StreamReader(stream);
string str = sr.ReadToEnd();
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
What is the issue here?
Detailed Source Code
The following class is used by both server program and client program.
modified:
namespace MyClientServer
{
public class ClientClass
{
private string Host { get; set; }
private int Port { get; set; }
private bool IsConnected = false;
public string ID { get; private set; }
public TcpClient Tcp { get; private set; }
NetworkStream stream;
private StreamReader sr;
private StreamWriter writer;
public ClientClass()
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
}
//constructor for server program.
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
IsConnected = true;
stream = Tcp.GetStream();
sr = new StreamReader(stream);
writer = new StreamWriter(stream);
ID = Read();
Console.WriteLine("Client [{0}] is now connected.", ID);
}
public bool Connect()
{
if (IsConnected == false)
{
Console.WriteLine("Client [{0}] is now connected.", ID);
IsConnected = true;
Tcp = new TcpClient(Host, Port);
stream = Tcp.GetStream();
sr = new StreamReader(stream);
writer = new StreamWriter(stream);
return true;
}
return false;
}
//constructor for client.
public ClientClass(string host, int port)
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
Host = host;
Port = port;
}
public void Write(string str)
{
if (IsConnected)
{
byte[] send = Encoding.ASCII.GetBytes(str);
writer.Write(send);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
StreamReader sr = new StreamReader(stream);
string str = sr.ReadToEnd();
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void PrintID()
{
Console.WriteLine("Client ID = {0}", ID);
}
public void SendIdToServer()
{
this.Write(ID);
}
public bool Disconnect()
{
if (IsConnected)
{
if (Tcp != null)
{
Tcp.Close();
Tcp = null;
Console.WriteLine("\nClient [{0}] is now disconnected.", ID);
return true;
}
}
return false;
}
}
}
original:
namespace MyClientServer
{
public class ClientClass
{
private string Host { get; set; }
private int Port { get; set; }
private bool IsConnected = false;
public string ID { get; private set; }
public TcpClient Tcp { get; private set; }
private BinaryReader reader;
private BinaryWriter writer;
public ClientClass()
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
}
//constructor for server program.
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
IsConnected = true;
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
ID = Read();
Console.WriteLine("Client [{0}] is now connected.", ID);
}
public bool Connect()
{
if (IsConnected == false)
{
Console.WriteLine("Client [{0}] is now connected.", ID);
IsConnected = true;
Tcp = new TcpClient(Host, Port);
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
return true;
}
return false;
}
//constructor for client.
public ClientClass(string host, int port)
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
Host = host;
Port = port;
}
public void Write(string str)
{
if (IsConnected)
{
byte[] strBytes = Encoding.UTF8.GetBytes(str);
byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
Array.Reverse(lenBytes);
writer.Write(lenBytes);
writer.Write(strBytes);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected)
{
byte[] lenBytes = reader.ReadBytes(4);
Array.Reverse(lenBytes);
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] bytes = reader.ReadBytes(len);
string str = Encoding.UTF8.GetString(bytes);
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void PrintID()
{
Console.WriteLine("Client ID = {0}", ID);
}
public void SendIdToServer()
{
this.Write(ID);
}
public bool Disconnect()
{
if (IsConnected)
{
if (Tcp != null)
{
Tcp.Close();
Tcp = null;
Console.WriteLine("\nClient [{0}] is now disconnected.", ID);
return true;
}
}
return false;
}
}
}
I took the advice of #Jimi and also took a look at the source code from this link.
Now my source code looks like the following:
public string Read()
{
if (IsConnected)
{
byte[] buffer = new byte[Tcp.ReceiveBufferSize];//create a byte array
int bytesRead = stream.Read(buffer, 0, Tcp.ReceiveBufferSize);//read count
string str = Encoding.ASCII.GetString(buffer, 0, bytesRead);//convert to string
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void Write(string str)
{
if (IsConnected)
{
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(str);
stream.Write(bytesToSend, 0, bytesToSend.Length);
stream.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
and, it is working fine.

Why doesn't the server shut down?

The following source code polls for incoming client connections.
class ServerForm : Form
{
//...
void PollIncomingClientConns(TcpListener listener)
{
listener.Start();
_keepPolling = true;
try
{
while (_keepPolling)
{
ClientClass client = new ClientClass(listener);
ClientDictionary.Add(client.ID, client);
SetStringToTextBox("Client [" + client.ID + "] is now connected.");
Thread thread = new Thread(delegate()
{
ReadFromClient(client);
});
thread.IsBackground = true;
thread.Start();
}
_tcplistener.Server.Close();
_tcplistener.Server.Dispose();
_tcplistener = null;
}
catch (Exception ex)
{
var inner = ex.InnerException as SocketException;
if (inner != null && inner.SocketErrorCode == SocketError.ConnectionReset)
{
SetStringToTextBox("Disconnected");
}
else
{
SetStringToTextBox(ex.Message);
}
listener.Stop();
}
}
void ReadFromClient(ClientClass client)
{
try
{
while (true)
{
string str = client.Read();
SetStringToTextBox("[" + client.ID + "] says: " + str);
switch (str)
{
// ... service client requests ...
// ... text messages ...
}
if (!client.Tcp.Connected)
{
SetStringToTextBox("[" + client.ID + "] is disconnected.");
client.Close();
break;
}
}
}
catch
{
client.Close();
}
}
// ...
}
In order to shut down the server, I am clicking, say, a button and setting _keepPolling to false.
But, on the client-side, I am finding that the client is still able to connect to the server. I.e. the server isn't shut down.
How can I solve this issue?
Relevant Source Code
The following is the client source code,
public class ClientClass
{
public string ID { get; private set; }
public string Host { get; set; }
public int Port { get; set; }
public TcpClient Tcp { get; private set; }
private BinaryReader reader;
private BinaryWriter writer;
/// <summary>
/// Creates a clienbt at the Client-end.
/// This requires Host and Post property to be set.
/// </summary>
public ClientClass()
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
}
/// <summary>
/// Creates a client at the Client-end.
/// </summary>
/// <param name="host"></param>
/// <param name="port"></param>
public ClientClass(string host, int port)
{
Random rnd = new Random();
ID = AlphaNumRandom.GenerateUpperCaseString(5, rnd);
Host = host;
Port = port;
}
/// <summary>
/// creates a proxy-client at the Server-end.
/// </summary>
/// <param name="listener"></param>
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
ID = Read();
}
/// <summary>
/// Connects the client to the server.
/// </summary>
/// <returns></returns>
public bool Connect()
{
bool is_connected = IsConnected();
if (!is_connected)
{
Tcp = new TcpClient(Host, Port);
NetworkStream stream = Tcp.GetStream();
reader = new BinaryReader(stream);
writer = new BinaryWriter(stream);
return true;
}
else if (is_connected)
{
return true;
}
else return false;
}
public bool IsConnected()
{
if (Tcp == null)
{
return false;
}
else
{
Socket s = Tcp.Client;
bool part1 = s.Poll(1000, SelectMode.SelectRead);
bool part2 = (s.Available == 0);
if ((part1 && part2) || !s.Connected)
return false;
else
return true;
}
}
public void Write(string str)
{
if (IsConnected())
{
byte[] strBytes = Encoding.UTF8.GetBytes(str);
byte[] lenBytes = BitConverter.GetBytes(strBytes.Length);
Array.Reverse(lenBytes);
writer.Write(lenBytes);
writer.Write(strBytes);
writer.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public string Read()
{
if (IsConnected())
{
byte[] lenBytes = reader.ReadBytes(4);
Array.Reverse(lenBytes);
int len = BitConverter.ToInt32(lenBytes, 0);
byte[] bytes = reader.ReadBytes(len);
string str = Encoding.UTF8.GetString(bytes);
return str;
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void PrintID()
{
Console.WriteLine("Client ID = {0}", ID);
}
public void SendIdToServer()
{
this.Write(ID);
}
public bool Close()
{
if (IsConnected())
{
if (Tcp != null)
{
Tcp.Close();
Tcp = null;
return true;
}
}
return false;
}
}
Edit:
class ServerForm : Form
{
// ...
private void startToolStripMenuItem_Click(object sender, EventArgs e)
{
string ipAddress = Constants.LOCAL_HOST_IP;
int portNo = Constants.PORT_NO;
IPAddress ip = IPAddress.Parse(ipAddress);
_tcplistener = new TcpListener(ip, portNo);
// poll for clients in a 2nd thread
Thread thread = new Thread(delegate()
{
PollIncomingClientConns(_tcplistener);
});
thread.IsBackground = true;
thread.Start();
SetStringToTextBox("Server program started on address [" + ipAddress + ":" + portNo + "]");
startToolStripMenuItem.Enabled = false;
stopToolStripMenuItem.Enabled = true;
}
// ...
}
After some testing, calling _tcplistener.Stop(); is sufficient. Call it where you are setting _keepPolling to false

Can't read/write data (TcpClient/Server)

I'm actually able to connect my TcpClient to my TcpServer, but I can't make them communicate. I tried client.GetStream() and BinaryReader/Writer.
Here is my code:
-Client:
public partial class Client : Window
{
#region Constructeurs
public Client() : this(string.Empty, 12221) { }
public Client(string ipDefaut, int portDefaut)
{
InitializeComponent();
numIp.FromString("192.168.2.168");
numPort.Value = portDefaut;
Serveur serveur = new Serveur();
serveur.Show();
}
#endregion
public void Start()
{
if (Ip == null)
return;
if (client == null || client.Client == null)
client = new TcpClient();
if (client.Connected == true)
{
ShowMessage("Déjà connecté.");
return;
}
client = new TcpClient();
try
{
client.ConnectAsync(Ip, Port).Wait(10);
}
catch (SocketException) { }
}
public void Stop()
{
if (client != null && client.Client != null)
if (client.Connected)
{
client.Client.Shutdown(SocketShutdown.Both);
client.Close();
}
}
public string Read()
{
if (client != null && client.GetStream() != null)
if (client.Connected && client.GetStream().DataAvailable)
{
BinaryReader reader = new BinaryReader(client.GetStream());
return reader.ReadString();
}
return string.Empty;
}
public void Send(string info)
{
if (client != null && client.GetStream() != null)
if (client.Connected)
{
BinaryWriter writer = new BinaryWriter(client.GetStream());
writer.Write(info);
writer.Flush();
}
}
private void ShowMessage(string message)
{
labelInfo.Content = message;
Storyboard sb = Resources["sbLabelInfo"] as Storyboard;
sb.Begin(labelInfo);
}
private void Connecter(object sender, RoutedEventArgs e)
{
foreach (string num in numIp.ToStringArray())
if (num == string.Empty)
{
ShowMessage("L'adresse ip doit être complète.");
return;
}
Start();
if (client.Connected)
{
ShowMessage("Connecté");
boutonConnecter.IsEnabled = false;
numIp.IsEnabled = false;
numPort.IsEnabled = false;
boutonAnnuler.Content = "Déconnecter";
}
else
ShowMessage("Impossible de se connecter.");
}
private void Annuler(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
Close();
else if ((string)boutonAnnuler.Content == "Déconnecter")
{
Stop();
boutonConnecter.IsEnabled = true;
numIp.IsEnabled = true;
numPort.IsEnabled = true;
boutonAnnuler.Content = "Annuler";
}
}
#region Propriétés
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
#endregion
#region Membres
private TcpClient client = new TcpClient();
#endregion
}
-Server:
public partial class Serveur : Window
{
#region Constructeurs
public Serveur() : this(12221) { }
public Serveur(int numPortDefaut)
{
InitializeComponent();
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
if (addr.AddressFamily == AddressFamily.InterNetwork)
numIp.FromString(addr.ToString());
numPort.Value = numPortDefaut;
serveur = new TcpListener(IPAddress.Parse(Ip), Port);
thread = new Thread(Accept);
serveur.Stop();
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
boutonDemarrer.IsEnabled = false;
MessageBox.Show(this, "Connection impossible - Tic Tac Toe", "Impossible de se connecter à internet. Vérifiez votre connection et réessayez.", MessageBoxButton.OK, MessageBoxImage.Warning);
Close();
}
}
#endregion
public void Start()
{
if (serveur != null)
{
try
{
serveur.Start();
}
catch (SocketException) { }
IsConnected = false;
StartThread();
}
else
{
serveur = new TcpListener(IPAddress.Parse(Ip), Port);
Start();
}
}
public void Stop()
{
if (serveur != null)
{
IsConnected = false;
serveur.Stop();
StopThread();
}
}
public void StartThread()
{
if (thread.ThreadState == ThreadState.Stopped)
thread.Start();
}
public void StopThread()
{
if (!IsConnected)
{
IsConnected = true;
while (thread.IsAlive) { }
IsConnected = false;
}
}
private void Accept()
{
while (!IsConnected && serveur != null)
if (serveur.Pending())
{
client = serveur.AcceptTcpClient();
IsConnected = true;
}
}
public string Read()
{
if (client != null && client.GetStream() != null)
if (client.Connected && client.GetStream().DataAvailable)
{
BinaryReader reader = new BinaryReader(client.GetStream());
return reader.ReadString();
}
return string.Empty;
}
public void Send(string info)
{
if (client != null && client.GetStream() != null)
if (client.Connected)
{
BinaryWriter writer = new BinaryWriter(client.GetStream());
writer.Write(info);
writer.Flush();
}
}
private void Demarrer(object sender, RoutedEventArgs e)
{
Start();
boutonAnnuler.Content = "Stop";
boutonDemarrer.IsEnabled = false;
numPort.IsEnabled = false;
numIp.IsEnabled = false;
}
private void Annuler(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
{
Stop();
Close();
}
else if ((string)boutonAnnuler.Content == "Stop")
{
StopThread();
boutonAnnuler.Content = "Annuler";
boutonDemarrer.IsEnabled = true;
numPort.IsEnabled = true;
numIp.IsEnabled = true;
}
}
#region Propriétés
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
public bool IsConnected { get; private set; }
#endregion
#region Membres
private TcpListener serveur = null;
private TcpClient client = null;
private Thread thread = null;
#endregion
}
The problem is that, in debug mode, client.GetStream().DataAvailable return always false.
Why does it return that and how do I can solve this ?
(numIp and numPort are some fields that the user needs to fill)
try this:
//tcp server
public class Server
{
private string ip { get; set; }
private int port { get; set; }
private Socket server { get; set; }
public List<ClientInfo> listClientsConnected { get; private set; }
// delegate for events
public delegate void Client_Connected(ClientInfo c);
public delegate void Client_Message(string msg, ClientInfo c);
public Server(string ip, int port)
{
this.ip = ip;
this.port = port;
this.listClientsConnected = new List<ClientInfo>();
}
// start server
public void Start()
{
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Parse(this.ip), this.port));
server.Listen(1);
server.BeginAccept(new AsyncCallback(ClientConnected), server);
}
// accept client connection
private void ClientConnected(IAsyncResult res)
{
Socket s = (Socket)res.AsyncState;
Socket client = s.EndAccept(res);
ClientInfo clientInf = new ClientInfo()
{
currentClient = client
};
client.BeginReceive(clientInf.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), clientInf);
// add client to list
listClientsConnected.Add(clientInf);
if (Cliente_Conneted_Event != null)
Cliente_Conneted_Event(clientInf);
}
// receive message from client
private void ReceiveMessage(IAsyncResult ar)
{
ClientInfo cl = (ClientInfo)ar.AsyncState;
Socket s = cl.currentClient;
int read = s.EndReceive(ar);
string msg = null;
if (read > 0)
{
msg = Encoding.ASCII.GetString(cl.buffer, 0, read);
s.BeginReceive(cl.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), cl);
}
if (Cliente_Message_Event != null)
Cliente_Message_Event(msg, cl);
}
// send message to client
public void sendMessage(string msg, ClientInfo client)
{
if (client.currentClient != null)
{
if (client.currentClient.Connected && !string.IsNullOrEmpty(msg))
{
client.currentClient.Send(Encoding.ASCII.GetBytes(msg));
}
}
}
//events
public event Client_Connected Cliente_Conneted_Event;
public event Client_Message Cliente_Message_Event;
}
// tcp client
public class Client
{
private Socket client { get; set; }
private string clientName { get; set; }
private string ip { get; set; }
private int port { get; set; }
// delegates
public delegate void Client_Connected(ClientInfo c);
public delegate void Client_Message(string msg, ClientInfo c);
public Client(string ip, int port)
{
this.ip = ip;
this.port = port;
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
// connect client to server
public void Connect()
{
ClientInfo clientInf = new ClientInfo()
{
currentClient = client,
};
client.BeginConnect(new IPEndPoint(IPAddress.Parse(this.ip), this.port), new AsyncCallback(ClientConnected), clientInf);
}
// accept client connection
private void ClientConnected(IAsyncResult res)
{
ClientInfo clientInf = (ClientInfo)res.AsyncState;
clientInf.currentClient.BeginReceive(clientInf.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), clientInf);
// client connected
if (Cliente_Conneted_Event != null)
Cliente_Conneted_Event(clientInf);
}
// receive message from client
private void ReceiveMessage(IAsyncResult ar)
{
ClientInfo cl = (ClientInfo)ar.AsyncState;
Socket s = cl.currentClient;
int read = s.EndReceive(ar);
string msg = null;
if (read > 0)
{
msg = Encoding.ASCII.GetString(cl.buffer, 0, read);
s.BeginReceive(cl.buffer, 0, ClientInfo.BUFFER_SIZE_FOR_MESSAGE, 0, new AsyncCallback(ReceiveMessage), cl);
}
if (Cliente_Message_Event != null)
Cliente_Message_Event(msg, cl);
}
// send message to client
public void sendMessage(string msg, ClientInfo client)
{
if (client.currentClient != null)
{
if (client.currentClient.Connected && !string.IsNullOrEmpty(msg))
{
client.currentClient.Send(Encoding.ASCII.GetBytes(msg));
}
}
}
public event Client_Connected Cliente_Conneted_Event;
public event Client_Message Cliente_Message_Event;
}
// in my case i used a console application
class Program
{
private static Server server;
static void Main(string[] args)
{
string ip = "127.0.0.1";
int port = 3122;
server = new Server(ip, port);
server.Cliente_Conneted_Event += server_Cliente_Conneted_Event;
server.Start();
// connect client 1
Client client = new Client(ip, port);
client.Connect();
client.Cliente_Message_Event+=client_Cliente_Message_Event;
sendMessageToClient();
Console.ReadKey();
}
//receive message from server
private static void client_Cliente_Message_Event(string msg, ClientInfo c)
{
try {
Console.WriteLine("Msg from Server:"+msg);
}
catch(Exception ex){
Console.WriteLine(ex.Message);
}
}
// client connected to server
private static void server_Cliente_Conneted_Event(ClientInfo c)
{
Console.WriteLine("Client Connected...");
}
// send message to all clients from server
private static void sendMessageToClient()
{
try
{
Console.Write("Msg:");
string msg = Console.ReadLine();
// send message to clients
if (server.listClientsConnected.Count > 0)
{
foreach (ClientInfo client in server.listClientsConnected)
server.sendMessage(msg, client);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
sendMessageToClient();
}
}
}
It was longer than expected... I finally gave up on the TcpClient/Server to use my own sockets.
Here is the result (i made a abstract class in my code because these classes are similar) :
Abstract class :
public abstract partial class Connectable : Window
{
public abstract void Start();
public abstract void Stop();
public void WaitMessage()
{
WaitMessage(new StateObject() { socket = socket });
}
private void WaitMessage(StateObject so)
{
Socket s = so.socket;
int read = s.Receive(so.buffer, 0, StateObject.BUFFER_SIZE, SocketFlags.None);
so.sb.Append(Encoding.UTF8.GetString(so.buffer, 0, read));
if (s.Available > 0)
WaitMessage(so);
else if (NewMessage != null)
{
NewMessage(so.sb.ToString());
so.sb.Clear();
}
}
public void ReceiveMessage()
{
StateObject state = new StateObject() { socket = socket };
try { socket.BeginReceive(state.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(MessageReceived), state); }
catch (SocketException e) { Console.WriteLine(e.Message); }
}
protected void MessageReceived(IAsyncResult ar)
{
StateObject so = (StateObject)ar.AsyncState;
Socket s = so.socket;
int read = s.EndReceive(ar);
so.sb.Append(Encoding.UTF8.GetString(so.buffer, 0, read));
if (s.Available > 0)
s.BeginReceive(so.buffer, 0, StateObject.BUFFER_SIZE, 0, new AsyncCallback(MessageReceived), so);
else if (NewMessage != null)
{
NewMessage(so.sb.ToString());
so.sb.Clear();
}
}
public void SendMessage(string msg)
{
if (socket != null)
{
if (socket.Connected && !string.IsNullOrEmpty(msg))
{
socket.Send(Encoding.UTF8.GetBytes(msg));
}
}
}
protected void ShowMessage(string message)
{
Console.WriteLine(message);
}
public virtual bool IsConnected()
{
if (socket == null)
return false;
return socket.Connected;
}
#region Members
protected Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public Message NewMessage;
#endregion
#region Delegates
public delegate void Message(string message);
#endregion
}
Server class :
public partial class Server : Connectable
{
#region Constructeurs
public Server() : this(12221) { }
public Server(int numPortDefaut)
{
InitializeComponent();
socket = null;
NewMessage += ShowMessage;
foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
if (addr.AddressFamily == AddressFamily.InterNetwork)
numIp.FromString(addr.ToString());
numPort.Value = numPortDefaut;
if (!System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
boutonDemarrer.IsEnabled = false;
MessageBox.Show(this, "Connection impossible - Tic Tac Toe", "Impossible de se connecter à internet. Vérifiez votre connection et réessayez.", MessageBoxButton.OK, MessageBoxImage.Warning);
Close();
}
}
#endregion
public override void Start()
{
if (socketListener.IsBound)
{
if (socket != null)
{
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
socket.Dispose();
socket = null;
}
socketListener.Close();
socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
try
{
socketListener.Bind(new IPEndPoint(IPAddress.Parse(Ip), Port));
socketListener.Listen(1);
AcceptConnection();
}
catch (SocketException e) { Console.WriteLine(e); }
}
public override void Stop()
{
acceptConnection.Cancel();
if (socket != null)
{
socketListener.Close();
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(false);
socket.Dispose();
socket = null;
}
}
private void AcceptConnection()
{
acceptConnection = new CancellationTokenSource();
new Thread(delegate()
{
try
{
while (socket == null)
{
if (socketListener.Poll(1, SelectMode.SelectRead))
socket = socketListener.Accept();
acceptConnection.Token.ThrowIfCancellationRequested();
}
Dispatcher.Invoke(delegate ()
{
boutonDemarrer.Content = "Jouer";
boutonDemarrer.IsEnabled = true;
});
}
catch (OperationCanceledException e) { Console.WriteLine("Fin de l'attente de connection ({0})", e.Message); }
}).Start();
}
private void ButtonClickStart(object sender, RoutedEventArgs e)
{
if ((string)boutonDemarrer.Content == "Jouer")
Close();
else if ((string)boutonDemarrer.Content == "Démarrer")
{
Start();
boutonAnnuler.Content = "Stop";
boutonDemarrer.IsEnabled = false;
numPort.IsEnabled = false;
}
}
private void ButtonClickCancel(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
Close();
else if ((string)boutonAnnuler.Content == "Stop")
{
Stop();
boutonAnnuler.Content = "Annuler";
boutonDemarrer.Content = "Démarrer";
boutonDemarrer.IsEnabled = true;
numPort.IsEnabled = true;
}
}
#region Propriétés
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
#endregion
#region Membres
private Socket socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private CancellationTokenSource acceptConnection = new CancellationTokenSource();
#endregion
}
Client class :
public partial class Client : Connectable
{
#region Constructeurs
public Client() : this(string.Empty, 12221) { }
public Client(string ipDefaut, int portDefaut)
{
InitializeComponent();
NewMessage += ShowMessage;
numIp.FromString("192.168.2.168");
numPort.Value = portDefaut;
}
#endregion
public override void Start()
{
try
{
socket.Connect(Ip, Port);
boutonConnecter.Content = "Jouer";
numIp.IsEnabled = false;
numPort.IsEnabled = false;
boutonAnnuler.Content = "Déconnecter";
}
catch (SocketException e)
{
Console.WriteLine(e.Message);
}
}
public override void Stop()
{
if (socket.Connected)
{
socket.Shutdown(SocketShutdown.Both);
socket.Close();
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
}
private void ButtonClickStart(object sender, RoutedEventArgs e)
{
if ((string)boutonConnecter.Content == "Jouer")
Close();
else if ((string)boutonConnecter.Content == "Connecter")
{
foreach (string num in numIp.ToStringArray())
if (num == string.Empty)
{
ShowMessage("L'adresse ip doit être complète.");
return;
}
Start();
}
}
private void ButtonClickCancel(object sender, RoutedEventArgs e)
{
if ((string)boutonAnnuler.Content == "Annuler")
Close();
else if ((string)boutonAnnuler.Content == "Déconnecter")
{
Stop();
boutonConnecter.IsEnabled = true;
numIp.IsEnabled = true;
numPort.IsEnabled = true;
boutonAnnuler.Content = "Annuler";
boutonConnecter.Content = "Connecter";
}
}
#region Properties
public string Ip { get { return numIp.ToString(); } }
public int Port { get { return (int)numPort.Value; } }
#endregion
}
If it can help someone else... :)

Asynchronous socket + waitone()

Let's start with some code:
class InternetConnector
{
private struct ConnectionData
{
public Action<Socket> SuccessHandler { get; set; }
public ClientStateObject clientObj { get; set; }
public Action<Exception> ErrorHandler { get; set; }
public Socket Socket { get; set; }
}
public static ManualResetEvent processingDone = new ManualResetEvent( false );
public static ConcurrentQueue<string> messages = new ConcurrentQueue<string>();
public bool ReceiveMessage(Action<Socket> successHandler, Action<Exception> errorHandler)
{
ClientStateObject obj = new ClientStateObject();
obj.server = client;
var connectionData = new ConnectionData
{
ErrorHandler = errorHandler,
SuccessHandler = successHandler,
Socket = client,
clientObj = obj
};
if (Connected)
{
client.BeginReceive(connectionData.clientObj.buffer, 0, ClientStateObject.bufSize, 0, new AsyncCallback(ReceiveCallback), connectionData);
receive = true;
receiveDone.WaitOne();
}
return receive;
}
private static void ReceiveCallback(IAsyncResult ar)
{
ConnectionData connectionData = new ConnectionData();
bool complete = false;
try
{
connectionData = (ConnectionData)ar.AsyncState;
Socket client = connectionData.Socket;
int num = client.EndReceive(ar);
{
connectionData.clientObj.stringBuffer.Append(Encoding.ASCII.GetString(connectionData.clientObj.buffer, 0, num));
string response = connectionData.clientObj.stringBuffer.ToString();
string[] msgs = response.Split('&');
for (int i = 0; i < msgs.Count(); i++)
{
string sts = msgs[i];
messages.Enqueue(sts + "&" );
}
receiveDone.Set();
if (connectionData.SuccessHandler != null)
{
connectionData.SuccessHandler(client);
processingDone.WaitOne();
client.BeginReceive(connectionData.clientObj.buffer, 0, ClientStateObject.bufSize, 0, new AsyncCallback(ReceiveCallback), connectionData);
}
}
}
catch (Exception e)
{
if (connectionData.ErrorHandler != null)
connectionData.ErrorHandler(e);
}
}
public partial class Form1 : Form
{
private InternetConnector client = new InternetConnector();
private bool isRunning = false;
private void AsyncSuccessHandler(Socket socket)
{
if (InvokeRequired)
{
BeginInvoke(new Action( () => AsyncSuccessHandler( socket ) ));
return;
}
if (InternetConnector.messages.Count() == 0)
{
status.Text = "Signals Receiver: Connected";
status.ForeColor = Color.Green;
isRunning = true;
client.ReceiveMessage(AsyncSuccessHandler, AsyncErrorHandler);
}
else
{
GUIChangeOnConnection();
InternetConnector.processingDone.Set();
}
}
private void GUIChangeOnConnection()
{
for( int i = 0; i < InternetConnector.messages.Count; i++ )
{
string message;
InternetConnector.messages.TryDequeue( out message );
// process the message
}
}
}
Now the problem.
Everything works fine. Reading from the socket is happening. However the call processingDone.WaitOne(); which should block the callback indefinitely until the call to processingDone.Set(); returns too early.
I verified it by setting the breakpoint at the end of the GUIChangeOnConnection(); - function closing bracket line. It hits the breakpoint and looking at the InternetConnector.messages I see that the queue is not empty, which means that the for loop did not finish.
And the second time this breakpoint is hit the number of messages in the queue is sky-rocketing.
What am I doing wrong? Or maybe my design is incorrect?
Thank you.

C# multi-thread ping

I'm working on a network monitoring application, that pings a (not known) number of hosts. So far I have the code below. I've made a class PingHost with a function zping and I called it with the help of a timer once every 2 seconds to let the 2 pings to finish, even if one of them gets TimedOut. But I think a better solution is to generate a new thread for every ping, so that the ping of every host would be independent.
Can anyone give me a hint how to do this?
namespace pinguin
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
PingHost caca = new PingHost();
PingHost caca1 = new PingHost();
this.label1.Text = caca.zping("89.115.14.160");
this.label2.Text = caca1.zping("89.115.14.129");
}
}
public class PingHost
{
public string zping(string dest)
{
Application.DoEvents();
Ping sender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 50;
int failed = 0;
int pingAmount = 5;
string stat = "";
PingReply reply = sender.Send(dest, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
stat = "ok";
}
else
{
stat = "not ok!";
}
return stat;
}
}
}
If you use .NET 4 you can use Parallel.Invoke.
You could handle the Ping.PingCompleted event:
ping.PingCompleted += new PingCompletedEventHandler(ping_PingCompleted);
then use:
ping.SendAsync()
side note: Choose more suitable names for your classes and routines. PingHost is more suitable as a routine name
Once I wrote such a solution (it constantly pings about 300 machines):
public class ManyAdressPing {
private readonly bool bAutoStarted;
private readonly CancellationTokenSource cancel = new CancellationTokenSource();
public ConcurrentDictionary<IPAddress, OneAddressPing> pingi = new ConcurrentDictionary<IPAddress, OneAddressPing>();
public ManyAdressPing(bool AutoStarted = true) {
bAutoStarted = AutoStarted;
}
public int CountPings => pingi.Count;
public void AddPingAddress(IPAddress addr, int msTimeOut = 3000, int BetweenPing = 3000) {
var oap = new OneAddressPing(addr, cancel.Token, msTimeOut, BetweenPing);
if (bAutoStarted) oap.Start();
pingi.TryAdd(oap.ipAddress, oap);
}
public void RemovePingAddress(IPAddress addr) {
if (pingi.TryRemove(addr, out var p)) p.Stop();
}
public void Stop() {
cancel.Cancel();
foreach (var pair in pingi) pair.Value.Stop();
}
public PingReply GetReply(IPAddress addr) {
if (pingi.ContainsKey(addr)) return pingi[addr].GetReply();
return null;
}
public Tuple<long, long> GetSuccessOperation(IPAddress addr) {
if (pingi.ContainsKey(addr)) return pingi[addr].GetSuccessOperation();
return null;
}
public PingReply[] GetReply() {
PingReply[] ret = pingi.Values.Select(x=>x.GetReply()).ToArray();
return ret;
}
public PingInfo GetPingInfo(IPAddress addr) {
if (pingi.ContainsKey(addr)) {
var ret = new PingInfo();
var p = pingi[addr];
ret.reply = p.GetReply();
ret.SuccessPing = p._SuccessReply;
ret.FailPing = p._FailReply;
ret.LastSuccessPing = p.LastSuccessfullPing;
return ret;
}
return null;
}
public bool IsPinged(IPAddress addr) {
if (pingi.ContainsKey(addr)) return true;
return false;
}
public IPAddress[] GetAddressesPing() {
return pingi.Keys.ToArray();
}
}
public class PingInfo {
public PingReply reply;
public long SuccessPing = 0;
public long FailPing = 0;
public DateTime LastSuccessPing;
public override string ToString() {
return $"Sping: {SuccessPing} last={LastSuccessPing}, Fping:{FailPing}, reply:{reply}";
}
}
public class OneAddressPing {
public static byte[] bu = {
0
};
public long _FailReply;
public long _SuccessReply;
private bool bStop = false;
private readonly CancellationToken cancellationToken;
public DateTime LastSuccessfullPing = DateTime.MinValue;
public int mSecBetweenPing = 3000;
public Ping ping;
public PingOptions popt;
private Task pTask;
// Here is a self-written LIFO stack
public LightQueue<PingReply> replys = new LightQueue<PingReply>(10);
private readonly AutoResetEvent reset = new AutoResetEvent(false);
private Logger log = null;
private Task pinging = null;
public OneAddressPing(IPAddress addr, CancellationToken ct, int timeOut = 3000, int BetweenPing = 3000, Logger _log =null) {
ipAddress = addr;
popt = new PingOptions();
popt.DontFragment = false;
cancellationToken = ct;
mSecTimeOut = timeOut;
mSecBetweenPing = BetweenPing;
log = _log;
}
public int mSecTimeOut { get; set; } = 3000;
public IPAddress ipAddress { get; set; }
public int CountPings => replys.Length;
private void SetReply(PingReply rep) {
if (rep == null) return;
replys.Put(rep);
if (rep.Status == IPStatus.Success) {
Interlocked.Increment(ref _SuccessReply);
LastSuccessfullPing = DateTime.Now;
} else {
Interlocked.Increment(ref _FailReply);
}
}
public async Task Start() {
if (pTask == null || pTask.Status != TaskStatus.Running) {
ping = new Ping();
Task.Factory.StartNew(PingCircle, TaskCreationOptions.RunContinuationsAsynchronously | TaskCreationOptions.LongRunning); pTask = Task.Run(PingCircle, cancellationToken);
}
}
public void Stop() {
if (pTask.Status == TaskStatus.Running) {
bStop = true;
try {
pTask.Wait(mSecTimeOut, cancellationToken);
} catch (Exception ex) {
log.ErrorSource($"Error ping stop: {ex.Message}");
}
}
}
private async Task PingCircle() {
while (cancellationToken.IsCancellationRequested == false && !bStop) {
try {
try {
PingReply rep = await ping.SendPingAsync(ipAddress, mSecTimeOut, bu,popt);
if (rep != null) SetReply(rep);
} catch (PingException p) {
// ignore ping error
Debug.WriteLine($"error: {p}");
} catch (Exception ee) {
log?.ErrorSource(ee);
Debug.WriteLine($"error: {ee}");
}
await Task.Delay(mSecBetweenPing, cancellationToken);
} catch (Exception ee) {
log?.ErrorSource(ee);
}
}
}
public PingReply GetReply() {
if (replys.IsEmpty) return null;
return replys.PeekLast(0);
}
public Tuple<long, long> GetSuccessOperation() {
return new Tuple<long, long>(_SuccessReply, _FailReply);
}
public bool LongPingSuccess() {
int ret = 0;
for (int i = 0; i < 5; i++) {
var r = replys.PeekLast(i);
if (r.Status == IPStatus.Success) ret++;
}
if (ret > 2) return true;
return false;
}
}

Categories

Resources