C# Socket Multithreading Lambda - c#

I have the following C# code:
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace CTCServer
{
class Server
{
//Stores the IP Adress the server listens on
private IPAddress ip;
//Stores the port the server listens on
private int port;
//Stores the counter of connected clients. *Note* The counter only gets increased, it acts as "id"
private int clientCount = 0;
//Defines if the server is running. When chaning to false the server will stop and disconnect all clients.
private bool running = true;
//Stores all connected clients.
public List<Client> clients = new List<Client>();
//Event to pass recived data to the main class
public delegate void GotDataFromCTCHandler(object sender, string msg);
public event GotDataFromCTCHandler GotDataFromCTC;
//Constructor for Server. If autoStart is true, the server will automaticly start listening.
public Server(IPAddress ip, int port, bool autoStart = false)
{
this.ip = ip;
this.port = port;
if (autoStart)
this.Run();
}
//Starts the server.
public void Run()
{
//Run in new thread. Otherwise the whole application would be blocked
new Thread(() =>
{
//Init TcpListener
TcpListener listener = new TcpListener(this.ip, this.port);
//Start listener
listener.Start();
//While the server should run
while (running)
{
//Check if someone wants to connect
if (listener.Pending())
{
//Client connection incoming. Accept, setup data incoming event and add to client list
Client client = new Client(listener.AcceptTcpClient(), this.clientCount);
//Declare event
client.internalGotDataFromCTC += GotDataFromClient;
//Add to list
clients.Add(client);
//Increase client count
this.clientCount++;
}
else
{
//No new connections. Sleep a little to prevent CPU from going to 100%
Thread.Sleep(100);
}
}
//When we land here running were set to false or another problem occured. Stop server and disconnect all.
Stop();
}).Start(); //Start thread. Lambda \(o.o)/
}
//Fires event for the user
private void GotDataFromClient(object sender, string data)
{
//Data gets passed to parent class
GotDataFromCTC(sender, data);
}
//Send string "data" to all clients in list "clients"
public void SendToAll(string data)
{
//Call send method on every client. Lambda \(o.o)/
this.clients.ForEach(client => client.Send(data));
}
//Stop server
public void Stop()
{
//Exit listening loop
this.running = false;
//Disconnect every client in list "client". Lambda \(o.o)/
this.clients.ForEach(client => client.Close());
//Clear clients.
this.clients.Clear();
}
}
}
Should run not be in a loop to create new threads?
If the first question is not true, and the lambda expression already creates new thread, at which point is new thread created? and where is the logic to decide it?

new Thread( will create the new thread. The lambda is executed on the thread. Run should not be in a loop. Because it will create many threads.
and the lambda expression already creates new thread, no it will be used as the thread method.
The only problem is, that you don't have a reference to the thread, so you cannot wait until it is terminated.
Also you're using a bool running for the while loop. You'd better use a ManualResetEvent for it.
I use this as standard thread setup:
// signal for terminating the thread.
private ManualResetEvent _terminating = new ManualResetEvent(false);
private Thread _thread;
public void Start()
{
ManualResetEvent threadStarted = new ManualResetEvent(false);
_thread = new Thread(() =>
{
threadStarted.Set();
while(!_terminating.WaitOne(0))
{
// do your thing here.
}
});
_thread.Start();
threadStarted.WaitOne();
}
public void Dispose()
{
_terminating.Set();
_thread.Join();
}
One remark here is: Should you use Threaded clients or async sockets.
Threaded clients: client count <= 10
async sockets: client count > 10
The problem with a server is, that your not in charge of how many clients are connecting.
Some pseudo code how to setup your tcp-server and running threads for each client.
public class Server
{
// signal for terminating the thread.
private ManualResetEvent _terminating = new ManualResetEvent(false);
private List<ClientHandler> _clients = new List<ClientHandler>();
public void Start()
{
ManualResetEvent threadStarted = new ManualResetEvent(false);
_thread = new Thread(() =>
{
threadStarted.Set();
// create listener.....
while(!_terminating.WaitOne(0))
{
// do your thing here.
// accept socket
var socket = _listenerSocket.Accept();
ClientHandler handler = new ClientHandler(socket);
_clients.Add(handler);
}
});
_thread.Start();
threadStarted.WaitOne();
}
public void Dispose()
{
_terminating.Set();
_thread.Join();
}
}
public class ClientHandler
{
// signal for terminating the thread.
private ManualResetEvent _terminating = new ManualResetEvent(false);
public ClientHandler(Socket socket)
{
ManualResetEvent threadStarted = new ManualResetEvent(false);
_thread = new Thread(() =>
{
threadStarted.Set();
while(!_terminating.WaitOne(0))
{
// do your thing here.
// accept socket
var bytesReaded = socket.Read(.....);
// handle data....
}
});
_thread.Start();
threadStarted.WaitOne();
}
public void Dispose()
{
_terminating.Set();
_thread.Join();
}
}

Related

Client Thread throwing a state exception and stopping C#

I'm trying to create two client threads which are connected to a server. When there are two connections (Two entries in the threadsArray), I want the start to be announced. The code is never hitting the threadRequest.annouceStart() call however.
Through debugging I have determined that the first thread that is created is being stopped while the server is listening for another connection in the form of the second client. Is it this "freeze" as the server hangs waiting for another connection that is stopping the first thread?
static void Main(string[] args)
{
runServer();
}
static void runServer()
{
TcpListener listener;
Socket connection;
Handler threadRequest;
string defaultName = "";
int defaultScore = 0;
int i = 0;
Thread[] threadsArray = new Thread[2];
try
{
listener = new TcpListener(IPAddress.Any, 43);
listener.Start();
Console.WriteLine("Quiz Server launched");
Console.WriteLine("A default user has been created for testing purposes");
while(true) //main game loop
{
connection = listener.AcceptSocket();
threadRequest = new Handler();
threadsArray[i] = new Thread(() => threadRequest.clientInteraction(connection, teamInformation));
threadsArray[i].Name = "Team" + (i + 1);
threadsArray[i].Start();
i++;
if (threadsArray[1] != null)
{
if (threadsArray[1].ThreadState == ThreadState.Running
&& threadsArray[0].ThreadState == ThreadState.Running)
{
foreach (Thread thread in threadsArray)
{
threadRequest.announceStart(connection, teamInformation);
}
}
}
}
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.ToString());
Console.ReadKey();
}
}
edit: added Handler class definition.
class Handler {
public static string interactionType;
public static string pTeamName;
public static string pAnswer;
public void announceStart(Socket connection, ConcurrentDictionary<string, int> teamInformation)...
public void clientInteraction(Socket connection, ConcurrentDictionary<string, int> teamInformation)...
public static void parseStrings(StreamReader sr, string recievedLine, out string pTeamName,
out string pAnswer)...
static void findInteractionType(out string interactionType, string clientString)...
}
Credit to Andrey Polyakov in comments.
"Thread stops if executing method returns. You should run infinite loop in such method for avoid thread termination" in regards to the clientInteraction() method.

UDPClient.Receive() stops any code from running

I'm trying to create a simple game using the XNA Framework. I'm starting to implement multiplayer over LAN. Everything has been going well but now I'm running into a problem with UDPClient.Receive.
When the server is running, it is supposed to have two listeners(using UDPClient.Receive), on different ports. One listener is waiting for any incoming connection requests for people who want to join the game and respond accordingly. The other listens for constant updates on the player's positions so it can keep all players' views synchronised. The problem is that I don't know how to code in the first listener.
When the listener for connection request starts, all the code freezes, and it doesn't start until that listener will receive something. How would I code it so it is just running in the background?
Here is my code for the connection listener:
public class Connect
{
public static void WaitForConnections()
{
UdpClient udpc2 = new UdpClient(2054);
IPEndPoint ep = null;
Random rnd = new Random();
Console.WriteLine("Waiting for connections...");
byte[] joinrequest = udpc2.Receive(ref ep);
if (Encoding.ASCII.GetString(joinrequest) == "join")
{
Console.WriteLine("Attempting to join");
if (Server.ConnectedPlayers.Count < Server.MaxPlayers)
{
byte[] newShooter = DataControls.ClassToByteArray(new ShooterObject(Server.ConnectedPlayers.Count + 1, new Vector2(((Server.ConnectedPlayers.Count + 1) * 100) + 22, 70), new byte[3] { (byte)rnd.Next(255), (byte)rnd.Next(255), (byte)rnd.Next(255) }));
udpc2.Send(newShooter, newShooter.Length, ep);
Console.WriteLine("Joined successfully");
}
else
{
byte[] error = Encoding.ASCII.GetBytes("full");
udpc2.Send(error, error.Length, ep);
Console.WriteLine("Too many players");
}
}
}
}
You need to use a background worker thread or equivalent (look at Task and threads generally) but to help you get going in basic full example:
using System;
using System.ComponentModel;
using System.Threading;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main()
{
// Create our listener and start listening...
var sammpleListener = new SampleListener();
sammpleListener.StartListening();
// Run forever...
Console.WriteLine("Waiting for players to join...");
Console.WriteLine("Press Ctrl+C to stop!");
for (var counter = 1;; counter++)
{
Console.WriteLine("Main thread working: {0}...", counter);
Thread.Sleep(200);
}
}
internal class SampleListener
{
private readonly BackgroundWorker _udpWaitForPlayer;
public SampleListener()
{
_udpWaitForPlayer = new BackgroundWorker();
_udpWaitForPlayer.DoWork += _udpWaitForPlayer_DoWork;
}
public void StartListening()
{
_udpWaitForPlayer.RunWorkerAsync();
}
private void _udpWaitForPlayer_DoWork(object sender, DoWorkEventArgs e)
{
const int junkSample = 10;
for (var i = 1; i <= junkSample; i++)
{
// Notice how this doesn't make the main thread sleep / hang...
Console.WriteLine("Background worker working: {0} of {1}...", i, junkSample);
Thread.Sleep(1000);
}
Console.WriteLine("Background worker: Finished!");
}
}
}
}

Mono: AutoResetEvent nonexpected behaviour

I use HttpListener class for simple multitheading HTTP server for Long Polling actions. I use AutoResetEvents and WaitHandle.WaitAny for signal messaging between threads. Application works fine on .NET 4.5. But we have some problem with multithreading after porting application on Mono (version 3.2.8 (Debian 3.2.8+dfsg-4ubuntu1)).
We expected when second HTTP request is received by server handling of first HTTP request should be finish. And so on. But in Mono handling of first request finish only by timeout.
The simplified code of my application is below.
class Program
{
private static AutoResetEvent autoEvent = new AutoResetEvent(false);
private static AutoResetEvent autoEvent2 = new AutoResetEvent(false);
public static void Main()
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:2999/");
listener.Start();
Console.WriteLine("Listening...");
BeginGetContext(listener);
Console.ReadLine();
}
public static void BeginGetContext(HttpListener listener)
{
Console.WriteLine("BeginGetContext...");
while (listener.IsListening)
{
var asyncResult = listener.BeginGetContext(ListenerCallback, listener);
asyncResult.AsyncWaitHandle.WaitOne();
}
}
public static void ListenerCallback(IAsyncResult result)
{
Console.WriteLine("ListenerCallback...");
autoEvent.Set();
autoEvent.Reset();
HttpListener listener = (HttpListener)result.AsyncState;
HttpListenerContext context = listener.EndGetContext(result);
// some code
//...
int res = WaitHandleNext();
if (res == 0 || res == 1)
{
// Never get this line
Console.WriteLine("Done...");
}
else if (res == WaitHandle.WaitTimeout)
{
// Always here
Console.WriteLine("Done by timeout");
}
}
private static int WaitHandleNext()
{
Console.WriteLine("WaitHandleNext...");
int waitResult = WaitHandle.WaitAny(new[] { autoEvent, autoEvent2 }, TimeSpan.FromSeconds(30), false);
return waitResult;
}
}
If I put Thread.Sleep(10) between autoEvent.Set and autoEvent.Reset I get expected behaviour but not always.
autoEvent.Set();
Thread.Sleep(10);
autoEvent.Reset();
I don't know it is expected behaviour of Mono, bug in Mono or my application bug.
How can I reach behaviour of my application on Mono such on .Net? Any workarounds or other help would be great.

Update main thread from worker without a dispatcher

This have probably been asked before, but I cant find the right answer.
I have a dll that runs a pipe in it's own thread. I use that dll in a Unity project, but the messages I push to Unity end up as exception, due to I don't call them from the main thread. So I need some help implementing this right. Here's how I start the background worker:
var worker = new BackgroundWorker();
worker.DoWork += (sender, e) =>
{
var client = new NamedPipeClientStream(".", "kinect-pipe", PipeDirection.In);
client.Connect();
while (_isWorkerRunning)
{
using (var sr = new StreamReader(client))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
// TODO send message to Unity in main thread
}
}
if (!client.IsConnected)
{
client.Connect();
}
}
client.Flush();
client.Close();
client.Dispose();
};
worker.RunWorkerAsync();
My pipe client runs in a thread, I have a public event that fires the messages to Unity. But i need to ensure the messages is dispatched. And I am not sure how to do this the right way?
I found a simple solution, where I use a shared buffer across the threads. So my pipe look like this:
private void PipeClientWorker()
{
//Client
var client = new NamedPipeClientStream(".", "kinect-pipe", PipeDirection.In);
client.Connect();
while (_isWorkerRunning)
{
using (var sr = new StreamReader(client))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
// TODO figure out how to do this in the right thread
if (KinectHandler != null)
{
KinectHandler.BeginInvoke(temp, null, null);
}
}
}
if (!client.IsConnected)
{
client.Connect();
}
}
client.Flush();
client.Close();
}
And I start it normally:
var thread = new Thread(PipeClientWorker) {Name = "Pipe Worker Thread", IsBackground = true};
thread.Start();
In Unity I've created a KinectController that puts the messages in a stack, and in the Update loop pops them to a single LastMessage string:
public string LastMessage;
private KinectReader _kinectReader;
private volatile Stack<string> _messageStack;
// Use this for initialization
void Start ()
{
_messageStack = new Stack<string>();
LastMessage = "";
// init Kinect Reader
_kinectReader = new KinectReader();
_kinectReader.StartPipeReader();
_kinectReader.KinectHandler += _kinectReader_KinectHandler;
}
void _kinectReader_KinectHandler(string message)
{
_messageStack.Push(message);
}
// Update is called once per frame
void Update ()
{
// Update Last message
while (_messageStack.Any())
{
LastMessage = _messageStack.Pop();
Debug.Log(LastMessage);
}
}
void OnApplicationQuit()
{
Debug.Log("Stoping the pipe client");
_kinectReader.Stop();
Debug.Log("Qutting application");
}
If anyone have similar issues or have solved it different I would like to discuss the solution :)
Try Thread Ninja. With it you can run background jobs in a coroutine style.

How do I stop SocketException: "A blocking operation was interrupted by a call to WSACancelBlockingCall" from being thrown?

Could you help me to get rid of this exception:
System.Net.Sockets.SocketException: "A blocking operation was
interrupted by a call to WSACancelBlockingCall"
What the below code does: sends UDP message to the server and fetches reply
(NAK or ACK)
Code that throws exception: m_receiveBytes = m_receiver.Receive(ref m_from);
Code:
public partial class _Default : System.Web.UI.Page
{
static readonly object lockScheduleIem = new object();
IPAddress m_AddressSend;
IPAddress m_AddressRecieve;
int m_groupPortSend;
int m_groupPortReceive;
IPEndPoint m_IPAddressSend;
IPEndPoint m_IPAddressReceive;
Byte[] m_receiveBytes;
Thread m_thread;
UdpClient m_receiver;
ManualResetEvent m_mre;
UdpClient m_sender;
IPEndPoint m_from;
protected void Page_Init(object sender, EventArgs e)
{
m_AddressSend = IPAddress.Parse("10.43.60.177");
m_AddressRecieve = IPAddress.Parse("10.43.60.99");
int.TryParse("60200", out m_groupPortSend);
int.TryParse("206", out m_groupPortReceive);
m_IPAddressSend = new IPEndPoint(m_AddressSend, m_groupPortSend);
m_IPAddressReceive = new IPEndPoint(m_AddressRecieve, m_groupPortReceive);
m_mre = new ManualResetEvent(false);
m_from = new IPEndPoint(IPAddress.Any, 0);
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
try
{
TimeSpan timeout;
timeout = new TimeSpan(0, 0, 0, 0, 5000);
m_sender = new UdpClient();
m_receiveBytes = null;
m_receiver = new UdpClient(m_IPAddressReceive);
m_thread = new Thread(new ThreadStart(ThreadProc));
m_thread.Start();
string str = string.Empty;
using (StreamReader sr = new StreamReader(#"C:\UDPmsgArchive\UDPmsg_Of_2011_10_18_13_7_33_968_634545400539687500.xml"))
str = sr.ReadToEnd();
byte[] XMLbytes = Encoding.ASCII.GetBytes(str);
m_sender.Send(XMLbytes, XMLbytes.Length, m_IPAddressSend);
m_mre.WaitOne(timeout, true);
m_mre.Reset();
m_receiver.Close();
if (m_receiveBytes != null)
Response.Write(Encoding.ASCII.GetString(m_receiveBytes, 0, m_receiveBytes.Length));
else
Response.Write("string.Empty");
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
}
public void ThreadProc()
{
try
{
m_receiveBytes = m_receiver.Receive(ref m_from); // ERROR HERE
m_mre.Set();
m_receiver.Close();
}
finally
{
m_mre.Set();
}
}
}
If I'm reading your code right, you're starting a thread to receive a UDP message. If it receives the message, it sets an event. The main thread starts the thread and then waits up to five seconds for the event to be set. If the event isn't set within that time, the main thread destroys the receiver that the thread is waiting on.
That's definitely going to throw an exception.
If you wait to eliminate the exception, modify your ThreadProc
try
{
// do stuff here
}
catch (SocketException) // or whatever the exception is that you're getting
{
}
I would suggest that you not include the m_mre.Set() call in a finally section. The main thread calls Reset on the event after the wait has completed, whether or not there is a timeout. If the thread calls Set in the finally, the the event's state will be set if a timeout occurs, because the following happens:
main thread calls Reset()
main thread calls Close() on the client
ThreadProc calls Set() in the finally
Instead, change your main thread code to look like this:
if (m_mre.WaitOne(timeout, true))
{
// event was set by the thread proc
// process the received data
// and reset the event
m_mre.Reset();
}
else
{
// A timeout occurred.
// Close the receiver
m_receiver.Close();
}
That said, you really don't have to spin up a thread to do this. Rather, you could use the asynchronous capabilities of UdpClient. Something like:
// Set timeout on the socket
m_receiver.Client.ReceiveTimeout = 5000;
try
{
IAsyncResult ir = m_receiver.BeginReceive(null, null);
m_receivedBytes = m_receiver.EndReceive(ir, m_receiver.Client.RemoteEndPoint);
// process received bytes here
}
catch (SocketException)
{
// Timeout or some other error happened.
}

Categories

Resources