Client Thread throwing a state exception and stopping C# - 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.

Related

Multiple Backgroundworkers with HttpListeners in c#

I am writing a simple server program, where I want to instantiate many "listeners" at the same time, so my requests are not processed sequentially but in parallel. I thought I could make a number of BackgroundWorker() instances, which would create an HttpListener() , like this (in my main function):
private static List<BackgroundWorker> _backgroundWorkers = new List<BackgroundWorker>();
static void Main(string[] args)
{
var numW = 5;
foreach (var w in Enumerable.Range(0, numW))
{
_backgroundWorkers.Add(new BackgroundWorker());
_backgroundWorkers[w].DoWork += _backgroundWorkers_DoWork;
_backgroundWorkers[w].RunWorkerCompleted += _backgroundWorkers_RunWorkerCompleted;
//start worker's server
lock(_backgroundWorkers[w])
_backgroundWorkers[w].RunWorkerAsync();
}
}
And the _backgroundWorkers_DoWork function just calls the following function:
public static void StartServer()
{
var httpListener = new HttpListener();
var server = new Server(httpListener, _url, ProcessResponse);
server.Start();
}
But my main program just ends right away. Any tips ?

C# Socket Multithreading Lambda

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();
}
}

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!");
}
}
}
}

Why does my streamreader and writer suddenly stop working?

Ok, so I'm attempting to create a simple Chat application over TCP/IP for a group of friends of mine who play DnD online. Eventually I want to add more features, but for now I just want the chat to work!!
Here is the code I have for the Main Server
class MainServer
{
IPAddress m_address = IPAddress.Parse("127.0.0.1");
Int32 m_port = 5550;
public static Hashtable userNicknames = new Hashtable(50);
public static Hashtable connectionToNick = new Hashtable(50);
public MainServer()
{
TcpListener listener = new TcpListener(m_address, m_port);
Thread listenThread = new Thread(new ParameterizedThreadStart(StartListening));
listenThread.Start(listener);
Console.WriteLine("Listening for incoming connection requests...");
}
private void StartListening(Object listener)
{
TcpListener server = (TcpListener)listener;
ClientCommCenter commC;
server.Start();
while (true)
{
if (server.Pending())
{
TcpClient client = server.AcceptTcpClient();
Console.WriteLine("Client has connected...");
commC = new ClientCommCenter(client);
}
}
}
public static void SendSystemMessage(string msg)
{
StreamWriter writer;
TcpClient[] connectedClients = new TcpClient[MainServer.userNicknames.Count];
MainServer.userNicknames.Values.CopyTo(connectedClients, 0);
for (int ii = 0; ii < connectedClients.Length; ii++)
{
try
{
if (msg.Trim().Equals(String.Empty))
continue;
writer = new StreamWriter(connectedClients[ii].GetStream());
writer.WriteLine("Message from server: " + msg);
writer.Flush();
writer = null;
}
catch (Exception e)
{
MainServer.userNicknames.Remove(MainServer.connectionToNick[connectedClients[ii]]);
MainServer.connectionToNick.Remove(connectedClients[ii]);
}
}
}
public static void SendMessageToAll(string nickname, string msg)
{
StreamWriter writer;
TcpClient[] connectedClients = new TcpClient[MainServer.userNicknames.Count];
MainServer.userNicknames.Values.CopyTo(connectedClients, 0);
for (int ii = 0; ii < connectedClients.Length; ii++)
{
try
{
if (msg.Trim().Equals(String.Empty))
continue;
writer = new StreamWriter(connectedClients[ii].GetStream());
writer.WriteLine(nickname + ": " + msg);
writer.Flush();
writer = null;
}
catch (Exception e)
{
String user = (string)MainServer.connectionToNick[connectedClients[ii]];
SendSystemMessage("ATTENTION: " + user + " has disconnected from chat");
MainServer.userNicknames.Remove(user);
MainServer.connectionToNick.Remove(connectedClients[ii]);
}
}
}
}
Here is the main communication class, used separately by each client
class ClientCommCenter
{
TcpClient m_client;
StreamReader m_reader;
StreamWriter m_writer;
String m_nickname;
public ClientCommCenter(TcpClient client)
{
m_client = client;
Thread chatThread = new Thread(new ThreadStart(StartChat));
chatThread.Start();
}
private String GetNick()
{
m_writer.WriteLine("Enter a nickname to begin.");
m_writer.Flush();
return m_reader.ReadLine();
}
private void StartChat()
{
m_reader = new StreamReader(m_client.GetStream());
m_writer = new StreamWriter(m_client.GetStream());
m_writer.WriteLine("Connected to DnD Chat!!");
m_nickname = GetNick();
while (MainServer.userNicknames.Contains(m_nickname))
{
m_writer.WriteLine("ERROR!!! Username already in use");
m_nickname = GetNick();
}
MainServer.userNicknames.Add(m_nickname, m_client);
MainServer.connectionToNick.Add(m_client, m_nickname);
MainServer.SendSystemMessage("****** " + m_nickname + " ****** has joined the chat!");
m_writer.WriteLine("Now connected....");
m_writer.Flush();
Thread startChatting = new Thread(new ThreadStart(runChat));
startChatting.Start();
}
private void runChat()
{
try
{
String clientMessage = String.Empty;
while(true){
clientMessage = m_reader.ReadLine();
MainServer.SendMessageToAll(m_nickname, clientMessage);
}
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
}
And finally, here is the code for the Client class:
public partial class MainForm : Form
{
[DllImport("kernel32.dll")]
private static extern void ExitProcess(int a);
TcpClient client;
StreamReader m_reader;
StreamWriter m_writer;
public MainForm()
{
InitializeComponent();
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = false;
Application.Exit();
if (m_reader != null)
{
m_reader.Dispose();
}
ExitProcess(0);
}
private void MainForm_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
SendChat();
}
}
private void SendChat()
{
TextBox txtChat = (TextBox)chatEntry;
if (chatEntry.Lines.Length >= 1)
{
m_writer.WriteLine(txtChat.Text);
m_writer.Flush();
chatEntry.Text = String.Empty;
chatEntry.Lines = null;
}
}
private void RunChat()
{
StreamReader reader = new StreamReader(client.GetStream());
while (true)
{
Application.DoEvents();
if (this.InvokeRequired)
{
this.Invoke(new MethodInvoker( delegate{
RunChat();
}));
}
if (reader.Peek() > 0)
{
chatDisplay.AppendText(reader.ReadLine() + "\r\n");
chatDisplay.SelectionStart = chatDisplay.Text.Length;
}
}
}
private void toolstripConnectButton_Click(object sender, EventArgs e)
{
client = new TcpClient("127.0.0.1", 5550);
m_writer = new StreamWriter(client.GetStream());
m_reader = new StreamReader(client.GetStream());
Thread chatThread = new Thread(new ThreadStart(RunChat));
chatThread.Start();
while (true)
{
Application.DoEvents();
}
}
private void sendButton_Click(object sender, EventArgs e)
{
SendChat();
}
}
The problem that I am having with the above code is this: I can connect to the running server perfectly fine, and I am correctly prompted by the server that I have connected, and it then prompts me for a nickname.
I type the nickname into the text box and press send. After this occurs however, I stop receiving messages from the server all together. Literally nothing. I can even spam the connect button and it constantly shows up with the same two messages:
"Connected"
"Enter a nickname"
I have been trying to figure this out for close to 5 hours now, and I simply have no idea what is going on. I have a feeling it is something incredibly simple, as the solution is ALWAYS simple.
So, generous people of SO, can you figure out my problem? Why does my streamreader and streamwriter suddenly stop working?!?!?!
Two things:
First, skip the if (reader.Peek() > 0). Just call reader.ReadLine(); this will block until you have a line available. I am not sure why, but even after sending the message, Peek is returning -1, but ReadLine returns a line at that point, fixing the problem. Anyway, spinning around on Application.DoEvents() is not helping matters.
(Similarly, you can skip if (server.Pending())).
Second, your use of Invoke is faulty; you should not be "Invoking" RunChat() because that is the method that repeatedly polls the stream for new data. This means you will run the entire method on the UI thread, which is precisely what you want to avoid. The UI is busy pumping the Windows message queue. You should "Invoke" only the code that modifies the control's properties.
(I suspect that is why you found it necessary to use Application.DoEvents() anyway. You shouldn't need it if you are handling your threading correctly.)
(Also, the first thing you should do is to check InvokeRequired. As your method is now, you're creating a StreamReader that you can never use. There are other places where you do that, but that's off topic.)
Here are two suggestions:
private void RunChat()
{
StreamReader reader = new StreamReader(client.GetStream());
Delegate invoker = new Action<string>(AppendChatText);
while (true)
Invoke(invoker, reader.ReadLine());
}
or, to use the more classic "invoke" pattern:
private void RunChat()
{
StreamReader reader = new StreamReader(client.GetStream());
while (true)
AppendChatText(reader.ReadLine());
}
private void AppendChatText(string text)
{
if (this.InvokeRequired)
{
this.Invoke((Action<string>)AppendChatText, text);
return;
}
chatDisplay.AppendText(text + "\r\n");
chatDisplay.SelectionStart = chatDisplay.Text.Length;
}
The first has the advantage of creating only one Delegate object; the second creates a new one each time.
Finally, this is a very C# 1.2 approach to the problem. A more up-to-date approach would use async/await to avoid creating all those threads (not to mention System.Collections.Generic.Dictionary<,> instead of HashTable).

A socket gets delayed from queue after awhile

am trying to use Socket.Select in multi-threaded application , and I don't wanna use async socket , so here is my code :-
public class Server {
private TcpListener m_listener;
private IConnectionFactory m_factory;
private List<Socket> Sockets = new List<Socket>();
private ConcurrentDictionary<Socket, Connection> Clients = new ConcurrentDictionary<Socket, Connection>();
private ConcurrentDictionary<string, ConcurrentQueue<Socket>> Threads = new ConcurrentDictionary<string, ConcurrentQueue<Socket>>();
private int maxsockets = 0;
private object sync = new object();
public Server(string ip, int port, IConnectionFactory factory, int maxsockets) {
IPAddress ipa = IPAddress.Parse(ip);
TcpListener listener = new TcpListener(ipa, port);
this.maxsockets = maxsockets;
m_listener = listener;
m_factory = factory;
int threads = maxsockets <= 100 ? 1 : maxsockets / 100;
for (int i = 0; i < threads; i++) {
Thread th = new Thread(HandelSockets);
th.Name = i.ToString();
Threads.TryAdd(i.ToString(), new ConcurrentQueue<Socket>());
th.Start();
}
}
public void HandelSockets() {
ConcurrentQueue<Socket> queue = Threads[Thread.CurrentThread.Name];
Connection temp;
Socket sock;
while (true) {
try {
lock (sync) {
while (queue.TryDequeue(out sock)) {
if (Clients.TryGetValue(sock, out temp)) {
if (!temp.Alive) {
Sockets.Remove(sock);
Clients.TryRemove(sock, out temp);
} else {
temp.Receive();
Console.WriteLine("recved from thread num : " + Thread.CurrentThread.Name);
}
}
}
}
} catch { }
Thread.Sleep(1);
}
}
public void Run() {
m_listener.Start();
Console.WriteLine("listen started");
Sockets.Add(m_listener.Server);
while (true) {
try {
var temp_list = Sockets.ToList();
Socket.Select(temp_list, null, null, 1000);
foreach (Socket socket in temp_list) {
if (socket == m_listener.Server) {
var sock = m_listener.AcceptSocket();
Sockets.Add(sock);
Connection conn = m_factory.Create(sock);
Clients.TryAdd(sock, conn);
} else if (Clients.Count >= maxsockets) {
Clients[socket].OnMaxConnections();
break;
} else {
if (!Threads.Values.Any(x => x.Contains(socket))) {
var quque = Threads.Values.Where(x => !x.Contains(socket)).OrderBy(x => x.Count).First();
lock (sync) {
quque.Enqueue(socket);
}
}
break;
}
}
} catch {
}
}
}
}
problem is after a while one of the connected sockets will be delayed , one of the sockets will stop sending or receiving until one of the other sockets do so!, or it might take a few secs/minutes until it comeback to receive and send!
I have no clue why would that happen!? maybe the way I select a queue with? , I hope someone can point me to what could make that delay happen thanks.
lock (sync) {
while (queue.TryDequeue(out sock)) {
if (Clients.TryGetValue(sock, out temp)) {
if (!temp.Alive) {
Sockets.Remove(sock);
Clients.TryRemove(sock, out temp);
} else {
temp.Receive();
Console.WriteLine("recved from thread num : " + Thread.CurrentThread.Name);
}
}
}
}
I can't see your implementation of Connection.Receive but if it's a blocking call i.e. doesn't return until it has received data, then that thread would be holding onto a lock on the sync object which is causing your other threads to wait and therefore causing the delay.
Now that you know what is causing the problem you can make the necessary changes, however i highly recommend you use the async methods as it'll perform better and remove the need for locking entirely.
Edit: oh i just realised this is an old question

Categories

Resources