Greetings everybody,
after few hours of trying to solve this by myself, I’m starting to be desperate, so I would like to ask if anyone experienced following behavior:
My application has main screen where end-user can put widgets. One of these widgets uses HttpWebRequest to retreive weather information from web-site. Everything worked just fine after I switched from 4.1 SDK to newest 4.2 SDK (VS2010 - so I’m using .NETMF 4.2 QFE). After system startup, widget updates itself without any problem for a few times (40 - 60 times), but after then it fails raising webexception, which has interesting inner exception:
Just to confirm that I have the same issue on a G120 with the latest firmware.
And I don’t use HttpWebRequest, just plain TCP client socket.
The exception I often get is : -1728053248, but I got other exceptions as well.
Same behavior, it works maybe for the first 40 to 1250 times.
If I only do “connects” without transmitting any data, it takes a while until I get an exception, but eventually, it happened around the 1250th connection.
If I connect to the server, and transmit back and forth 3kbytes messages for a little while, eventually I get an exception.
Once the exception happens, I cannot ever reconnect to the server, without rebooting the G120.
Here is my client code:
using System;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Text;
using Microsoft.SPOT;
using Microsoft.SPOT.Net.NetworkInformation;
namespace DataLoggerCommonLib {
public class SocketClient : Disposable {
public System.Threading.Thread mSocketClientThread = null;
public bool mNetworkAvailable = false;
public bool mConnected = false;
public string mServerIP;
public int mServerPort;
private int mTimeoutMillis = 5*1000; // Après 60 secondes sans communications du serveur, on essait de se reconnecter
public object ThreadMutex = new object();
private bool mClosingThread = false;
private int mNumSocket = 0;
private DateTime mTimeLastCommunication = DateTime.Now;
private Byte[] mCommBuffer = new Byte[65536];
public SocketClient(string serverIP, int serverPort) {
this.mServerIP = serverIP;
this.mServerPort = serverPort;
}
public void VerifyConnectionIsAlive() {
TimeSpan verifyExpired = DateTime.Now - mTimeLastCommunication;
//If time since last communication has expired...
if (mSocketClientThread == null || CommonTools.ConvertTimeSpanToMillis(verifyExpired) >= mTimeoutMillis) {
Debug.Print("Server not responding for a while. Restarting connection...");
mClosingThread = true;
mConnected = false;
try {
if (mSocketClientThread != null) {
if ( mSocketClientThread.Join(5000) ) {
Debug.Print("SocketClient Thread Join successful.");
} else {
Debug.Print("SocketClient Thread Join FAILED, closing socket and trying again.");
//CloseSocket();
if (mSocketClientThread.Join(5000)) {
Debug.Print("SocketClient Thread Join successful after 2nd try.");
} else {
Debug.Print("Thread Join FAILED, aborting thread.");
try {
if (mSocketClientThread != null) {
mSocketClientThread.Abort();
}
} catch {
}
Thread.Sleep(5000);
}
}
mSocketClientThread = null;
}
} catch {
}
mSocketClientThread = null;
Thread.Sleep(1000);
Debug.GC(true);
GC.WaitForPendingFinalizers();
mClosingThread = false;
ConnectToServerAndKeepAlive();
}
}
public void ConnectToServerAndKeepAlive() {
mTimeLastCommunication = DateTime.Now;
mSocketClientThread = new System.Threading.Thread(StartConnectionBackGround);
mSocketClientThread.Start();
}
private void StartConnectionBackGround() {
mTimeLastCommunication = DateTime.Now;
Socket socket = Connect();
if ( socket != null ) {
mNumSocket++;
Debug.Print("NumSocket:" + mNumSocket);
//this.WaitForCommands(socket);
}
CloseSocket(socket);
}
public Socket Connect() {
bool linger = false;
Debug.GC(true);
Thread.Sleep(100);
Socket socket = null;
try {
IPHostEntry hostEntry = Dns.GetHostEntry(mServerIP);
if (hostEntry != null && hostEntry.AddressList.Length > 0) {
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.ReceiveTimeout = 10000;
socket.SendTimeout = 10000;
IPEndPoint endPoint = new IPEndPoint(hostEntry.AddressList[0], mServerPort);
if (endPoint != null) {
socket.Connect(endPoint);
if (linger) {
socket.SetSocketOption(SocketOptionLevel.Socket
, SocketOptionName.DontLinger, true);
} else {
socket.SetSocketOption(SocketOptionLevel.Tcp
, SocketOptionName.NoDelay, true);
}
mNetworkAvailable = true;
mConnected = true;
} else {
Debug.Print("Unable to determine Host Address");
return null;
}
} else {
Debug.Print("Unable to resolve DNS entry");
return null;
}
} catch (Exception ex) {
Debug.Print("Server not responding..." + ex.Message);
return null;
}
return socket;
}
public void WaitForCommands(Socket socket) {
Debug.Print("Connection OK, waiting for command");
try {
//do {
// Wait for the client request to start to arrive.
if (socket != null) {
//if (socket.Poll(15000000, SelectMode.SelectRead)) {
while (socket.Available != 0) {
mTimeLastCommunication = DateTime.Now;
Int32 bytesRead = socket.Receive(mCommBuffer, socket.Available, SocketFlags.None);
string request = CommonTools.DecodeHttpRequest(CommonTools.BytesToString(mCommBuffer, bytesRead));
Debug.Print(request);
//string responseString = decode_request(request);
string responseString = logger.HttpProcessor.processHttpRequest(request);
// Return a static HTML document to the client.
String str = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: " + responseString.Length + "\r\n\r\n" + responseString;
socket.Send(Encoding.UTF8.GetBytes(str));
mTimeLastCommunication = DateTime.Now;
Debug.GC(true);
GC.WaitForPendingFinalizers();
Thread.Sleep(1000);
}
//}
}
Thread.Sleep(100);
//} while (!mClosingThread);
} catch (Exception ex) {
Debug.Print("Error while processing commands. Reconnecting..." + ex.Message);
}
}
private void CloseSocket(Socket socket) {
try {
if (socket != null) {
socket.Close();
}
} catch {
}
socket = null;
}
protected override void ReleaseManagedResources() {
}
}
}
For now I will make my server to communicate with the G120 devices, but I would eventually need the G120 to connect as client to the server because of firewall/routing issues.
If it helps, I could provide a fully functionnal VS2010 solution/project to show the socket exceptions I am getting.
By the way, this is with an ENC28J60 module.
I tried to set KeeAplive property to false and the behavior is different but not good at all. It just stopped to throw SocketException as I described in my first post, but after few successful updates, it just hangs on calling:
using (HttpWebResponse wr = (HttpWebResponse)request.GetResponse())
but this time without any preceeding exceptions.
I don’t understand your sentence:
I closed and disposed everuthing properly so I don’t understand why should anything stay opened?
“Parameters” is just string property contained in abstract class of widget which holds value in format depending on specific widget implementation. In case of weather widget it represents ID of measure. You can test it for example with value 61 to see temperature in my home city
That should have read "keepalive " .
I am running your code with a timer and that may be the difference based on what I read in the other thread concerning the need for the sleep call. Will let you know.
OK, thanks, let me know about your results. I’m running the code in separated thread… I tried to add Sleep and calling Debug.GC(true) according to topic I’ve posted above, but with no luck.
public class Program
{
private static EthernetBuiltIn ethernet;
public static void Main()
{
ethernet = new EthernetBuiltIn();
ethernet.NetworkAddressChanged += new NetworkInterfaceExtension.NetworkAddressChangedEventHandler(ethernet_NetworkAddressChanged);
ethernet.CableConnectivityChanged += new EthernetBuiltIn.CableConnectivityChangedEventHandler(ethernet_CableConnectivityChanged);
ethernet.Open();
NetworkInterfaceExtension.AssignNetworkingStackTo(ethernet);
ethernet.NetworkInterface.EnableDhcp();
new Thread(testThread_Work).Start();
while (true)
{
Thread.Sleep(5000);
}
}
private static void ethernet_CableConnectivityChanged(object sender, EthernetBuiltIn.CableConnectivityEventArgs e)
{
logDebug("Network cabel " + (e.IsConnected ? "connected" : "disconnect"));
}
private static void ethernet_NetworkAddressChanged(object sender, EventArgs e)
{
logDebug("Network address changed :: " + ethernet.NetworkInterface.IPAddress);
}
private static void testThread_Work()
{
int count = 0;
while (true)
{
using (HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(@ "http://www.webcamlive.cz/xml_measureById.php?idMeasure=" + 61)))
{
request.UserAgent = "Touch Panel";
request.KeepAlive = false;
using (HttpWebResponse wr = (HttpWebResponse)request.GetResponse())
{
using (Stream s = wr.GetResponseStream())
{
using (XmlReader xml = XmlReader.Create(s))
{
//while (xml.Read()) logdebug("xml: " + xml.Name);
xml.Close();
}
if ((count++ % 100) == 0)
{
logDebug("Response: " + count);
}
s.Close();
}
wr.Close();
}
}
}
}
private static void logDebug(string text)
{
Debug.Print(text);
}
}
Sometimes I can even reach debu output “Response: 501”, but it was my top, after that garbage collection occured and it hangs again. Never happend with .NETMF 4.1 before