I have been evaluating the capabilities of G80 and testing a few implementations of some socket servers, mostly based on some examples from this forum (specifically https://www.ghielectronics.com/community/forum/topic?id=22141&page=13#msg208815) before get stuck into fleshing out my own for a project coming up.
I have been having some problems diagnosing some strange behaviour:
I have setup a browser tab auto-refreshing every 2 seconds. The code (below) will serve responses back to the browser for hours so far but the socket seems to hang very reliably and periodically every 10sec or so then recover. The picture attached shows Chromeās request timeline with the auto-refresher going at 2seconds.
Any help would be appreciated.
Looking down the line, this project will require reliable network access for weeks/months at a time. Is this feasible at the moment with netmf? Has anyone set up a server with this level of reliability? If so Iād be interested in chatting about code and costs if anything is for sale.
public class SimpleWebServer
{
private AutoResetEvent _listenerStarted;
internal Socket _socket;
internal Thread _thread;
internal Thread _acceptThread;
private IPAddress _interfaceAddress = IPAddress.Any;
private int _receiveTimeout = -1;
private int _sendTimeout = -1;
private int _listenBacklog = 5;
private bool _isActive = false;
const int BufferSize = 1460;
const int StringLength = 500 * 1024;
const int READ_CHUNK_SIZE = 1460;//
public static Object SDCardLock = new Object();
static DateTime _bootTime = DateTime.Now;
static string html = "";
static byte[] response = new byte[BufferSize*2];
static int _numReceived;
static byte[] _receiveBuffer = new byte[BufferSize*2];
static EndPoint remoteEndPoint;
int numBytesToWrite ;
int offset = 0;
int bytesSent;
int sendSize;
static Microsoft.SPOT.Hardware.OutputPort LED2;
static Microsoft.SPOT.Hardware.OutputPort LED3;
static Microsoft.SPOT.Hardware.OutputPort LED4;
public bool Start(int servicePort)
{
try
{
LED2 = new Microsoft.SPOT.Hardware.OutputPort(GHI.Pins.G80.Gpio.PE13, false);
LED3 = new Microsoft.SPOT.Hardware.OutputPort(GHI.Pins.G80.Gpio.PE11, false);
LED4 = new Microsoft.SPOT.Hardware.OutputPort(GHI.Pins.G80.Gpio.PE9, false);
_listenerStarted = new AutoResetEvent(false);
_interfaceAddress = System.Net.IPAddress.GetDefaultLocalAddress();
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint _localEndPoint = new IPEndPoint(_interfaceAddress, servicePort);
_socket.Bind(_localEndPoint);
_socket.ReceiveTimeout = _receiveTimeout;
_socket.SendTimeout = _sendTimeout;
_socket.Listen(_listenBacklog);
_isActive = true;
_thread = new Thread(StartListen);
_thread.Start();
_listenerStarted.WaitOne();
}
catch (Exception)
{
return false;
}
return true;
}
public bool Stop()
{
try
{
_isActive = false;
_socket.Close();
}
catch (Exception)
{
return false;
}
return true;
}
private void StartListen()
{
_listenerStarted.Set();
while (_isActive)
{
try
{
LED2.Write(true);
var clientSocket = _socket.Accept();
_acceptEvent.Set();
LED2.Write(false);
LED3.Write(true);
new Thread(() =>
{
try
{
OnSocket(clientSocket);
}
catch (Exception ex)
{
throw ex;
}
}).Start();
}
catch (SocketException ex)
{
Debug.Print("SocketException in Accept(): errorcode: " + ex.ErrorCode);
//throw;
}
}
_socket.Close();
}
protected virtual void OnSocket(Socket socket)
{
try
{
//if (socket.Poll(-1, SelectMode.SelectRead))
//{
// //remoteEndPoint = new IPEndPoint(0, 0);
// if (socket.Available == 0)
// {
// LED4.Write(true);
// return;
// }
//}
while (!socket.Poll(100000, SelectMode.SelectRead))
{
if (socket.Poll(10, SelectMode.SelectError))
{
Debug.Print("RCP Client Socket error");
throw new ApplicationException("RCP Client Socket error");
}
Thread.Sleep(0);
}
if (socket.Available == 0)
{
// disconnect
return ;
}
_numReceived = socket.Receive(_receiveBuffer, BufferSize*2, SocketFlags.None);
html = "<!DOCTYPE html><html><body><h1> Sample Test. Uptime: " + (DateTime.Now - _bootTime).ToString() + "<br>GC: " + Debug.GC(false) + "</h1></html>";
response = Encoding.UTF8.GetBytes("HTTP/1.1 200 OK\nServer: dingus server\nContent-Length: " + html.Length + "\nAccept-Ranges: bytes\nContentType: application/octet-stream\nConnection: close\n\n" + html);
numBytesToWrite = response.Length;
offset = 0;
do
{
sendSize = (numBytesToWrite <= BufferSize) ? numBytesToWrite : BufferSize;
bytesSent = socket.Send(response, offset, sendSize, SocketFlags.None);
numBytesToWrite -= bytesSent;
offset += bytesSent;
} while (numBytesToWrite > 0);
//response = Encoding.UTF8.GetBytes(html);
//numBytesToWrite = response.Length;
//offset = 0;
//do
//{
// sendSize = (numBytesToWrite <= BufferSize) ? numBytesToWrite : BufferSize;
// bytesSent = socket.Send(response, offset, sendSize, SocketFlags.None);
// numBytesToWrite -= bytesSent;
// offset += bytesSent;
//} while (numBytesToWrite > 0);
html = null;
//for (int i = 0; i < 1; i++)
// {
// SendFile("\\SD\\LogFiles\\FTPTestingJune.pd0", socket);
// }
}
catch (SocketException ex)
{
Debug.Print("SocketException in OnSocket(): Code:" + ex.ErrorCode + ". Message: "+ ex.Message);
if (ex.ErrorCode == (int)SocketError.ConnectionReset)
return;
}
catch (Exception ex)
{
Debug.Print("General exception in OnSocket(): " + ex.Message);
throw ex;
}
finally
{
socket.Close();
}
LED3.Write(false);
}