I'm trying to run a StreamSocketListener in a background task of a UWP app.
I followed below MS example and my EnableTransferOwnership call is exactly same as MS example.
https://learn.microsoft.com/en-us/windows/uwp/networking/network-communications-in-the-background#socket-broker-and-the-socketactivitytrigger
However I receive an exception
Exception thrown: 'System.InvalidOperationException' in
System.Private.CoreLib.dll WinRT information: A wildcard address
cannot be used with a specific port when the Wake standby action is
set. Try using BindEndpointAsync with a non-null localHostName.
Service name bind exeception: A method was called at an unexpected
time.
My question is why it cause this exception?
Could MS example source be wrong?
public async Task<bool> SocketInitListener(string socketPort, IBackgroundTaskRegistration backgroundRegistrationTask)
{
SocketPort = socketPort;
SocketLstener = new StreamSocketListener();
SocketLstener.EnableTransferOwnership(backgroundRegistrationTask.TaskId, SocketActivityConnectedStandbyAction.Wake);
SocketLstener.ConnectionReceived += OnConnection;
SocketLstener.Control.KeepAlive = false;
try
{
await SocketLstener.BindServiceNameAsync(SocketPort);
}
catch (Exception ex)
{
Debug.WriteLine("Service name bind exeception: " + ex.Message);
return false;
}
return true;
}
Also my app need to listen to this specific port and it does not know about client HostName.
So I don't think I can use BindEndpointAsync() in my case.
Appreciate any help!
Recently I had to build a small TCP client app, that connects to an external app's TCP listener and is intended to deal with large amount of data volumes and on high frequencies.
I made a wrapper class around the TCPClient class, just to catch exceptions, and keep reference to some properties of interest (network stream etc.). Here is the wrapper:
public class MyTCPClient
{
private string serverIP;
private int serverPort;
public TcpClient tcpClient = new TcpClient();
private IPEndPoint serverEndPoint;
private NetworkStream stream = null;
public string name;
public MyTCPClient(string serverIp, int serverPort, string parentName)
{
this.serverIP = serverIp;
this.serverPort = serverPort;
this.name = parentName + "_TCPClient";
serverEndPoint = new IPEndPoint(IPAddress.Parse(serverIP), serverPort);
tcpClient.ReceiveBufferSize = 1048576;
this.TryConnect();
}
private bool TryConnect()
{
try
{
tcpClient.Connect(serverEndPoint);
}
catch (SocketException e1)
{
throw new ErrorOnConnectingException(e1, "SocketException while connecting. (see msdn Remarks section for more details. ) Error code: " + e1.ErrorCode);
}
catch (ArgumentNullException e2)
{
throw new ErrorOnConnectingException(e2, "ArgumentNullException while connecting. (The hostname parameter is null.) Message: " + e2.Message);
}
catch (ArgumentOutOfRangeException e3)
{
throw new ErrorOnConnectingException(e3, "ArgumentOutOfRangeException while connecting (The port parameter is not between MinPort and MaxPort. ). Message: " + e3.Message);
}
catch (ObjectDisposedException e4)
{
throw new ErrorOnConnectingException(e4, "ObjectDisposedException while connecting. (TcpClient is closed. ) Message: " + e4.Message);
}
try
{
stream = this.tcpClient.GetStream();
}
catch (ObjectDisposedException e1)
{
throw new ErrorOnGettingStreamException(e1, "ObjectDisposedException while acquiring Network stream. (The TcpClient has been closed. ) Message: " + e1.Message);
}
catch (InvalidOperationException e2)
{
throw new ErrorOnGettingStreamException(e2, "ArgumentOutOfRangeException while acquiring Network stream (The TcpClient is not connected to a remote host. ). Message: " + e2.Message);
}
return true;
}
public string ReadData()
{
try
{
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] dataHeader = new byte[12];
if (this.tcpClient.Connected)
{
stream.Read(dataHeader, 0, 12);
}
else
{
throw new ErrorOnReadingException(null, "The underlying TCP tcpClient is not connected any more");
}
var strHeaderMessage = System.Text.Encoding.Default.GetString(dataHeader);
Utils.logToTimeStampedFile(strHeaderMessage, name);
int bodyAndTailCount = Convert.ToInt32(strHeaderMessage.Replace("#", ""));
byte[] dataBodyAndTail = new byte[bodyAndTailCount];
if (this.tcpClient.Connected)
{
stream.Read(dataBodyAndTail, 0, bodyAndTailCount);
}
else
{
throw new ErrorOnReadingException(null, "The underlying TCP tcpClient is not connected any more");
}
var strBodyAndTailMessage = System.Text.Encoding.Default.GetString(dataBodyAndTail);
Utils.logToTimeStampedFile(strBodyAndTailMessage, name);
return strBodyAndTailMessage;
}
catch (FormatException e0)
{
CloseAllLeft();
throw new ErrorOnReadingException(e0, "FormatException while reading data. (Bytes red are null or does not correspond to specification, happens on closing Server) Message: " + e0.Message);
}
catch (ArgumentNullException e1)
{
CloseAllLeft();
throw new ErrorOnReadingException(e1, "ArgumentNullException while reading data. (The buffer parameter is null.) Message: " + e1.Message);
}
catch (ArgumentOutOfRangeException e2)
{
CloseAllLeft();
throw new ErrorOnReadingException(e2, "ArgumentOutOfRangeException while reading data. (see msdn description) Message: " + e2.Message);
}
catch (IOException e3)
{
CloseAllLeft();
throw new ErrorOnReadingException(e3, "IOException while reading data. (The underlying Socket is closed.) Message: " + e3.Message);
}
catch (ObjectDisposedException e4)
{
CloseAllLeft();
throw new ErrorOnReadingException(e4, "ArgumentOutOfRangeException while reading data. (see msdn description) Message: " + e4.Message);
}
}
public void CloseAllLeft()
{
try
{
stream.Close();
}
catch (Exception e)
{
Console.WriteLine("Exception closing tcp network stream: " + e.Message);
}
try
{
tcpClient.Close();
}
catch (Exception e)
{
Console.WriteLine("Exception closing tcpClient: " + e.Message);
}
}
}
Still, nothing mentioned about the threads using this MyTCPClient. The app should have two such TCP clients, connecting on different ports, and doing different jobs. I was new to TCP programming and after some wandering around the properties I decided to use the blocking read approach - i.e by default the TCPClient.Read() method will block the thread until there is new data. I needed such approach bucause I do not have control on the external app's listener, and the only way to recognize a server's closing was the "zero bytes" sent as per TCP Sockets specs.
So, i build an abstract class that will maintain and control threads that will later make use of the above MyTCPClient class (which by design, eventually might block the parent theads). Here is the code for my abstract TCPManager:
/// <summary>
/// Serves as a dispatcher for the high frequency readings from the TCP pipe.
/// Each time the thread is started it initializes new TCPClients which will attempt to connect to server.
/// Once established a TCP socket connection is alive until the thread is not requested to stop.
///
/// Error hanling level here:
///
/// Resources lke NetworkStream and TCPClients are ensured to be closed already within the myTCPClient class, and the error handling here
/// is steps on top of that - sending proper emails, notifications and logging.
///
/// </summary>
public abstract class AbstractmyTCPClientManager
{
public string name;
public string serverIP;
public int serverPort;
public Boolean requestStop = false;
public Boolean MyTCPClientThreadRunning = false;
public Boolean requestStart = false;
public myTCPClient myTCPClient;
public int sleepInterval;
public Thread MyTCPClientThread;
public AbstractmyTCPClientManager(string name, string serverIP, int serverPort)
{
this.name = name;
this.serverIP = serverIP;
this.serverPort = serverPort;
}
public void ThreadRun()
{
MyTCPClientThreadRunning = false;
bool TCPSocketConnected = false;
bool AdditionalInitializationOK = false;
// keep trying to init requested tcp clients
while (!MyTCPClientThreadRunning && !requestStop) // and we are not suggested to stop
{
while (!TCPSocketConnected && !requestStop) // and we are not suggested to stop)
{
try
{
myTCPClient = new myTCPClient(serverIP, serverPort, name);
TCPSocketConnected = true;
}
catch (ErrorOnConnectingException e0)
{
// nah, too long message
string detail = e0.originalException != null ? e0.originalException.Message : "No inner exception";
//Utils.logToTimeStampedFile("Creating connection attempt failed.(1." + e0.customMessage + " 2." + detail + "). Will retry in 10 seconds...", name);
//Utils.logToTimeStampedFile(e0.customMessage + " (" + detail + "). Will retry in 10 seconds...", name);
Utils.logToTimeStampedFile(detail + ". Will retry in 10 seconds...", name);
Thread.Sleep(10000);
}
catch (ErrorOnGettingStreamException e1)
{
// nah, too long message
string detail = e1.originalException != null ? e1.originalException.Message : "No inner exception";
//Utils.logToTimeStampedFile("Getting network stream attempt failed. (1." + e1.customMessage + " 2." + detail + "). Will retry in 10 seconds...", name);
//Utils.logToTimeStampedFile(e1.customMessage + " (" + detail + "). Will retry in 10 seconds...", name);
Utils.logToTimeStampedFile(detail + ". Will retry in 10 seconds...", name);
Thread.Sleep(10000);
}
}
Utils.logToTimeStampedFile("TCP Communication established", name);
while (!AdditionalInitializationOK && !requestStop) // or we are not suggested to stop
{
try
{
AdditionalInitialization();
AdditionalInitializationOK = true;
}
catch (AdditionalInitializationException e1)
{
string detail = e1.originalException != null ? e1.originalException.Message : "No inner exception";
//Utils.logToTimeStampedFile("Additional initialization failed (1." + e1.customMessage + " 2." + detail + "). Will retry in 10 seconds", name);
Utils.logToTimeStampedFile(e1.customMessage + ". Will retry in 10 seconds", name);
Thread.Sleep(10000);
}
}
MyTCPClientThreadRunning = TCPSocketConnected && AdditionalInitializationOK;
ViewModelLocator.ControlTabStatic.updateUIButtons();
}
Utils.logToTimeStampedFile("Additional Initialization successfully completed, thread started", name);
// while all normal (i.e nobody request a stop) continiously sync with server (read data)
while (!requestStop)
{
try
{
syncWithInterface();
}
catch (ErrorOnReadingException e1)
{
string detail = e1.originalException != null ? e1.originalException.Message : "No inner exception";
//Utils.logToTimeStampedFile("Error ocured while reading data. (1." + e1.customMessage + " 2." + detail + ")", name);
Utils.logToTimeStampedFile(e1.customMessage, name);
if (!requestStop) // i.e if this indeed is an exception, during a normal flow, and nobody requested a thread stop (which migh cause read exceptions as a consequence)
{
Utils.logToTimeStampedFile("There was no external stop request, when the error occured, doing tcp client restart.", name);
requestStop = true;
requestStart = true;
}
}
Thread.Sleep(sleepInterval);
}
// we need to close all after execution, but the execution may be closed before/while resources were still initializing
if (TCPSocketConnected)
{
myTCPClient.CloseAllLeft();
}
if (AdditionalInitializationOK)
{
ReleaseAdditionalResources();
}
// remember that thread is stoped
MyTCPClientThreadRunning = false;
Utils.logToTimeStampedFile("Thread stoped", name);
ViewModelLocator.ControlTabStatic.updateUIButtons();
// this serves as a restart
if (requestStart)
{
Utils.logToTimeStampedFile("Restarting thread...", name);
this.requestStop = false;
this.requestStart = false; // we are already processing a request start event, so reset this flag
this.MyTCPClientThread = new Thread(new ThreadStart(this.ThreadRun));
this.MyTCPClientThread.Name = this.name;
this.MyTCPClientThread.IsBackground = true;
this.MyTCPClientThread.Start();
}
}
/// <summary>
/// this method empties the entire TCP buffer, cycling through it
/// </summary>
private void syncWithInterface()
{
int counter = 0;
// read at most 100 messages at once (we assume that for 3 sec interval there might not be more,
//even if they are, it is still OK, they just will be processed next time)
while (counter < 100)
{
counter++;
string data = myTCPClient.ReadData();
ForwardData(data);
}
// below is left for testing:
/*
* "Sleep(0) or Yield is occasionally useful in production code for
* advanced performance tweaks. It’s also an excellent diagnostic tool
* for helping to uncover thread safety issues: if inserting Thread.Yield()
* anywhere in your code makes or breaks the program, you almost certainly have a bug."*/
Thread.Yield();
}
/// <summary>
/// Left for implementing in the caller that initialized the object. Meaning: one and the same way for receiving market/order data. Different ways of processing this data
/// </summary>
/// <param name="data"></param>
public abstract void ForwardData(string data);
/// <summary>
/// left for implementing in child classes. Its purpose is to initialize any additional resources needed for the thread to operate.
/// If something goes wrong while getting this additional resources,
/// an AdditionalInitialization exception should be thrown, which is than handled from the initialization phase in the caller.
/// </summary>
public abstract void AdditionalInitialization();
// countrapart of AdditionalInitialization method - what is initialized should be then closed
public abstract void ReleaseAdditionalResources();
}
Later, each needed TCP communication channel would have a dedicated implementation for the above abstract class, providing implementation of the methods ForwardData (i.e what to do with this data) and AdditionalInitialization (i.e what else is needed to be initialized before a particular TCP communication processing is run. For example on of my threads required additional storage Thread to be initialized prior receiving data).
Everything was fine, except for closing the TCP processing. I had this requestStop variables to control whther a thread should exit or continue, but the thing is that Read() method may fall in continious blocking, preventing even the requestStop variable from being read (I should say that the two tcp channels I need to process are very different in that one of them is very frequently receiving data and the other one - sporadically). I would like still to have them implementing the same design. So from what I am reading so far I have to implement another, "parent", or "controlling", or "wrapper" thread that will actually take the job on observing requestStop parameter.
I am looking towards solutions like this post, or timers like this post
Any suggestions would be greatly appreciated. Thanks!
I would personally use asynchronous sockets for this:
http://msdn.microsoft.com/en-us/library/bbx2eya8.aspx
If you, however, still want to use blocking reads, you one could simply be to Close() the socket from another thread.
I hope this help.
I would recommend calling the ReadAsync method of NetworkStream and passing a CancellationToken to it. This way, the read operation can be easily cancelled (from another thread) when a request stop event is observed:
public class MyTCPClient : IDisposable
{
...
private CancellationTokenSource cancellationTokenSource = new CancellationTokenSource ();
...
public string ReadData()
{
...
byte[] dataHeader = new byte[12];
if (this.tcpClient.Connected)
{
stream.ReadAsync(dataHeader, 0, 12, cancellationTokenSource.Token).Wait();
} ...
Set your 'requestStop' bool and Close the client socket from another thread. This causes the read() call to return 'early' with an error/exception. The client thread can check 'requestStop' after every read() return and clean up/exit if requested.
TBH, I rarely bother with explicitly shutting down such clients anyway. I just leave them until the app exits.
I have the following .NET code. Most of it was written long before I was hired, and none of the original devs still work for us.
private void SendTCPMessage(string IpAddress, string Message)
{
...
//original code that fails because the Host entry produced
//has no elements in AddressList.
//IPHostEntry remoteMachineInfo = Dns.GetHostEntry(IpAddress);
//New code that fails when connecting
IPHostEntry remoteMachineInfo;
try
{
remoteMachineInfo = Dns.GetHostEntry(IpAddress);
if (remoteMachineInfo.AddressList.Length == 0)
remoteMachineInfo.AddressList =
new[]
{
new IPAddress(
//Parse the string into the byte array needed by the constructor;
//I double-checked that the correct address is produced
IpAddress.Split('.')
.Select(s => byte.Parse(s))
.ToArray())
};
}
catch (Exception)
{
//caught and displayed in a status textbox
throw new Exception(String.Format("Could not resolve or parse remote host {0} into valid IP address", IpAddress));
}
socketClient.Connect(remoteMachineInfo, 12345, ProtocolType.Tcp);
...
}
The SocketClient code of note is as follows:
public void Connect(IPHostEntry serverHostEntry, int serverPort, ProtocolType socketProtocol)
{
//this line was causing the original error;
//now AddressList always has at least one element.
m_serverAddress = serverHostEntry.AddressList[0];
m_serverPort = serverPort;
m_socketProtocol = socketProtocol;
Connect();
}
...
public void Connect()
{
try
{
Disconnect();
SocketConnect();
}
catch (Exception exception) ...
}
...
private void SocketConnect()
{
try
{
if (SetupLocalSocket())
{
IPEndPoint serverEndpoint = new IPEndPoint(m_serverAddress, m_serverPort);
//This line is the new point of failure
socket.Connect(serverEndpoint);
...
}
else
{
throw new Exception("Could not connect!");
}
}
...
catch (SocketException se)
{
throw new Exception(se.Message);
}
...
}
...
private bool SetupLocalSocket()
{
bool return_value = false;
try
{
IPEndPoint myEndpoint = new IPEndPoint(m_localAddress, 0);
socket = new Socket(myEndpoint.Address.AddressFamily, SocketType.Stream, m_socketProtocol);
return_value = true;
}
catch (SocketException)
{
return_value = false;
}
catch (Exception)
{
return_value = false;
}
return return_value;
}
When connecting to the endpoint within SocketConnect, I get a SocketException stating:
The system detected an invalid pointer address in attempting to use a pointer argument in a call.
Information online is a bit light on how to fix this. AFAICT, the address is parsing properly, and it's retrieved properly once passed in to the SocketClient class. Honestly, I don't know if this code has ever worked; I have never personally seen it do what it's supposed to, and the functionality that uses all this was created for the benefit of a single client of ours, and has apparently not been functional since before I was hired.
I need to know what to look for to resolve the error. If it helps, the remote computer to which I am trying to establish a connection is on the remote side of a VPN tunnel, and we do have connectivity via other pieces of software we use.
Help?
Found it. The address used as the local endpoint for the socket, in SetupLocalSocket(), used a similarly naive method of getting the address; by resolving the local host and getting the first address. That first address, more often than not, is an IPv6 address, not the IPv4 address that was obviously expected. So, I had it look for the first IPv4 address in the list and use that as the endpoint, and it worked.
I make an application in android can send character code to server C# when user input on android keyboard.
This is send method in android side:
public Boolean writeMessage(String message) {
try {
printWriter = new PrintWriter(socket.getOutputStream(), true);
printWriter.println(message);
return true;
} catch (Exception ex) {
Log.e(TAG,"write error: " +ex.getMessage());
return false;
}
}
And server listen the messages (C#):
Thread myThread = new Thread(new ThreadStart(ServeClient));
myThread.Start();
void ServeClient(){
StreamReader reader = new StreamReader(tcpClient.GetStream());
while (true)
{
try
{
String message = reader.ReadLine();
if (message != null)
{
Console.WriteLine(message);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
My code works, but when user input faster, the server delay read message in 1,2 or 3 seconds (I have test the method get character when user input, it works fine, not delay). Where is my problem? Thanks in advance!
Your problem may be caused by Nagle's algorithm reducing TCP traffic. Consider setting TCP_NODELAY on your client (and server - TcpClient.Client.NoDelay - if communication is two-way).
Edit: For java it is Socket.setTcpNoDelay method.
This is only the important stuff that the bluescreen shows. I'm on Windows 7 x64.
"A problem has been detected and Windows has been shut down to prevent damage
to your computer.
PROCESS_HAS_LOCKED_PAGES
* STOP: 0x00000076 (0x0000000000000000, 0xfffffa8009dcd060, 0x0000000000000011,
0x0000000000000000)"
I can't work on it now because every time I close it I get a bluescreen!
The program doesn't do anything yet except run the background worker below. It pings all addresses that could be part of the user's home network and attempts to connect to a certain port that another program will be listening on.
private void NetworkScanner_DoWork(object sender, DoWorkEventArgs e)
{
bool ExceptionEncountered = false;
int IPsProcessed = 0;
NetworkSearcherOutput = "Starting network scanner...";
NetworkSearcher.ReportProgress(0);
Thread.Sleep(1000);
foreach (IPAddress IP in Dns.GetHostAddresses(Dns.GetHostName()))
{
if (IP.AddressFamily == AddressFamily.InterNetwork)
{
string[] Octets = IP.ToString().Split('.');
Octets[3] = "0";
IPAddress CurrentAddressIteration = StringArrayToIP(Octets);
while (GetLastOctet(CurrentAddressIteration) != 255)
{
PingReply Reply = new Ping().Send(CurrentAddressIteration, 5);
if (Reply.Status == IPStatus.Success)
{
NetworkSearcherOutput = CurrentAddressIteration.ToString() + " sent response.";
NetworkSearcher.ReportProgress(0);
Thread.Sleep(500);
InClient Client = new InClient(CurrentAddressIteration);
try
{
Client.Connect();
SnapshotBox.Image = Client.Receive(typeof(Image));
NetworkSearcherOutput = CurrentAddressIteration.ToString() + " is running program.";
NetworkSearcher.ReportProgress(0);
Thread.Sleep(1000);
}
catch (Exception E)
{
// A socket exception is expected when the client is not running the program.
if (E is SocketException)
{
Client.Close();
NetworkSearcherOutput = CurrentAddressIteration.ToString() + " is not running program.";
NetworkSearcher.ReportProgress(0);
Thread.Sleep(1000);
}
//Unhandled exception. Show messagebox and close.
else
{
MessageBox.Show("Network scanner encountered an unhandled exception.\n\n" + E.GetType().ToString() + ": " + E.Message, "Unhandled Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
ExceptionEncountered = true;
break;
}
}
}
else
{
NetworkSearcherOutput = CurrentAddressIteration.ToString() + " did not respond.";
NetworkSearcher.ReportProgress(0);
}
IPsProcessed++;
if (IPsProcessed == 5)
{
NetworkSearcher.ReportProgress(2);
IPsProcessed = 0;
}
Octets = CurrentAddressIteration.ToString().Split('.');
Octets[3] = (Int32.Parse(Octets[3]) + 1).ToString();
CurrentAddressIteration = StringArrayToIP(Octets);
}
}
}
if (!ExceptionEncountered)
{
NetworkSearcherOutput = "Network scanning complete.";
NetworkSearcher.ReportProgress(0);
NetworkSearcher.ReportProgress(100);
}
else
{
NetworkSearcherOutput = "Network scanning encountered an error.";
NetworkSearcher.ReportProgress(-1);
}
I thought C# programs were supposed to never cause bluescreens?
I discovered this issue a few weeks back. It only happens when using .NET 4.
Reported at MS Connect.
Edit:
(Will*) Add this link to MS Connect bug report.
*login.live.com is going into an infinite loop again...
Just to be clear, there is no way for "user" mode code to forcibly create a blue screen in windows, unless it uses undocumented APIs and or forces bad data into a driver. Your C# code is likely not be at fault here, as if you use the user mode classes (Socket) then the socket is responsible for not crashing your computer.
As #Joe has commented Microsoft Support KB Article 256010 clearly describes this stop message, but better yet has clear instructions on capturing the driver name responsible for this error.
Note that any software firewall that you have installed also is involved at kernel mode level so could also be responsible for this error. I recommend you follow the KB articles advice and try to find out what is at fault. But you could also ensure that you have updated your network drivers and firewall/VPN software to the latest stable versions.