PhotonView.RPC not called under PhotonNetwork.LocalPlayer.IsMasterClient - c#

I'd like to make the master client execute the news updates code, and other clients receive the updates message from the master client, but I met a weird problem when I put PhotonView.RPC() within if (!PhotonNetwork.LocalPlayer.IsMasterClient)
This is the news updates code executed only by the master client:
if (PhotonNetwork.LocalPlayer.IsMasterClient)
{
if (currentItem < news.newsList.Count)
{
timeGap = TimeManager.globalSec - pubTime;
if (timeGap >= 2)
{
pubTime = TimeManager.globalSec;
if (page[currentPage].Count < 4)
{
page[currentPage].Add(news.newsList[currentItem]);
hlTitle.GetComponent<TextMeshProUGUI>().text = news.newsList[currentItem].newsTitle;
hlContent.GetComponent<TextMeshProUGUI>().text = news.newsList[currentItem].newsContent;
if (currentPage == 0)
{
for (int i = 0; i < page[currentPage].Count; i++)
{
newsItems[i].GetComponent<TextMeshProUGUI>().text = page[currentPage][i].newsTitle;
}
}
currentItem++;
}
else
{
page.Add(new List<NewsIndex>());
pageSum++;
}
}
NewsCount(currentItem, pageSum);
print(itemSum);
print(pageSum)
}
}
Code in Punrpc:
[PunRPC]
void NewsCount(int newsNum, int pageNum)
{
itemSum = newsNum;
pageSum = pageNum;
}
Other clients receive message from master client:
if (!PhotonNetwork.LocalPlayer.IsMasterClient) {
view.RPC("NewsCount", RpcTarget.All, itemSum, pageSum);
print(itemSum);
print(pageSum);
}
Now the problem is that it can print out numbers but is constantly 0 and 1, which means the view.RPC() doesn't work at all.
Console log in master client
Console log in other clients

to be honest I'm a bit confused. You say
Other clients receive message from master client
but no! In your code all the non-master clients are sending an RPC, not receiving.
And on the other hand I don't see the master client sending anything, he is rather directly calling NewsCount which makes this method be executed only locally for the master client but not actually send as an RPC to other clients!
So what happens is that all your non-master clients send their own 0 and 1 to everyone else since they never actually calculate these they never change. It doesn't affect the master client since he always calculates and prints his own values.
I can only guess but if I understanding you correctly you actually rather want to send the calculated values from the master client to everyone else.
So I think what you rather wanted to do is
...
if (PhotonNetwork.LocalPlayer.IsMasterClient)
{
if (currentItem < news.newsList.Count)
{
......
view.RPC(namof(NewsCount), RpcTarget.AllBuffered, currentItem, pageSum);
}
}
...
[PunRPC]
void NewsCount(int newsNum, int pageNum)
{
itemSum = newsNum;
pageSum = pageNum;
print($"new {nameof(itemSum)}={itemSum}");
print($"new {nameof(pageSum)}={pageSum}");
}

Related

How to properly recycle my TCP port using HttpListener c#

Per the comments, and my own testing, I am certain that my initial TCP port is not clearing out, and I don't really know how to remedy it.
I tried to run through the prefixes like so within my refresh method:
foreach (string item in myWebListener.Prefixes) {
if (item.Contains("http://127.0.0.1:5000")) {
myWebListener.Prefixes.Remove(item);
}
}
This did not make any noticeable change in the behavior.
The only other thing that was popping up in the web logs was something about the favicon.ico file, and just maybe another browser thread is trapping my connection trying to retrieve this and was going to provide it as an async callback to finish things out, though I didn't provide it so this line of thinking makes sense to me (How to provide a favicon.ico file in my byte stream as an embedded resource is My next research project).
If this shows no changes, my next research project is trying to leverage TCPListener:
I ran across this Q/A, but it really didn't help me as I am not familiar with the TCP way of doing what I have done here, and the work-around looks similar to what I was already attempting in my original code.
There was a mention of a using statement in the linked Q/A, and my guess is that it would look something like:
using(TCPListener myTCPListener = new TCPListener()) {
//Set the necessary TCP statements here.
//Do what I already did with my existing code here.
}
That's as far as my brain can take me so far, does this sound far off based on the factors at play here?
BELOW WAS THE ORIGINAL QUESTION CONTENT:
I am successfully reaching my running C# HttpListener localhost server, and successfully sending information back out to the local requesting browser page.
But after the first time, I completely lock up the browser web page waiting for a new response.
I debug with no errors on VS, so I don't even know where to look next; Hence that's why I'm here.
My hope is, is that someone can shed some light on how to refresh my server internally, so when the new query is needed, I can respond to it just like it was the first time.
I'm using an http get method to call this, so the call would look similar to the following:
"http://127.0.0.1:5000/?param1=searchForThings&param2=itemToSearchFor";
I have to rip out a lot of proprietary code, but here is what is happening:
public class myWebServer {
public myWebServer() {
refresh();
//The Global is being set When the API
// Loads & is referenced here
ev1 = _MyGlobalEvents.ev1
}
public static HttpListener myWebListener { get; set; }
public static HttpListenerContext context { get; set; }
public static AsyncCallback myGetCallback { get; set; }
public static HttpResponseMessage myResp { get; set; }
public static Stream output { get; set; }
public static MyAPIDefinedEventType ev1 { get; set; }
public static void refresh() {
if (myWebListener != null) {
myWebListener.Stop();
myWebListener.Close();
}
if (output != null) { output.Dispose(); }
if (myGetCallback != null) { myGetCallback = null; }
myWebListener = new HttpListener();
myGetCallback = new AsyncCallback(processRequest);
myWebListener.Prefixes.Add("http://127.0.0.1:5000/");
myWebListener.Start();
myResp = new HttpResponseMessage(HttpStatusCode.Created);
myWebListener.BeginGetContext(myGetCallback, myResp);
}
public static void processRequest(IAsyncResult result) {
context = myWebListener.EndGetContext(result);
context.Response.KeepAlive = true;
myResp = new HttpResponseMessage(HttpStatusCode.Accepted);
context.Response.StatusCode = (int)HttpStatusCode.Accepted;
output = context.Response.OutputStream;
string label = context.Request.QueryString["param1"];
string fiStr = context.Request.QueryString["param2"];
if (label != null || label != "" || label.Contains("\n") == false) {
int pass1 = 0;
int pass2 = 0;
try {
int myInt = label.ToCharArray().Length;
pass1 = 1;
} catch { }
if (pass1 > 0) {
try {
int myInt2 = fiStr.ToCharArray().Length;
pass2 = 1;
} catch { }
}
if ((pass1 == 1 && pass2 == 0) || (pass1 == 1 && pass2 == 1)) {
pass1 = 0;
pass2 = 0;
if (label == "searchForThings" && (fiStr != null && fiStr != "")) {
string respStr = "<html><body><div id=\"status_msg\" style=\"display:inline;\">" + fiStr + "</div></body></html>";
byte[] respBuffer = Encoding.ASCII.GetBytes(respStr);
context.Response.StatusCode = (int)HttpStatusCode.Accepted;
output.Write(respBuffer, 0, respBuffer.Length);
_MyGlobalEvents.searchStr = fiStr;
ev1.Raise();
}
}
}
}
//When the Custom Event is done processing it runs something like the
//following to clean up and finalize
public void _processSearch(string resultStr) { processSearch(resultStr); }
public static void processSearch(string resultStr) {
string respStr = "<html><head>" +
"<style type=\"text/css\">" +
"tr.dispRow{ display:table-row; }\n" +
"tr.noRow{ display:none; }" +
"</style>" +
"</head>" +
"<body>" +
resultStr +
"</body></html>";
byte[] respBuffer = Encoding.ASCII.GetBytes(respStr);
output.Flush();
context.Response.StatusCode = (int)HttpStatusCode.OK;
output.Write(respBuffer, 0, respBuffer.Length);
output.Close();
context.Response.KeepAlive = false;
context.Response.Close();
refresh();
}
}
public static class _MyGlobalEvents {
public static string searchStr { get; set; }
public static MyAPIDefinedEventType ev1 { get; set; }
}
"But after the first time, I completely lock up the browser web page waiting for a new response" - are you saying the error is seen on the browser sending an Http request but getting no response ?
I'd advise downloading and using Telerik Fiddler (free) to see whats actually being sent and received between the client and server.
As other respondees have said - this is not a normal pattern for HttpListener and I'd guess you are having problems with TCP port caching on the server, and your .Stop() and .Close() methods are not freeing the TCP port (Windows caches it)
My particular problem was actually the favicon.ico file request from the browser locking up the connection.
Early on I was noticing that my server was being hit twice, and that is why I had my flags in place to make certain that I was only operating on what was the actual Get request based on the URL I was expecting...
Otherwise the URL was erroring as a blank string (turns out this was the favicon.ico request being made - irritating, because when the string is completely empty you have no idea how to troubleshoot it). So I was ignoring it and not touching what I didn't understand.
Well it turns I could NOT ignore this request, because the browser is expecting a response for it. All I had to do was put an else section in my code that executed if my flag options weren't met, and close, dispose and refresh the connection when this happened.
This Q/A really described the solidified solution to the problem fairly well, but my Exception.Message was blank which didn't really get addressed there either, so I'm glad I get to document it here in the hopes that anyone else who may ever run into the same problem finds the answer a little more strait forward.
As for the answer that PhillipH provided, this proved to be the most helpful to me, as it revealed to me that I needed to be checking what was happening from the network traffic eventing.
However I could not really use the tools that this user suggested, but found an alternative with Google Chrome's built in chrome://net-internals/. Just type that into your address bar in chrome and execute it.
Anyway way this was the total answer for me, but PhillipH you deserve it for moving me in the right direction.

How to validate the message that is receive in socket in C#

First 4 characters represent the length of message.
I want to validate by getting first 4 bit of the received message to find its length and verify whether it matches with the first 4 bit.
For example
First four bit give me 45 and message length is 49 then this is true (45 body + first 4 bit length)
else first four bit give 45 but message length 35 . drop this message. This where the problem is.
Class:
internal static void BeginReceive(this Client client)
{
client.outBuffer.Clear();
client.KindOfMessage = KindMessage.Unknown;
client.MessageLength = int.MaxValue;
using (client.mreBeginReceive = new ManualResetEvent(false))
{
try
{
while (!client.closed)
{
client.mreBeginReceive.Reset();
client.socket.BeginReceive(client.socketBuffer, 0, Const.BufferSize, SocketFlags.None, EndReceive, client);
client.mreInit.SetIfNotNull();
client.mreBeginReceive.WaitOne();
client.mreIsConnected.WaitOne();
}
}
catch (Exception e)
{
client.HandleError(e);
}
}
}
private static void EndReceive(IAsyncResult result)
{
var client = (Client)result.AsyncState;
if (client.closed)
{
return;
}
try
{
var receive = client.socket.EndReceive(result);
if (receive == 0)
{
client.Disconnect();
return;
}
client.ProcessNewData(receive);
}
catch (Exception e)
{
client.HandleError(e);
}
client.mreBeginReceive.SetIfNotNull();
}
internal static void ProcessNewData(this Client client, int receive)
{
lock (client.outBuffer)
{
client.outBuffer.AddRange(client.socketBuffer.Take(receive));
do
{
client.EnvelopeRead();
if (client.outBuffer.Count >= client.MessageLength)
{
var msg = client.outBuffer.GetRange(0, client.MessageLength).ToArray();
client.outBuffer.RemoveRange(0, client.MessageLength);
client.RaiseMessageReceived(msg, client.KindOfMessage);
client.KindOfMessage = KindMessage.Unknown;
client.MessageLength = client.outBuffer.Count >= Const.TotalSizeOfEnvelope ? 0 : int.MaxValue;
}
} while (client.outBuffer.Count >= client.MessageLength);
}
}
and process data as following
internal static void ProcessNewData(this Client client, int receive)
{
lock (client.outBuffer)
{
client.outBuffer.AddRange(client.socketBuffer.Take(receive));
do
{
client.EnvelopeRead();
if (client.outBuffer.Count >= client.MessageLength)
{
var msg = client.outBuffer.GetRange(0, client.MessageLength).ToArray();
client.outBuffer.RemoveRange(0, client.MessageLength);
client.RaiseMessageReceived(msg, client.KindOfMessage);
client.KindOfMessage = KindMessage.Unknown;
client.MessageLength = client.outBuffer.Count >= Const.TotalSizeOfEnvelope ? 0 : int.MaxValue;
}
} while (client.outBuffer.Count >= client.MessageLength);
}
**i change it as **
internal static void ProcessNewData(this Client client, int receive)
{
lock (client.outBuffer)
{
client.outBuffer.AddRange(client.socketBuffer.Take(receive));
List<Byte> a = new List<byte>();
a.AddRange(client.socketBuffer.Take(receive));
totmsglen2 = ((int.Parse(a.GetRange(0, 2)[0].ToString()) * 256) + int.Parse(a.GetRange(0, 2)[1].ToString()) + 2);
if (a.Count != totmsglen2)
{
// this is not valid messge discared it
a.RemoveRange(0,totmsglen2);
}
else
{// valid message process it
client.outBuffer.AddRange(a.GetRange(0,totmsglen2));
a.RemoveRange(0,totmsglen2);
}
do
{
client.EnvelopeRead();
if (client.outBuffer.Count >= client.MessageLength)
{
var msg = client.outBuffer.GetRange(0, client.MessageLength).ToArray();
client.outBuffer.RemoveRange(0, client.MessageLength);
client.RaiseMessageReceived(msg, client.KindOfMessage);
client.KindOfMessage = KindMessage.Unknown;
client.MessageLength = client.outBuffer.Count >= Const.TotalSizeOfEnvelope ? 0 : int.MaxValue;
}
} while (client.outBuffer.Count >= client.MessageLength);
}
}
The code works only for one message and not when continuous messages are received.
Cases:
0010aaaaaaaaa valid
0007asd invalid
0005iiiii valid
For example First four bit give me 45 and message length is 49 then this is true (45 body + first 4 bit length) else first four bit give 45 but message length 35 . drop this message.
The first 4 bytes are the "message length". There's no other way for a server to know when a message completes. So it's not possible to detect a mismatch.
it also not secure for examples if they send the length 500 and message is 200 long then it fail, in this situation
Your protocol will just be waiting for the completion of that message. This is not a failure; it is by design. For example, if a client sends a length of 500 and a message that is 500, but if the packets got broken up, your sever could get a length of 500 with a message that is 200... and then seconds later get the other 300 of the message. That's the way TCP/IP works.
However:
it also not secure
This is true. By following this simple approach, you allow two trivial denial-of-service attacks:
The client sends some huge message length, causing your server to allocate a huge buffer expecting some huge message.
The client only sends a partial message, causing your server to keep that buffer and socket allocated. A distributed attack can successfully consume a lot of your server resources.
To mitigate these attacks, you should do two things:
Have a reasonable maximum message size, and reject any client that tries to send a larger one.
Add an "idle timer" to each socket. Each time you receive data, reset the timer. When the timer goes off, kill the connection. Also, if the client is not sending enough data (i.e., the rate of data is too low for a period of time), then kill the connection.
A simple approach would be to make sure that the receiving logic only passes full messages back. Also you cannot assume that a full message (or even size info) is received always. So you would do something like:
Beginreceive(4 bytes length info) to start things off, then loop through EndReceive and new BeginReceives as long as the 4 bytes are not in.
Then BeginReceive(number of bytes expected) and again loop through EndReceive/BeginReceieve until you have all bytes in. That would be the moment to pass on the message to the decoding logic.

Redirect to a different aspx page and run the next code in background (.NET 4.5.2)

I am working on an ASP.NET Webform project (legacy code).On my button_click event i am sending sms message to all the datas populated in this.
var customerSMS = BusinessLayer.SMS.SmsSetup.GetAllCustomerSMS(OfficeId);
This takes around 15seconds to do all the computing and get the data(1000rows)
from the Db.And for each data it runs through the loop and does validation and
sends the sms and it does take time.I want to do this task in background and
redirect the user to the index page and the background process continues till it
gets out of the loop.I am new to this and still learning this beautiful
language C#.I did go through this amazing Asynchronous Programming async/await
and Multithreading approach and got hold of it only in simple WindowsForm
applications.Any reference/code snippet/best approach with a simple explanation for my case would be helpful.
My button click event code :
protected void ReturntoDashboard_Click(object sender, EventArgs e)
{
sms = Everest.Net.BusinessLayer.SMS.SmsSetup.GetSmsSetUp(OfficeId);
if (sms.EnableSmsData && sms.SmsCount > 0)
{
#region Loan Section
var smsLoan = Everest.Net.BusinessLayer.SMS.SmsSetup.GetLoanId(s.Sms_AccountNumber);
var loanId =
BusinessLayer.SMS.SmsSetup.GetLoanIdValue(s.Sms_AccountNumber);
var dateexceeded =
BusinessLayer.SMS.SmsSetup.IsDateExceeded(loanId);
if (smsLoan != null && dateexceeded == true)
{
foreach (Common.SMS.SMSSetup sm in smsLoan)
{
var smsClosingBalanceLoan = BusinessLayer.SMS.SmsSetup.GetAmountForLoanAlert( sm.LoanId,
BusinessLayer.Core.DateConversion
.GetCurrentServerDate()
.AddDays(sms.DaysbeforeLoanalerts).ToString());
if (smsClosingBalanceLoan != null)
{
if (smsClosingBalanceLoan.LoanAmountToPay > 0)
{
int smsSentAlertCount = sms.LoanAlertCount;
var logCount = BusinessLayer.SMS.SmsSetup.GetLoanSmsAlertSentCount(DateTime.Now.AddDays(-smsSentAlertCount).ToString("yyyy-MM-dd"), DateTime.Now.ToString("yyyy-MM-dd"), sm.LoanAccountNumber);
if (logCount < smsSentAlertCount)
{
smsLog = new Everest.Net.Common.SMS.SMSSetup();
finalMessage = "Dear Member, Your Loan accnt " + sm.LoanAccountNumber + " with Principal"+ "+" + "Int Amnt: Rs." + smsClosingBalanceLoan.LoanAmountToPay + " need to be payed.Thank You," + officeName.OfficeName;
smsLog.LogServiceType = "Loan";
smsLog.LogSmsType = s.Sms_SmsType;
smsLog.LogSmsMessage = finalMessage;
smsLog.LogCustomerId = s.CustomerId.ToString();
smsLog.LogAccountNumber = s.Sms_AccountNumber;
smsLog.LogAccountType = s.Sms_AccountType;
smsLog.LogSmsSentDate = BusinessLayer.Core.DateConversion.GetCurrentServerDate();
smsLog.LogSmsFailedDate = "";
smsLog.LogSentStatus = true;
smsLog.LogUserId = UserId;
smsLog.LogSmsFailedMessage = "";
try
{
var result = Everest.Net.BusinessLayer.SMS.smsParameters.SendSMS(sms.FromNum, sms.Token, sms.Url, cellNum, finalMessage);
}
catch (Exception ex)
{
smsLog.LogSmsFailedDate = System.DateTime.Now.ToString("MM/dd/yyyy HHmmss");
smsLog.LogSentStatus = false;
smsLog.LogSmsFailedMessage = ex.Message;
Everest.Net.BusinessLayer.SMS.SmsSetup.InsertSMSLog(smsLog);
}
sms = Everest.Net.BusinessLayer.SMS.SmsSetup.GetSmsSetUp(OfficeId);
sms.SmsCount = sms.SmsCount - 1;
Everest.Net.BusinessLayer.SMS.SmsSetup.UpdateSmsSetup(sms);
Everest.Net.BusinessLayer.SMS.SmsSetup.InsertSMSLog(smsLog);
}
}
}
}
}
}
}
}
catch (Exception ex)
The ideal solution would remove the responsibility of sending the SMS from the web application itself. Instead, the web application should create a database record containing the message and recipient addresses, and a separate background job (e.g. a Windows Service) should poll the database and send SMS messages when neeeded. This is the best solution in terms of fault tolerance and auditability, because there is a permanent record of the messaging job which can be resumed if the system fails.
That being said, maybe you don't want to go to all that trouble. If you feel strongly that you wish to send the SMS directly from the ASP.NET application, you will need to create a Task and queue it to run using QueueBackgroundWorkitem. You will need to refactor your code a bit.
Move all the logic for sending the SMS into a separate function that accepts all the information needed as parameters. For example,
static void SendSMS(string[] addresses, string messagetext)
{
//Put your SMS code here
}
When you need to call the function, queue it as a background item
HostingEnvironment.QueueBackgroundWorkItem(a => SendSMS(addresses, messageText));
If your worker task needs to access its own cancellation token (e.g. if it is supposed to loop until cancelled), it is passed as an argument to the lambda expression. So you could modify the prototype
static void SendSMS(string[] addresses, string messagetext, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
//Put your code here
}
}
and pass it thus:
HostingEnvironment.QueueBackgroundWorkItem(token => SendSMS(addresses, messageText, token));
Placing the task in the background queue ensures that ASP.NET keeps track of the thread, doesn't try to garbage collect it, and shuts it down properly when the application pool needs to shut down.
After queuing the background operation, your page can render is content per usual and conclude the HTTP response while the task continues to execute.

Misbehaving Service behviors

Basically I'm making a program to simulate a petrol station system.
My problem is that I'm trying to send a request through a WCF service such as this:
User Requests Pump to be activated ----> WCF SERVICE ----> Point of Sale
User starts pumping petrol<---- WCF SERVICE <---- Point of Sale Accepts
At the moment it works, but only sometimes.
This is how I try to get a response:
while(PumpserviceClient.getRequestedAcceptedStatusFromPos().Accepted == false)
{
PumpserviceClient.RequestPump(int.Parse(PumpID));
// needs to wait for pump to be activated
if (PumpserviceClient.getRequestedAcceptedStatusFromPos().Accepted == true /*&& PumpserviceClient.getRequestedAcceptedStatusFromPos().PumpNo == int.Parse(PumpID)*/)
{
MessageBox.Show(" The Pos has accepted your pump request");
// if its accepted you call
Customer.ActivatePump();
}
And these are the methods in the service:
bool Accepted= false;
bool Requested=false;
public void AcceptPump(int PumpNumber)
{
Accepted = true;
Requested = false;
int pumpnumber = PumpNumber;
PumpRequest.Accepted = Accepted;
PumpRequest.Requested = Requested;
}
public void RequestPump(int PumpNumber)
{
int pumpnumber = PumpNumber;
Requested = true;
Accepted = false;
PumpRequest.Accepted = Accepted;
PumpRequest.PumpNo = PumpNumber;
PumpRequest.Requested = Requested;
}
public void ResetRequest(int PumpNumber)
{
int pumpnumber = PumpNumber;
Requested = false;
Accepted = false;
PumpRequest.Accepted = Accepted;
PumpRequest.PumpNo = 0;
PumpRequest.Requested = Requested;
}
public Message getRequestedStatusFromPump()
{
return PumpRequest;
}
public Message getRequestedAcceptedStatusFromPos()
{
return PumpRequest;
}
}
and the point of sale system accepts the requests by:
if (Client.getRequestedStatusFromPump().Requested == true)
{
MessageBox.Show("Pump Number: "+Client.getRequestedStatusFromPump().PumpNo + " Is waiting to be accepted");
// need to press a button or something
Client.AcceptPump(Client.getRequestedStatusFromPump().PumpNo);
}
Code here http://www.pastebucket.com/8642
I read the code posted. You use the following attribute:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
This means your code will not multi-thread. But there is no guarantee multiple sessions won't make requests and "interrupt" each other's workflow.
For example:
Client A calls request pump
Client B calls reset pump
Client A reads... client A wonders why pump was reset.
Your code is written expecting the object to be by session. I'd suggest using this context mode and seeing if you have better luck.
The other option is to add session information to your model. I can't imagine why this would be useful. It certainly won't be easy.
The only way i found around this problem, without changing service behaviors was to create a new list
public void CreatePumpList()
{
WaitingPumps = new List<WaitingPumps>();
for (int i = 0; i < PumpLimit+1 ; i++)
{
WaitingPumps.Add(new WaitingPumps());
}
}
Then just use the pump Number as the index in this list so they don't get confused with each other.

IPGlobalProperties.GetIPGlobalProperties

I wrote a test app to get all active ports on my network. Did some searching and found this was the easiest way. So I tried it and it work just fine. I then wrote another socket app with a sever and client side. It's pretty basic, has a create sever, join server and refresh button to get the active servers. The only time this method gets called is when you press the refresh button. If I open up the application 3 or more times and create a server with connected clients by the 4th one this method starts giving me this (Unknown error (0xc0000001)) error. Any idea why this could happen? Funny thing is I never get this on the initial application, the one I opened first. I don't know if somehow it get's a lock on this or something.
The exception gets thrown at this line:
IPEndPoint[] endPoints = properties.GetActiveTcpListeners();
Here's the method, it returns an object of List for all ports within a min and max range.
public static List<UserLocalSettings> ShowActiveTcpListeners(int min, int max)
{
List<UserLocalSettings> res = new List<UserLocalSettings>();
try
{
IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] endPoints = properties.GetActiveTcpListeners();
foreach (IPEndPoint e in endPoints)
{
if (e.Port > (min - 1) && e.Port < (max + 1))
{
UserLocalSettings tmpClnt = new UserLocalSettings();
tmpClnt.player_ip = e.Address.ToString();
tmpClnt.player_port = e.Port;
tmpClnt.computer_name = Dns.GetHostEntry(e.Address).HostName;
res.Add(tmpClnt);
}
}
}
catch (Exception ex1)
{
}
return res;
}
Here's a screen print of the exception:

Categories