SignalR client consumes all ports on the machine - c#

We are seeing a very strange issue with our signalR client that results in complete port exhaustion on the machine running the code. Over 16000 ports end up in the Close_Wait state.
The logs show that the Closed handle is firing several hundred times a second.
The program can run fine for hours or days before the issue occurs.
How is it possible to make the Closed handle in the code below fire continuously until all ports are exhausted?
using Microsoft.AspNet.SignalR.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp
{
public class TestEvents
{
private HubConnection _connection;
private IHubProxy<ITestHub, ITestClientContract> Proxy;
public TestEvents()
{
string url = "http://myserver/MySignalRHub";
_connection = new HubConnection(url);
_connection.Closed += HubConnectionOnClosed;
_connection.Reconnected += HubConnectionOnReconnected;
_connection.Reconnecting += HubConnectionOnReconnecting;
Proxy = _connection.CreateHubProxy<ITestHub, ITestClientContract>("TestHub");
}
public async Task Start()
{
await _connection.Start();
var result = await Proxy.CallAsync(h => h.TestMethod("test"));
Console.WriteLine($"Got {result} from connection {_connection.ConnectionId}");
}
private async void HubConnectionOnClosed()
{
Console.WriteLine("Closed");
try
{
await _connection.Start();
}
catch(Exception ex)
{
Console.WriteLine("Error");
}
}
private async void HubConnectionOnReconnected()
{
Console.WriteLine("Reconnected");
}
private async void HubConnectionOnReconnecting()
{
Console.WriteLine("Reconnecting");
}
}
}

Related

Apparent Memory Leak when dispatching from HttpClient continuation

The Issue: After using HttpClient correctly (as a static single instance) over a long time, ConcurrentStack+Node instances consistently grow in size causing increased memory usage. Edit: This seems related to the dispatcher called in SetText and AddText.
The Use-Case: I am polling a device on my local network through HTTP transmission. I use System.Threading.Timer to control the frequency of my requests. The callback for the polling timer is async void so that the await operator can be used for continuation control. The default window dispatcher is used to display text results after the HttpRequest is called.
The Code for Recreation: .NET Framework 4.5 ; WPF ; All standard settings with a single TextBlock created in MainWindow with x:Name="Debug"
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace LeakIsolator
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
static MainWindow()
{
WebClient.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
HttpClient.DefaultRequestHeaders.CacheControl = new System.Net.Http.Headers.CacheControlHeaderValue()
{
NoStore = true,
NoCache = true
};
}
public MainWindow()
{
InitializeComponent();
Timer = new Timer(Poll, null, Timeout.Infinite, Timeout.Infinite);
Loaded += MainWindow_Loaded;
}
private static HttpClient HttpClient { get; } = new HttpClient();
private static WebClient WebClient { get; } = new WebClient();
private Timer Timer { get; }
private void SetText(string text)
{
Dispatcher.Invoke(() => Debug.Text = text);
}
private void AddText(string text)
{
Dispatcher.Invoke(() => Debug.Text += text);
}
private async void Poll(object a)
{
try
{
SetText("Getting status...");
SetText(await GetResponseStringHttpClient("http://10.10.10.87/status"));
}
catch (Exception e)
{
SetText($"Exception. {e.Message}");
}
finally
{
Start();
}
}
private async Task<string> GetResponseStringWebClient(string address)
{
return await WebClient.DownloadStringTaskAsync(address);
}
private async Task<string> GetResponseStringHttpClient(string address)
{
using (var response = await HttpClient.GetAsync(address))
{
if (response.IsSuccessStatusCode)
{
AddText(" Success...");
return await response.Content.ReadAsStringAsync();
}
else
{
AddText(" Fail.");
return null;
}
}
}
private void Start()
{
Timer.Change(1000, Timeout.Infinite);
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Start();
}
}
}
Using ANTS memory profiler, and running the application for 37 minutes in the most recent test, 2.618 MB (small for now, but this is a long-running application) inaccessible-to-me bytes are allocated by a PinnableBufferCache, presumably stored in the gen 2 heap.
I am not sure if this is a memory leak or is a part of something I do not understand. Why am I seeing these memory increases and why am I unable to dictate the local caching behavior of HttpClient and WebClient?
I would guess AddText, you could try commenting out the code in that method and see if the memory leak goes away.

Multithreaded network application issues

I've looked at least a hundred threads and none gave me a solution to my specific problem so far and i got tired of looking,
I'm trying to emulate a runescape game server in C#,
I need to receive lots of connections and parse the requests and send out responses for them until the game has loaded all the files, and then proceed to the actual login protocol. this needs to be able to handle multiple connections per second, as in, i handle 3 basic protocols "jaggrab", "ondemand" and then regular game protocol i.e; login, player updating etc these are all handled on the same port
My Server class listens for connections on one thread, while on another thread my PipelineFactory handles the connections in a Queue one by one as fast as it can, meanwhile there is a TaskPool thread which is executing PoolableTask objects at their own individual intervals... this works fine except as soon as I accept a connection both the pool and server threads begin to block and furthermore, the server object stops listening for connections all together but the thread seems to keep running.. I assume this is because the TcpListener.Pending() is not being updated? but i cant seem to find a function to update this list in the docs or anywhere
I seem to be using the threads the way all the multithreading tutorials explain them to work? i dont really understand what im doing wrong.. heres the important parts of my code:
MainEntry.cs:
using System;
using System.Threading;
using gameserver.evt;
using gameserver.io;
using gameserver;
using gameserver.io.player;
public static class MainEntry
{
public static void Main(string[] args)
{
Console.WriteLine("Starting game server...");
new Thread(new ThreadStart(Server.Run)).Start();
new Thread(new ThreadStart(TaskPool.Run)).Start();
new Thread(new ThreadStart(PipelineFactory.Run)).Start();
//TODO maybe pool these
}
}
Server.cs:
using gameserver.io.player;
using gameserver.io.sql;
using gameserver.model;
using gameserver.model.player;
using util;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using gameserver.io.player.pipeline;
using gameserver.evt;
using util.cache;
namespace gameserver.io
{
public class Server
{
public static TcpListener serverSocket;
public static Dictionary<int, Player> players = new Dictionary<int, Player>(Constants.MaxPlayers);
public static Database database;
public const int ListenPort = 43594;
public static bool running = true;
public static readonly Cache cache = new Cache(Constants.CacheDir);
public static void Bind()
{
serverSocket = new TcpListener(IPAddress.Parse("0.0.0.0"), ListenPort);
serverSocket.Start();
Console.WriteLine("Server started at 0.0.0.0:" + ListenPort);
}
public static void Run()
{
if (serverSocket == null)
Bind();
while(IsRunning())
{
Console.Write("serve");
var incoming = serverSocket.AcceptTcpClient();
if (incoming != null)
{
PipelineFactory.queue.Enqueue(new PlayerSocket(incoming));
}
Thread.Sleep(25);
}
}
private static void Destroy()
{
serverSocket.Stop();
//saveall players
//Environment.Exit(0);
}
public static bool Online(Player player)
{
if(player == null)
{
return false;
}
for (int i = 0; i < players.Count; i++)
{
if (player.username == players[i].username)
{
return true;
}
}
return false;
}
public static Database Database => database ?? (database = new Database());
public static bool IsRunning() => running;
}
}
TickPool.cs:
using gameserver.io;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace gameserver.evt
{
public class TaskPool
{
public static bool running = true;
public static List<PoolableTask> tasks = new List<PoolableTask>();
public static void Run()
{
do
{
long cur = Environment.TickCount;
Console.Write("tick");
foreach (PoolableTask t in tasks)
{
if (cur - t.last >= t.interval)
{
if (t == null)
continue;
t.Execute();
t.last = cur;
}
}
Thread.Sleep(100);
} while (Server.IsRunning());
}
public static void Add(PoolableTask task)
{
if(!tasks.Contains(task))
tasks.Add(task);
}
public static void Stop(PoolableTask task)
{
if(tasks.Contains(task))
tasks.Remove(task);
}
}
}
PipelineFactory.cs:
using gameserver.evt;
using gameserver.io.player.pipeline;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace gameserver.io.player
{
// simple but effective state machine for all non player model related protocol
public class PipelineFactory
{
public static Queue<PlayerSocket> queue = new Queue<PlayerSocket>(100);
private static readonly LoginPipe loginPipe = new LoginPipe();
private static readonly JaggrabPipe jgpipe = new JaggrabPipe();
private static readonly HandshakePipe handshake = new HandshakePipe();
private static readonly OnDemandPipe ondemand = new OnDemandPipe();
public static void Run()
{
while (Server.IsRunning())
{
Console.Write("pipe");
if (queue.Count() > 0)
{
var socket = queue.First();
if (socket == null || !socket.GetSocket().Connected
|| socket.state == PipeState.Play)
{
queue.Dequeue();
return;
}
switch (socket.state)
{
case PipeState.Handshake:
socket.currentPipeline = handshake;
break;
case PipeState.Jaggrab:
socket.currentPipeline = jgpipe;
break;
case PipeState.OnDemand:
socket.currentPipeline = ondemand;
break;
case PipeState.LoginResponse:
case PipeState.Block:
case PipeState.Finalize:
socket.currentPipeline = loginPipe;
break;
case PipeState.Disconnect:
//TODO: Database.saveForPlayer
socket.Close();
break;
}
try
{
if (socket.currentPipeline != null)
socket.state = socket.currentPipeline.HandleSocket(socket);
}
catch (Exception)
{
socket.Close();
queue.Dequeue();
}
}
Thread.Sleep(20);
}
}
}
}
The protocol itself really shouldn't matter just know it's all being handled asynchronously
I'm a java programmer at heart but trying to delve into C# head first so thats why my conventions might not be perfect, and I don't really know how to/dont understand intellisense documentation but at some point ill look into it
EDIT: I just wanna note that everything worked perfectly before i tried using threads to multithread this, when i had the PipelineFactory a PoolableTask object implementation, it could handle multiple connections etc and there was only the main thread calling 2 while loops handling everything in the whole server, i'm trying to spread out the load over the cpu but its not working out for me lol

WiFi communication between C# and ESP8266 [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm working on school project right now and I'm looking for the simplest way to connect C# with ESP8266 not via SerialPort (COM4) but via WiFi module on ESP8266 (I have to use this method). I have to build simple project to sending measured data from ESP to C# and also receiving my own defined control commands (strings like "LEDON" "LEDOFF" etc.) from C# to ESP just like remote control of measurement project. I have low knowledge in C# same as basics of servers/internet and things like that. I have everything done in Arduino IDE code but I'm stuck on C# cause I never before programmed there. I hope you understand my bad English and concept of my question. :)
EDIT:
Well, so I did some changes in my school project and now I am on this stage, where I need to solve this part of code. I hope that is last step to finish my project. All I have to do is solve Writing data from C# to ESP using unfilled method named "Writing" in following code:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace ESP8266
{
public class Projekt
{
public event MessageEventHandler Message;
public delegate void MessageEventHandler(Projekt sender, string Data);
public TcpListener server;
public Thread W_Thread;
public Thread R_Thread;
public bool IsLiserning = true;
public TcpClient client;
public StreamReader clientdata;
public StreamWriter serverdata;
public Projekt()
{
server = new TcpListener(IPAddress.Parse(Dns.GetHostEntry(Dns.GetHostName().ToString()).AddressList[1].ToString()), 5000);
server.Start();
W_Thread = new Thread(new ThreadStart(Writing));
W_Thread.Start();
R_Thread = new Thread(new ThreadStart(Reading));
R_Thread.Start();
}
public void Reading()
{
while (IsLiserning == true)
{
if (server.Pending() == true)
{
client = server.AcceptTcpClient();
clientdata = new StreamReader(client.GetStream());
}
try
{
Message?.Invoke(this, clientdata.ReadLine());
}
catch (Exception){}
}
}
public void Writing()
{
while (IsLiserning == true)
{
if (server.Pending() == true)
{
client = server.AcceptTcpClient();
serverdata = new StreamWriter(client.GetStream());
}
try
{
//NEED_TO_SOLVE_THIS_PART
}
catch (Exception){}
}
}
}
}
Maybe there is missing something more than that part of code and you guys are able to help me I hope :) Thanks for all answers by the way :)
You may look at this project, basically you want to communicate via TCP/IP between the arduino and the C#. consider the C# as the server and the arduino as the client. Then they just need to send message to each other to communicate.
The link I'm providing is doing a lot more than needed, so if you're lost, maybe start with something really basic and look here and check the links at the end talking about c# server. They will be easier to understand compared to my first link.
[EDIT] Ok, only links answer is dangerous and not the best, so here is a really light version of what I gave through the first link:
Your server will have a list of receivers, each receiver only handle one client. It's a big simplification of one of my project, I hope that by removing lots of things I didn't break anything:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Windows.Data;
namespace DemoServer.Models
{
public class Server
{
public TcpListener Listener { get; set; }
public int Port { get; set; }
public bool IsStarted { get; private set; }
public List<Receiver> Receivers = new List<Receiver>();
public Server(int port)
{
Receivers.Clear();
BindingOperations.EnableCollectionSynchronization(Receivers, Receivers);
Port = port;
IsStarted = false;
}
public void Start()
{
if (!IsStarted)
{
try
{
Listener = new TcpListener(System.Net.IPAddress.Any, 0);
Listener.Start();
IsStarted = true;
IPAddress address = ((IPEndPoint)Listener.LocalEndpoint).Address;
int port = ((IPEndPoint) Listener.LocalEndpoint).Port;
Console.WriteLine("Server Started");
//Start Async pattern for accepting new connections
WaitForConnection();
}
catch (Exception e)
{
Console.WriteLine(e);
IsStarted = false;
}
}
}
public void Stop()
{
if (IsStarted)
{
Listener.Stop();
IsStarted = false;
Receivers.Clear();
Console.WriteLine("Server Stopped");
}
}
private void WaitForConnection()
{
Listener.BeginAcceptTcpClient(new AsyncCallback(ConnectionHandler), null);
}
private void ConnectionHandler(IAsyncResult ar)
{
if (IsStarted)
{
Receiver newClient = new Receiver(Listener.EndAcceptTcpClient(ar), this);
newClient.Start();
Receivers.Add(newClient);
WaitForConnection();
}
}
public void SomeInteractionBetweenClients()
{
Console.WriteLine("Interaction!");
}
}
}
Then comes the Receiver code, where you really handle the communication with your client:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading;
namespace DemoServer.Models
{
public class Receiver : ModelBase
{
bool ConnectionStatus = false;
private uint m_Id = 0;
public uint Id
{
get { return m_Id; }
set => SetAndRaisePropertyChanged(ref m_Id, value);
}
private Thread receivingThread;
private Thread sendingThread;
public Server Server { get; set; }
public TcpClient Client { get; set; }
public List<String> MessageQueue { get; private set; }
public Receiver(TcpClient client, Server server)
{
MessageQueue = new List<String>();
Server = server;
Client = client;
Client.ReceiveBufferSize = 1024;
Client.SendBufferSize = 1024;
ConnectionStatus = true;
}
public void Start()
{
receivingThread = new Thread(ReceivingMethod);
receivingThread.IsBackground = true;
receivingThread.Start();
sendingThread = new Thread(SendingMethod);
sendingThread.IsBackground = true;
sendingThread.Start();
}
private void Disconnect()
{
if (!ConnectionStatus) return;
ConnectionStatus = false;
Client.Client.Disconnect(false);
Client.Close();
}
private void SendingMethod()
{
while (ConnectionStatus)
{
if (MessageQueue.Count > 0)
{
var message = MessageQueue[0];
try
{
NetworkStream clientStream = Client.GetStream();
StreamWriter streamWriter = new StreamWriter(clientStream);
streamWriter.Write(message);
streamWriter.Flush();
Console.WriteLine($"We are sending '{message}' to the client");
}
catch
{
Disconnect();
}
finally
{
MessageQueue.RemoveAt(0);
}
}
Thread.Sleep(30);
}
}
private void ReceivingMethod()
{
while (ConnectionStatus)
{
if (Client.Available > 0)
{
try
{
NetworkStream clientStream = Client.GetStream();
StreamReader streamReader = new StreamReader(clientStream);
char[] puchBuffer = new char[Client.Available];
int iQtt = streamReader.Read(puchBuffer, 0, Client.Available);
string msg = String.Empty;
for (int i = 0; i < puchBuffer.Length; i++)
{
msg = $"{msg}{Convert.ToString(puchBuffer[i])}";
}
OnMessageReceived(msg);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Thread.Sleep(30);
}
}
private void OnMessageReceived(String msg)
{
// Here you can parse the messages coming ffrom the client and do whatever is needed
// If needed, you can even call some public methods from the server to forward some info to an other client for example or just the server:
// eg: Server.SomeInteractionBetweenClients();
}
}
}
I hope this will help for the communication part. For the GUI there are lots of tutorials on the web but if possible I still think WPF/MVVM is better to learn than winforms.
From my understanding your project requires 2 way communication. Making c# as server will not be ideal since there is no easy way to send command from C# to esp8266. I assume your project is utilizing esp8266 as the arduino platform (not attaching esp8266 to arduino as wifi module), please check out MQTT which is a broker for publishing and subscribing messages. That way both esp8266 and C# code and communicate via MQTT and achieve 2 way communication purpose.
for esp8266, you can check out arduino MQTT library for esp8266 here: https://github.com/knolleary/pubsubclient.

Serial Communication gets back wrong answer when something is running in the background (like browsing the hard drive)

I have some big trouble with serial requests.
Description from what i want:
establish a serial connection, send serial requests to 6 temperature
sensors one by one (this is done every 0,5 second in a loop)
the question and answer-destination is stored in a List array
every request is started in a separate thread so the gui does not bug
while the programme waits for the sensor-hardware to answer
My problem:
The connection and the request is working fine, but if I am browsing data at the local hard drive the answer from the sensor-unit gets destroyed (negative algebraic sign or value from other sensor or simply wrong value).
How does this happen or how can I solve this?
Where I guess the problem might be:
In the private void ReceiveThread() of class SerialCommunication
Here is my code:
Class CommunicationArray:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hardwarecommunication
{
public class CommunicationArray
{
public string request { get; set; }
public object myObject { get; set; }
public string objectType { get; set; }
}
}
Class SerialCommunication
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
namespace Hardwarecommunication
{
class SerialCommunication
{
Thread t2;
Thread t;
private SerialPort serialPort = new SerialPort("COM2", 115200, Parity.Even, 8, StopBits.One);
string serialAnswer = "";
private volatile bool _shouldStop;
private int counter;
List<CommunicationArray> ar = new List<CommunicationArray>();
object[] o = new object[3];
public void addListener(string request, object myObject, string objectType)
{
CommunicationArray sa = new CommunicationArray();
sa.request = request;
sa.myObject = myObject;
sa.objectType = objectType;
ar.Add(sa);
}
public void startListen()
{
t2 = new Thread(() => writeSerialPortThread());
t2.Start();
}
public void startSerialPort2()
{
try
{
serialPort.Open();
//MessageBox.Show("Connection opend!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
public void stopSerialPort2()
{
try
{
if (serialPort.IsOpen == true)
// Connection closed
serialPort.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void writeSerialPortThread()
{
string request = "";
for (int i = 0; i < ar.Count(); i++)
{
request = ar[i].request;
//request = ((object[])ar[0])[0].ToString();
//if (!t.IsAlive)
//{
try
{
t = new Thread(ReceiveThread);
_shouldStop = false;
//MessageBox.Show("start thread");
t.Start();
serialPort.Write(request);
Thread.Sleep(50);
_shouldStop = true;
t.Join();
}
catch
{
}
Label tmpLabelObject = (Label)ar[i].myObject;
serialAnswer = serialAnswer.Replace("=", "");
if (tmpLabelObject.InvokeRequired)
{
MethodInvoker UpdateLabel = delegate
{
tmpLabelObject.Text = serialAnswer;
};
try
{
tmpLabelObject.Invoke(UpdateLabel);
}
catch
{
}
}
}
}
private void ReceiveThread()
{
//MessageBox.Show("in thread");
while (!_shouldStop)
{
serialAnswer = "";
try
{
//MessageBox.Show("in thread");
serialAnswer = serialPort.ReadTo("\r");
if (serialAnswer != "")
{
}
return;
}
catch (TimeoutException) { }
}
}
}
}
Class Form1 //to establish the connection and to start the Sensor request
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Hardwarecommunication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private SerialCommunication serialCommunication1 = new SerialCommunication();
private void Form1_Load(object sender, EventArgs e)
{
//start up serial connection
serialCommunication1.startSerialPort2();
}
private void buttonStart_Click(object sender, EventArgs e)
{
timerRecord.Enabled = true;
if (this.buttonStart.Text == "Start")
this.buttonStart.Text = "Stop";
else
this.buttonStart.Text = "Start";
}
private void timerRecord_Tick(object sender, EventArgs e)
{
if (this.buttonStart.Text == "Stop")
{
this.serialCommunication1.startListen();
}
}
private void buttonFillRequestArray_Click(object sender, EventArgs e)
{
this.serialCommunication1.addListener("$0BR00\r" + "\r", this.labelResult0, "label0"); //request to the hardware
this.serialCommunication1.addListener("$0BR01\r" + "\r", this.labelResult1, "label1");
this.serialCommunication1.addListener("$01R00\r" + "\r", this.labelResult2, "label2");
this.serialCommunication1.addListener("$01R01\r" + "\r", this.labelResult3, "label3");
this.serialCommunication1.addListener("$01R02\r" + "\r", this.labelResult4, "label4");
}
}
}
I woud be happy about any try to fix the problem.
I coud also upload the solution as .zip but you can't test it at all because you do not have the sensor hardware.
Note: serialPort.Write(string) is a non-blocking store into the output buffer.
That means the following won't guarantee you've even finished writing your request before you stop listening for a response:
serialPort.Write(request);
Thread.Sleep(50);
_shouldStop = true;
You could add:
while( serialPort.BytesToWrite > 0 ) Thread.Sleep(1); // force blocking
but it's ill advised.
One thing I'm wondering. There is only a single serial port here. Why do you want many different threads to work with it when you could manage the entire serial port interaction with a single thread? (Or at worse, 1 thread for input 1 thread for output)
To me it makes a lot more sense to store up requests into a queue of some kind and then peel them off one at a time for processing in a single thread. Responses could be similarly queued up or fired as events back to the caller.
EDIT: If you don't mind one read/write cycle at a time you could try:
string response;
lock(serialPort) {
// serialPort.DiscardInBuffer(); // only if garbage in buffer.
serialPort.Write(request);
response = serialPort.ReadTo("\r"); // this call will block till \r is read.
// be sure \r ends response (only 1)
}

HttpListener Problem

I have to establish an HttpListener that will wait for requests made by our client's server. I have to receive that request on port 8088 and extract the query string. That is the easy part.
I'm running the HttpListener in a windows service. I cannot get it to fire properly. I build the setup project install the service on our server and it never starts. I suspect there's an error with my code.
HttpListenerClass:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Threading;
namespace lalalolo
{
class HttpListenerClass
{
bool keepAlive = true;
public void AddToFile(string contents)
{
var fs = new FileStream(#"C:\HttpListenerserv.txt", FileMode.OpenOrCreate, FileAccess.Write);
var sw = new StreamWriter(fs);
sw.BaseStream.Seek(0, SeekOrigin.End);
sw.WriteLine(contents);
sw.Flush();
sw.Close();
}
private HttpListener listener;
public HttpListenerClass()
{
ThreadPool.SetMaxThreads(50, 100);
ThreadPool.SetMinThreads(50, 50);
listener = new HttpListener();
listener.Prefixes.Add("http://*:8088/");
}
public void Start()
{
listener.Start();
if(keepalive == true){
{
try
{
HttpListenerContext ctx = listener.GetContext();
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessRequest), ctx);
}
catch(Exception ex)
{
AddToFile(ex.Message);
}
}
}
}
public void Stop()
{
listener.Stop();
keepalive == false;
}
public void ProcessRequest(object listenerContext)
{
try
{
var context = (HttpListenerContext)listenerContext;
string QS = context.Request.QueryString["ID"];
AddToFile(QS);
}
catch(Exception ex)
{
AddToFile(ex.Message);
}
}
}
}
Service1.cs:
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.ServiceProcess;
using System.Text;
using System.Threading;
namespace lalalolo
{
public partial class HttpListenerTest1 : ServiceBase
{
HttpListenerClass HTTP = new HttpListenerClass();
public void AddToFile(string contents)
{
var fs = new FileStream(#"C:\HttpListenerserv.txt", FileMode.OpenOrCreate, FileAccess.Write);
var sw = new StreamWriter(fs);
sw.BaseStream.Seek(0, SeekOrigin.End);
sw.WriteLine(contents);
sw.Flush();
sw.Close();
}
public HttpListenerTest1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
HTTP.Start();
}
protected override void OnStop()
{
HTTP.Stop();
}
}
}
What am I doing wrong?
Thank you guys!
Queuing worker items in a while(true) loop? Are you serious?!
Your OnStart method never returns because of that while loop. However, returning from the OnStart method is essential for the service manager to know, that your service started correctly.
Your service will probably just die with an OutOfMemoryException or something similar, because of that endless loop.
Suggestion:
Try adopting this sample. It is in IronPython but that also uses the .NET framework. Hint: The while(true) in that implementation should be changed to be able to break the while loop when your service is being stopped. Additionally, you must call serveforever in your Start method in an async way.
This should get you going.

Categories

Resources