MultiClient TCP server in C# - c#

I've been developing a TCP server, and I require it to allow for the access of multiple clients at the same time.
I also require it to allow them to disconnect and reconnect whenever they wish and for whenever they send a TCP message for the logic to run behind it as well.
I have my basic code set up which allows for one user to be connected at once however, it doesn't allow for multiple clients.
Server Code - (First part, without logic)
IPAddress ipAd = IPAddress.Any;
TcpListener myList = new TcpListener(ipAd, 5001);
myList.Start();
Console.WriteLine("Waiting for a new connection");
Console.WriteLine("Last Connection From - " + client);
Console.Write("Stats - Errors: ");
Console.BackgroundColor = ConsoleColor.Red;
Console.Write(" " + Errors + " ");
Console.BackgroundColor = ConsoleColor.DarkCyan;
Console.WriteLine();
Console.WriteLine();
Console.Write(feed);
Socket s = myList.AcceptSocket();
client = Convert.ToString(s.RemoteEndPoint);
Console.Write(feed);
byte[] b = new byte[100];
int k = s.Receive(b);
Console.WriteLine("\n Message Recieved");
string msg = "";
for (int i = 0; i < k; i++)
{
msg = msg + Convert.ToChar(b[i]);
}
feed = feed + " \n " + msg;
There is also client code which, I'm not going to put in here because I don't believe it's needed. If you have any questions or improvements/modifications about the client just ask/tell me and I'll take a look.
I've been told there is ways of doing it through another thread but I haven't got a clue to how I would approach it.

Related

How to interconnect C# Socket with ESP8266 (Hardware TCP)

I am trying to create a GUI to an ESP8266 project that I have already developed. The boards are using the NodeMCU firmware, and I am loading programs on through the ESP8266 Arduino Core. I am using C# for my GUI program on Windows.
Here is my debug code for the ESP8266 (in Arduino):
#include <ESP8266WiFi.h>
String ConnectedMAC[8];
IPAddress ConnectedIP[8];
WiFiClient clientforcom;
void setup() {
WiFi.mode(WIFI_AP_STA);
Serial.begin(9600);
int f = WiFi.scanNetworks();
Serial.println("Scanning Networks");
delay(5000);
for (int n = 0; n < f; n++) {
Serial.println(WiFi.SSID(n));
}
WiFi.begin(ssid, passtring); //SSID and passtring are my home network credentials
delay(2000);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.print("The IP of this node is: ");
Serial.println(WiFi.localIP());
}
void loop() {
MACManagement();
WiFiServer serverforclient(WiFi.localIP(), 25565);
while (!serverforclient.hasClient()) { //this does not work with Socket or delay is too long
delay(50);
Serial.println("Waiting for client");
}
clientforcom = serverforclient.available();
while (clientforcom.available() <= 0) {
delay(50);
Serial.println("Waiting for response");
}
String response = clientforcom.readString();
if (response.startsWith("GetController")) {
Serial.println("Sending String");
clientforcom.println("Returned String");
}
}
void MACManagement() {
unsigned char number_client;
struct station_info *stat_info;
struct ip_addr *IPaddress;
IPAddress address;
int i = 0;
number_client = wifi_softap_get_station_num();
stat_info = wifi_softap_get_station_info();
Serial.print(" Total Connected Clients are = ");
Serial.println(number_client);
while (stat_info != NULL) {
IPaddress = &stat_info->ip;
address = IPaddress->addr;
Serial.print("client= ");
Serial.print(i);
Serial.print(" IP adress is = ");
Serial.print((address));
ConnectedIP[i] = address;
Serial.print(" with MAC adress is = ");
Serial.print(stat_info->bssid[0], HEX); Serial.print(" ");
Serial.print(stat_info->bssid[1], HEX); Serial.print(" ");
Serial.print(stat_info->bssid[2], HEX); Serial.print(" ");
Serial.print(stat_info->bssid[3], HEX); Serial.print(" ");
Serial.print(stat_info->bssid[4], HEX); Serial.print(" ");
Serial.print(stat_info->bssid[5], HEX); Serial.print(" ");
ConnectedMAC[i] = String(stat_info->bssid[0], HEX) + ":" + String(stat_info->bssid[1], HEX) + ":" + String(stat_info->bssid[2], HEX) + ":" + String(stat_info->bssid[3], HEX) + ":" + String(stat_info->bssid[4], HEX) + ":" + String(stat_info->bssid[5], HEX);
stat_info = STAILQ_NEXT(stat_info, next);
i++;
Serial.println();
}
}
and here is my network accessing code in C#:
void loadUI(){
enterIPLabel.Visible=false;
errorBox.Text="Connecting to Leader node";
tcpcom=new TcpClient(leadernode.ToString(),25565);
tcpcom.Connect(leadernode.ToString(),25565);
while(!tcpcom.Connected);
tcpcom.Client.Send(System.Text.Encoding.ASCII.GetBytes("GetController"));
errorBox.Text="Awaiting Node Response";
while(tcpcom.Available<=0); //hopefully this should stop this method from executing until the response is made
//FILL IN CODE FOR RETURN STATEMENT
tabController.Visible=true;
NodeMap.Visible=true;
}
However, when I reach the "Waiting for Client" section of the ESP8266 code and I run the C# program, entering the IP Address into leadernode. I get an error from .NET that states:
System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it
I have no idea why the ESP8266 would be refusing the connection, I put delays such that the Software Watch Dog would not initiate, so I don't understand why it would break the program.

C# monitor SNMP timeticks from multiple IP addresses

I'm attempting to monitor multiple SNMP agents (timeticks) with SnmpSharpNet across separate networks. The code below works with a single IP address, but when I try and connect to a second IP address the code fails, I'm trying to run this asynchronously but it appears that SnmpSharpNet won't allow me to receive data from more than one agent.
Is this the right way to approach this problem? Is there a better alternative to SmnpSharpNet?
community = new OctetString("public");
// Define agent parameters class
param = new AgentParameters(community);
// Set SNMP version to 1 (or 2)
param.Version = SnmpVersion.Ver1;
for (int i = 0; i < sendsqldatalist.Count(); i++)
{
agent = new IpAddress(sendsqldatalist[i].ip);
target = new UdpTarget((IPAddress)agent, 161, 2000, 1);
// Make SNMP request
resultlist.Add(result = (SnmpV1Packet)target.Request(pdu, param));
// If result is null then agent didn't reply or we couldn't parse the reply.r
if (resultlist[i] != null)
{
// ErrorStatus other then 0 is an error returned by
// the Agent - see SnmpConstants for error definitions
if (resultlist[i].Pdu.ErrorStatus != 0)
{
Console.WriteLine("error on - " + sendsqldatalist[i].oid + " " + sendsqldatalist[i].ip);
// agent reported an error with the request
//- Error status found here http://www.docs.snmpsharpnet.com/docs-0-9-1/
MessageBox.Show("Error in SNMP reply from " + target.Address.ToString() + Environment.NewLine + "Error status " + result.Pdu.ErrorStatus.GetType() + Environment.NewLine + "Error Index " + result.Pdu.ErrorIndex.ToString(), "WARNING!");
}
else
{
Console.WriteLine("ConnectSNMP() CONNECTED - " + sendsqldatalist[i].oid + " - " + sendsqldatalist[i].ip);
}
}
}
Thanks in advance!

C# TCP Client sends a message, but Server is not receiving the message [duplicate]

This question already has answers here:
Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on
(22 answers)
Closed 5 years ago.
This is the error :
**
Exception thrown: 'System.InvalidOperationException' in
System.Windows.Forms.dll Additional information: Cross-thread
operation not valid: Control 'displayText' accessed from a thread
other than the thread it was created on.
**
I was created multi threaded client and server application using on C#. I was researched about this error but I could not find any relevant answer. I know this is comes when two or more threads started on the program...But my server side has one thread...I don't know why this is comes..........
Here is my Server side:
private void Handler()
{
try {
byte[] b = new byte[100];
int k = s.Read(b, 0, b.Length);
//int k = s.Receive(b);
string szReceived = Encoding.ASCII.GetString(b,0,k);
//If the data to be converted is available only in sequential blocks (such as data read from a stream) or if the amount of data is so large that it needs to be divided into smaller blocks,
while (ServerRunning)
{
string ConcatString = "";
for (int i = 0; i < k; i++)
{
char n = Convert.ToChar(b[i]);
string chars = Convert.ToString(n);
ConcatString = ConcatString + chars;
}
if (b[0] == '$')
{
displayText.AppendText("\nPrivate Message");
//MessageBox.Show("\nPrivate Message" + Environment.NewLine);
}
else
{
displayText.AppendText("\n" + ConcatString);
//MessageBox.Show(ConcatString + Environment.NewLine);
}
//Encoding is the process of transforming a set of Unicode characters into a sequence of bytes and using new instance
ASCIIEncoding asen = new ASCIIEncoding();
//s.Send(asen.GetBytes("The string was recieved by the server." + Environment.NewLine));
displayText.AppendText("\n" + ConcatString);
/* clean up */
//*
// k = s.Receive(b);
s.Close();
client.Close();
//MessageBox.Show("Recieved..." + Environment.NewLine);
}
}
catch(Exception ex)
{
MessageBox.Show("Error ...." + ex);
}
}
I am new to Socket Programming, but I was researched each and every code segment and experimented the code in several times.. Still can't figure out what exactly I missed in this program...
So please help me to solve this...I will be appreciated very much...
Thanks..
Invoke((MethodInvoker) delegate { displayText.AppendText("\n" + ConcatString); });
should fix it; that dispatches the "append to the UI" code to the UI thread and waits for it to complete.

Pinging using ARP always return host offline

I'm trying to check if computer on the net is online by using code which supposedly to check it by using ARP packets.
I am always getting message that host is offline even when I'm sure that it's online. I have checked on my localhost IP and on some always working IPs such as google.
That could be wrong with this code?
[DllImport("iphlpapi.dll", ExactSpelling = true)]
public static extern int SendARP(IPAddress DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen);
private byte[] macAddr = new byte[6];
private uint macAddrLen;
private void Ping(IPAddress address)
{
if (SendARP(address, 0, new byte[6], ref macAddrLen) == 0)
{
open++;
txtDisplay.AppendText("Host " + address + " is open." + Environment.NewLine);
}
else
{
closed++;
txtDisplay.AppendText("Host " + address + " is closed." + Environment.NewLine);
}
}
By using previous code I'm basically trying to do something like following code. But the problem with this code is that when host is closed that it takes like 2 seconds to get the respond which I want to eliminate. Someone suggested to use ARP ping:
private void Ping(IPAddress address)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
if (cbDontFragment.Checked) options.DontFragment = true;
else options.DontFragment = false;
string dataa = string.Empty;
int dataCounter = 0;
options.Ttl = (int)nudTTL.Value;
for (int i = 0; i < nudData.Value; i++)
{
dataCounter++;
if (dataCounter == 10) dataCounter = 0;
dataa += dataCounter.ToString();
}
byte[] buffer = Encoding.ASCII.GetBytes(dataa);
int timeout = 120;
try
{
PingReply reply = pingSender.Send(address, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
open++;
txtDisplay.AppendText("Host " + address + " is open. ");
if (cbDontFragment.Checked) txtDisplay.AppendText(" Don't fragment. ");
txtDisplay.AppendText(" TTL: " + options.Ttl.ToString() + " ");
txtDisplay.AppendText(" Bytes: " + nudData.Value + " ");
txtDisplay.AppendText(Environment.NewLine);
}
else
{
closed++;
txtDisplay.AppendText("Host " + address + " is closed. ");
if (cbDontFragment.Checked) txtDisplay.AppendText(" Don't fragment. ");
txtDisplay.AppendText(" TTL: " + options.Ttl.ToString() + " ");
txtDisplay.AppendText(" Bytes: " + nudData.Value + " ");
txtDisplay.AppendText(Environment.NewLine);
}
}
catch (Exception ex)
{
txtDisplay.SelectedText += Environment.NewLine + ex.Message;
}
}
ARP cannot be used for what you are trying to do. It only works over a local network.
It's purpose is to resolve an IP address (which is routed) to a MAC address (which is not). It is never sent beyond a network segment (a lan)

Sending files from Client to Server

I am trying to send multiple files to a server ever 2 seconds and after the file is sent it is deleted and the program is restarted as to again generate the file which needs again to be sent to server.
But it works till the time the server is online...In case the sever is restarted all the program functions will work fine but when this function is invoked it keeps on displaying "No connection could be made because the target machine actively refused it" no matter even when the server comes online in between..
private void sendfile()
{
timer.Stop();
RegistryKey theLocalMachine = Registry.LocalMachine;
RegistryKey theSystem2 = theLocalMachine.OpenSubKey(#"SOFTWARE\\NetworkUsagemonitoring\\", true);
RegistryKey interfacekey4 = theSystem2.OpenSubKey("Usagerecorder", true);
string serverno = interfacekey4.GetValue("serverno").ToString();
for (int i = 0; i < netarr1.Length; i++)
{
for (int j = 0; j < netarr2.Length; j++)
{
if (netarr1[i].Name == netarr2[j])
{
if (recorded[j] == 1)
{
try
{
IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse(serverno), 5656);
Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
if (File.Exists(#"C:\" + netarr1[i].Name + "_record.xml"))
{
fileName = (#"C:\" + netarr1[i].Name + "_record.xml");
fileName = fileName.Replace("\\", "/");
while (fileName.IndexOf("/") > -1)
{
filePath += fileName.Substring(0, fileName.IndexOf("/") + 1);
fileName = fileName.Substring(fileName.IndexOf("/") + 1);
}
byte[] fileNameByte = Encoding.ASCII.GetBytes(fileName);
if (fileNameByte.Length > 850 * 1024)
{
return;
}
byte[] fileData = File.ReadAllBytes(filePath + fileName);
byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length];
byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length);
fileNameLen.CopyTo(clientData, 0);
fileNameByte.CopyTo(clientData, 4);
fileData.CopyTo(clientData, 4 + fileNameByte.Length);
clientSock.Connect(ipEnd);
clientSock.Send(clientData);
clientSock.Close();
recorded[j] = 0;
File.Delete(#"C:\" + netarr1[i].Name + "_record.xml");
}
else
{
UpdateNetwork_Interface();
}
}
catch (Exception ex)
{
LogEvent("No connection could be made because the target machine actively refused it", EventLogEntryType.Information);
break;
}
finally
{
j++;
}
}
else
{
UpdateNetwork_Interface();
}
}
}
}
}
What i want is of the server goes offline or "No connection could be made because the target machine actively refused it" is displayed...the program should continue with the loop and move unhindered until server comes online and the updated file will be sent to the server.
Well, you're exception handling is faulty. You are catching (Exception ex) and printing out the error message you quoted. It's entirely possible that the ACTUALL exception has to do with the files you are writing and erasing. perhaps some files failed to erase or be opened.
Looking at the code, i suspect the problem is that you're never actually closing the socket if there is an exception.
You should add the following to the finally clause.
if (clientSocket!=null)
clientSocket.Close();
And you should print out the actual exception message to the error log so you know what's really going on when an error occurs.

Categories