When I use F11 debug, NetStatus value is true, but when I use F5 debug, NetStatus value is false. Why? How do I fix it?
I don't know what time the _connect value changes.
Is this a multi-threading synchronization issue?
namespace conn
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
class Program
{
static void Main(string[] args)
{
wait_conn();
}
private static void wait_conn()
{
bool NetStatus = false;
string DataS = "127.0.0.1";
CheckIpConn conn = new CheckIpConn();
conn.CheckIp(DataS);
//Thread.Sleep(3000);
NetStatus = conn.Connected;
if (!NetStatus)
Console.WriteLine(conn.Connected.ToString());
Console.Read();
}
}
public class CheckIpConn
{
private int _port = 135;
private volatile bool _connect;
private IPEndPoint _iPEndPoint;
private TcpClient _client;
private TimerCallback _timerCallBack;
private System.Threading.Timer _timer;
public bool Connected
{
get { return _connect; }
}
public void CheckIp(string Ip)
{
_iPEndPoint = new IPEndPoint(IPAddress.Parse(Ip), _port);
_timerCallBack = new TimerCallback(CheckConnect);
_timer = new System.Threading.Timer(_timerCallBack, null, 10, 1000);
_timer.Dispose();
}
public void CheckConnect(object o)
{
try
{
_client = new TcpClient();
_client.Connect(_iPEndPoint);
_connect = true;
_client.Close();
}
catch
{
_connect = false;
}
}
}
}
Your code is extremely unclear - it looks like you're trying to do things asynchronously, but doing so badly. For example, you're creating a Timer and then immediately disposing of it.
When stepping line by line in the debugger, that may work - because the timer may get to fire before the Dispose call... but when you just run the code, you're disposing of the timer before it gets a chance to fire. Additionally, you're using the value of conn.Connected immediately after calling CheckIp - so if the timer did fire, it would probably be after you'd checked the value anyway.
I would strongly advise you to just do the check synchronously. Get that working and then consider an asynchronous approach.
You create a timer which executes a function on the threadpool - so you don't really have much of a gurantee that when CheckIP returns the timer callback has been exececuted.
Furthermore: Why do you dispose of the timer as soon as you created it? While MSDN states that a callback can occur after dispose because the callback is queued this is certainly a bad style. Also this means that you are only checking once - so you might as well do it synchroneously - especially wait_conn indicates that it should wait until a connection has been established.
Also: TcpClient is disposable so you should do:
using (var client = new TcpClient())
{
client.Connect(_iPEndPoint);
_connect = true;
client.Close();
}
There is no point having a member variable in the class if you do not do anything with it anyway.
Related
I attached two of the following scripts to a single GameObject.
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class TestScript : MonoBehaviour
{
static UdpClient udp;
private string udp_message = "";
Thread thread;
public int port = 8888;
void Start()
{
udp = new UdpClient(port);
thread = new Thread(new ThreadStart(ThreadMethod));
thread.Start();
}
// Update is called once per frame
void Update()
{
string port_string = port.ToString();
Debug.Log(port_string + ":" + udp_message);
}
void ThreadMethod()
{
while (true)
{
try
{
IPEndPoint remoteEP = null;
byte[] data = udp.Receive(ref remoteEP);
udp_message = Encoding.ASCII.GetString(data);
}
catch
{
}
}
}
}
Then, I used 8888 as the port for one script, as shown in the following image. The other script used port 8889.
I am using two different ports on 8888 and 8889.
However, when I send data to only the 8888 port, the UDP on the 8889 port also seems to be responding.
What is the cause of this?
How can I fix it?
Well your udp field is static!
Both instances of your component overwrite it with different references in
udp = new UdpClient(port);
So basically whichever script runs last "wins" and you are only ever using that UdpClient instance.
Later both your threads will access the very same udp reference for doing
udp.Receive(...);
Simply do not make you field static and you should be fine ^^
private UdpClient udp;
And to your empty catch block ... I would at least make it
catch(Exception e)
{
Debug.LogException(e);
}
which displays an error in the console but doesn't interrupt the thread.
And then also make sure to clean up!
private void OnDestroy()
{
thread?.Abort();
udp?.Dispose();
}
otherwise you might end up with zomby threads or blocked UDP ports ;)
I have been following an old tutorial for making a chat program and I have been dissecting it to fit into a new form, although I have gotten it to work as it was intended it runs into the error: "Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall."
that points to this part of the code.
while (Connected)
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
I only get the error upon closing the client, or disconnecting.
this is the majority of the client code.
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;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace Table_Top_RPG
{
public partial class Connect : Form
{
// Will hold the user name
private string UserName = "Unknown";
public static StreamWriter swSender;
private StreamReader srReceiver;
private TcpClient tcpServer;
// Needed to update the form with messages from another thread
private delegate void UpdateLogCallback(string strMessage);
// Needed to set the form to a "disconnected" state from another thread
private delegate void CloseConnectionCallback(string strReason);
private Thread thrMessaging;
private IPAddress ipAddr;
private bool Connected;
public Connect()
{
// On application exit, don't forget to disconnect first
Application.ApplicationExit += new EventHandler(OnApplicationExit);
InitializeComponent();
}
private void BtnConnect_Click(object sender, EventArgs e)
{
// If we are not currently connected but awaiting to connect
if (Connected == false)
{
InitializeConnection();
}
else // We are connected, thus disconnect
{
CloseConnection("Disconnected at user's request.");
}
}
// The event handler for application exit
public void OnApplicationExit(object sender, EventArgs e)
{
if (Connected == true)
{
// Closes the connections, streams, etc.
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
}
private void InitializeConnection()
{
// Parse the IP address from the TextBox into an IPAddress object
ipAddr = IPAddress.Parse(Connect.IpBox.Text);
// Start a new TCP connections to the chat server
tcpServer = new TcpClient();
tcpServer.Connect(ipAddr, int.Parse(Connect.PortBox.Text));
// Helps us track whether we're connected or not
Connected = true;
// Prepare the form
UserName = Connect.NameBox.Text;
// Disable and enable the appropriate fields
IpBox.Enabled = false;
NameBox.Enabled = false;
Main.TxtMsg.Enabled = true;
Connect.BtnConnect.Text = "Disconnect";
// Send the desired username to the server
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(UserName);
swSender.Flush();
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
private void ReceiveMessages()
{
// Receive the response from the server
srReceiver = new StreamReader(tcpServer.GetStream());
// If the first character of the response is 1, connection was successful
string ConResponse = srReceiver.ReadLine();
// If the first character is a 1, connection was successful
if (ConResponse[0] == '1')
{
// Update the form to tell it we are now connected
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { "Connected Successfully!" });
}
else // If the first character is not a 1 (probably a 0), the connection was unsuccessful
{
string Reason = "Not Connected: ";
// Extract the reason out of the response message. The reason starts at the 3rd character
Reason += ConResponse.Substring(2, ConResponse.Length - 2);
// Update the form with the reason why we couldn't connect
this.Invoke(new CloseConnectionCallback(this.CloseConnection), new object[] { Reason });
// Exit the method
return;
}
// While we are successfully connected, read incoming lines from the server
while (Connected)
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
}
internal void CloseConnection(string Reason)
{
// Show the reason why the connection is ending
Main.ChatLog.AppendText(Reason + "\r\n");
// Enable and disable the appropriate controls on the form
IpBox.Enabled = true;
NameBox.Enabled = true;
Main.TxtMsg.Enabled = false;
BtnConnect.Text = "Connect";
// Close the objects
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
// This method is called from a different thread in order to update the log TextBox
private void UpdateLog(string strMessage)
{
// Append text also scrolls the TextBox to the bottom each time
Main.ChatLog.AppendText(strMessage + "\r\n");
}
}
}
there is another form called Main where all the chat dialog is sent, but the majority of its code is not relevant.
if anyone knows a better way to handle this or knows of a good chat program tutorial i can go through for better examples of how clients connect and disconnect is handled properly without crashing I would be much appreciative.
You should probably think about using Asynchronous programming, where there are no blocking calls.
The problem is, as you surely know, that you close your client while there is an active call.
I'm pretty sure NetworkStream and StreamReader/Writer does have some asynchronous methods. Try to look at some here:
http://msdn.microsoft.com/en-us/library/system.io.streamreader.readasync.aspx
I believe you need to close and dispose each stream per use in your case because you are performing them synchronously. Consider using the using statement for writing...and do something similar for reading. Plus don't forget to remove them from the CloseConnection...
using (NetworkStream ns=tcpServer.GetStream())
{
swSender = new StreamWriter(ns);
swSender.WriteLine(UserName);
swSender.Flush();
ns.Close();
ns.Dispose();
swSender = null;
}
I am using Named Pipes to communicate with a process. I have been able to make it work with the following code. (Original code found here : via archive.org )
class ProgramPipeTest
{
public void ThreadSenderStartClient(object obj)
{
// Ensure that we only start the client after the server has created the pipe
ManualResetEvent SyncClientServer = (ManualResetEvent)obj;
using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".","ToSrvPipe",PipeDirection.Out,PipeOptions.None))
{
// The connect function will indefinately wait for the pipe to become available
// If that is not acceptable specify a maximum waiting time (in ms)
pipeStream.Connect();
Console.WriteLine("[Client] Pipe connection established");
using (StreamWriter sw = new StreamWriter(pipeStream))
{
sw.AutoFlush = true;
string temp;
Console.WriteLine("Please type a message and press [Enter], or type 'quit' to exit the program");
while ((temp = Console.ReadLine()) != null)
{
if (temp == "quit") break;
sw.WriteLine(temp);
}
}
}
}
public void ThreadStartReceiverClient(object obj)
{
// Ensure that we only start the client after the server has created the pipe
ManualResetEvent SyncClientServer = (ManualResetEvent)obj;
using (NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", "FromSrvPipe", PipeDirection.In, PipeOptions.None))
{
// The connect function will indefinately wait for the pipe to become available
// If that is not acceptable specify a maximum waiting time (in ms)
pipeStream.Connect();
Console.WriteLine("[ClientReceiver] Pipe connection established");
using (StreamReader sr = new StreamReader(pipeStream))
{
// Display the read text to the console
string temp;
while ((temp = sr.ReadLine()) != null)
{
Console.WriteLine("Received from server: {0}", temp);
}
}
}
}
static void Main(string[] args)
{
// To simplify debugging we are going to create just one process, and have two tasks
// talk to each other. (Which is a bit like me sending an e-mail to my co-workers)
ProgramPipeTest Client = new ProgramPipeTest();
Thread ClientThread = new Thread(Client.ThreadSenderStartClient);
Thread ReceivedThread = new Thread(Client.ThreadStartReceiverClient);
ClientThread.Start();
ReceivedThread.Start();
}
}
Everything works as intended. I am able to issue commands to my target process (audacity).
My issue is, I basically want to wrap a C# GUI around this code, but am not sure how to modify it so that the communication is done without having to use the console, as commands would be issued via the GUI or from the code.
I have tried turning the streamWriter sw into a class variable, exposing it via property and calling sw.WriteLine() with a method, but that doesn't seem to work.
So I am unsure how to encapsulate the stream back and forth nicely within an object.
I found this article which seemed like it was spot on, Using Named Pipes to Connect a GUI to a Console App in Windows, but unfortunately it does not seem to come with any code and is kind of over my head without any to refer to.
So how can I use named pipes without having to use the console to issue the commands ?
What you want to do is take the main pieces of logic which are the sender, the receiver out of that code and rewrite it into a re-usable class that can be used like a purpose-specific wrapper class.
Perhaps the code below could serve as a guideline (I have NOT checked to see if this works, it might require minor changes)
public sealed class ResponseReceivedEventArgs : EventArgs
{
public ResponseReceivedEventArgs(string id, string response)
{
Id = id;
Response = response;
}
public string Id
{
private set;
get;
}
public string Response
{
private set;
get;
}
}
public delegate void ResponseReceived(object sender, ResponseReceivedEventArgs e);
public sealed class NamedPipeCommands
{
private readonly Queue<Tuple<string, string>> _queuedCommands = new Queue<Tuple<string,string>>();
private string _currentId;
private readonly Thread _sender;
private readonly Thread _receiver;
// Equivalent to receiving a "quit" on the console
private bool _cancelRequested;
// To wait till a response is received for a request and THEN proceed
private readonly AutoResetEvent _waitForResponse = new AutoResetEvent(false);
// Lock to modify the command queue safely
private readonly object _commandQueueLock = new object();
// Raise an event when a response is received
private void RaiseResponseReceived(string id, string message)
{
if (ResponseReceived != null)
ResponseReceived(this, new ResponseReceivedEventArgs(id, message));
}
// Add a command to queue of outgoing commands
// Returns the id of the enqueued command
// So the user can relate it with the corresponding response
public string EnqueueCommand(string command)
{
var resultId = Guid.NewGuid().ToString();
lock (_commandQueueLock)
{
_queuedCommands.Enqueue(Tuple.Create(resultId, command));
}
return resultId;
}
// Constructor. Please pass in whatever parameters the two pipes need
// The list below may be incomplete
public NamedPipeCommands(string servername, string pipeName)
{
_sender = new Thread(syncClientServer =>
{
// Body of thread
var waitForResponse = (AutoResetEvent)syncClientServer;
using (var pipeStream = new NamedPipeClientStream(servername, pipeName, PipeDirection.Out, PipeOptions.None))
{
pipeStream.Connect();
using (var sw = new StreamWriter(pipeStream) { AutoFlush = true })
// Do this till Cancel() is called
while (!_cancelRequested)
{
// No commands? Keep waiting
// This is a tight loop, perhaps a Thread.Yield or something?
if (_queuedCommands.Count == 0)
continue;
Tuple<string, string> _currentCommand = null;
// We're going to modify the command queue, lock it
lock (_commandQueueLock)
// Check to see if someone else stole our command
// before we got here
if (_queuedCommands.Count > 0)
_currentCommand = _queuedCommands.Dequeue();
// Was a command dequeued above?
if (_currentCommand != null)
{
_currentId = _currentCommand.Item1;
sw.WriteLine(_currentCommand.Item2);
// Wait for the response to this command
waitForResponse.WaitOne();
}
}
}
});
_receiver = new Thread(syncClientServer =>
{
var waitForResponse = (AutoResetEvent)syncClientServer;
using (var pipeStream = new NamedPipeClientStream(servername, pipeName, PipeDirection.In, PipeOptions.None))
{
pipeStream.Connect();
using (var sr = new StreamReader(pipeStream))
// Do this till Cancel() is called
// Again, this is a tight loop, perhaps a Thread.Yield or something?
while (!_cancelRequested)
// If there's anything in the stream
if (!sr.EndOfStream)
{
// Read it
var response = sr.ReadLine();
// Raise the event for processing
// Note that this event is being raised from the
// receiver thread and you can't access UI here
// You will need to Control.BeginInvoke or some such
RaiseResponseReceived(_currentId, response);
// Proceed with sending subsequent commands
waitForResponse.Set();
}
}
});
}
public void Start()
{
_sender.Start(_waitForResponse);
_receiver.Start(_waitForResponse);
}
public void Cancel()
{
_cancelRequested = true;
}
public event ResponseReceived ResponseReceived;
}
You can see that I have created abstractions for the Console.ReadLine (the command queue) and Console.WriteLine (the event). The "quit" is also a boolean variable that is set by the "Cancel()" method now. Obviously this isn't the most optimal/correct way of doing it - I am just showing you one way to relate the imperative code from above into a wrapper class that can be re-used.
I'm writing a C# program that runs two IRC connections at once.
The connections are threaded, and each thread starts like so:
MainThread = new Thread(new ThreadStart(StartMainProcessor));
MainThread.IsBackground = false;
MainThread.Start();
private void StartMainProcessor() {
MainProcessor.Bot.Connect();
//while (true) { }
}
Bot.Connect() looks like this (somewhat abridged version):
public void Connect() {
try {
Client.Connect(IRCHelper.SERVER, IRCHelper.PORT);
}
catch (CouldNotConnectException e) {
Reconnect(true);
return;
}
try {
Client.Listen();
}
catch (Exception e) {
Reconnect(false);
return;
}
}
This works fine until the bot disconnects (which will always happen eventually, it's the nature of IRC).
When it disconnects, Reconnect() is called, which starts a timer. When that timer expires the bot is meant to then call Connect() again. The reason for the timer is that an IRC server will refuse an immediate reconnection sometimes.
However, once the Connect() method has ended, the Thread ends, and the program (console application) exits. (Client.Listen() is blocking)
I had previously overcome this problem by adding while (true) { } in StartMainProcessor()... But this eats up 100% CPU, and I'd really prefer a different solution.
Thank you for your help. :)
Sounds like you need a signaling construct. For example, you could use something like an AutoResetEvent to block the thread calling Reconnect, i.e. call Reconnect, start the timer and then block the thread. Then set the auto reset event in the timer expired event handler to allow the thread to continue (unblock) and call Connect.
I'm not a fan of spinning the processor - wastes huge amounts of CPU resources when you add infinite loops or sleeps in loops.
Why don't you just Thread.Sleep inside Bot.Reconnect? That would keep your thread alive and wake it up when ready to call Bot.Connect again.
You might want to try something like that
private bool canExitThread;
private void StartMainProcessor()
{
while (canExitThread)
{
//do the magic here
System.Threading.Thread.Sleep(1); //make sure you allow thread to do the job, otherwise you will get 100 cpu usage
//do the connecting, disconnecting, listening
}
}
Also can you check if Client is connected? if so then you should be checking that within the main loop and if it's disconnected - call the connect method.
Hope that gives you an idea how to do it.
Also have a look the the article below, which might explain things a little bit more.
http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
how about something like this
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace Server
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting server..");
foreach (var connection in new[] {new Connection(TimeSpan.FromSeconds(1)), new Connection(TimeSpan.FromSeconds(1))})
ThreadPool.QueueUserWorkItem(connection.Connect);
Console.WriteLine("Server running. Press Enter to quit.");
Console.ReadLine();
}
}
public class Connection //might be good to implement IDisposable and disconnect on Dipose()
{
private readonly TimeSpan _reConnectionPause;
public Connection(TimeSpan reConnectionPause)
{
_reConnectionPause = reConnectionPause;
}
//You probably need a Disconnect too
public void Connect(object state)
{
try
{
//for testing assume connection success Client.Connect(IRCHelper.SERVER, IRCHelper.PORT);
Debug.WriteLine("Open Connection");
}
catch (Exception)
{
//You might want a retry limit here
Connect(state);
}
try
{
//Client.Listen();
//Simulate sesison lifetime
Thread.Sleep(1000);
throw new Exception();
}
catch (Exception)
{
Debug.WriteLine("Session end");
Thread.Sleep(_reConnectionPause);
Connect(state);
}
}
}
}
I presume you have a Main method, so why don't we start there:
private static readonly MAX_NUM_BOTS = 2;
static void Main(string[] args)
{
List<Thread> ircBotThreads = new List<Thread>();
for(int numBots = 0; numBots < MAX_NUM_BOTS; numButs++)
{
Thread t = new Thread(()=>{StartMainProcessor();});
t.IsBackground = false;
t.Start();
ircBotThreads.Add(t);
}
// Block until all of your threads are done
foreach(Thread t in ircBotThreads)
{
t.Join();
}
Console.WriteLine("Goodbye!");
}
private static void StartMainProcessor()
{
MainProcessor.Bot.Connect();
}
Then you can do something like this:
// 30 second time out (or whatever you want)
private static readonly TimeSpan TIMEOUT = TimeSpan.FromSeconds(30.0);
// specify the maximum number of connection attempts
private static readonly int MAX_RECONNECTS = 10;
public void Connect()
{
bool shouldListen = false;
// This is your connect and re-connect loop
for(int i = 0; i < MAX_RECONNECTS; i++)
{
try
{
Client.Connect(IRCHelper.SERVER, IRCHelper.PORT);
shouldListen = true;
}
catch (CouldNotConnectException e)
{
// It's OK to sleep here, because you know exactly
// how long you need to wait before you try and
// reconnect
Thread.Sleep((long)TIMEOUT.TotalMilliseconds);
shouldListen = false;
}
}
while(shouldListen)
{
try
{
Client.Listen();
}
catch (Exception e)
{
// Handle the exception
}
}
}
This is a very rough draft, but the concept is that you keep trying to reconnect until you fail. Once you connect, then you listen (I presume you listen for something in IRC) and you process the data until you decide that you no longer need to be doing that work.
I have a simple server that waits for a client to connect, reads the incoming stream, and sends a message back. What I would like to do is have every connection handled by a separate thread. This is my first time working with sockets and threads in C#, and most of the examples I have found are really confusing, so any help or simple examples would be much appreciated.
Here is what I have right now.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
[STAThread]
static void Main(string[] args)
{
TestServer ts = new TestServer();
ts.Start();
}
class TestServer
{
private readonly int port = 48888;
private readonly IPAddress ip = IPAddress.Parse("127.0.0.1");
private TcpListener listener;
public TestServer()
{
this.listener = new TcpListener(this.ip, this.port);
}
public void Start()
{
this.listener.Start();
Console.WriteLine("Server Running...");
Socket s;
Byte[] incomingBuffer;
int bytesRead;
Byte[] Message;
while (true)
{
s = this.listener.AcceptSocket();
incomingBuffer = new Byte[100];
bytesRead = s.Receive(incomingBuffer);
string message = "Hello from the server";
Message = Encoding.ASCII.GetBytes(message.ToCharArray());
s.Send(Message);
}
}
}
Try this:
public void Start()
{
this.listener.Start();
Console.WriteLine("Server running...");
while (true)
{
Socket s = this.listener.AcceptSocket();
ThreadPool.QueueUserWorkItem(this.WorkMethod, s);
}
}
private void WorkMethod(object state)
{
using (Socket s = (Socket)state)
{
byte[] buffer = new byte[100];
int count = s.Receive(buffer);
string message = "Hello from the server";
byte[] response = Encoding.ASCII.GetBytes(message);
s.Send(response);
}
}
Not answering your question directly, but ...
Thread pools are not about 'new thread per connection', they are about having some meaningful number of threads (with some relation to number of cores on the box) already running and waiting for work. This "work" is given to the pool by the producer thread (the one accepting the connections in your case) via one or more queues.
Please note that this is not always the best solution though. Take a look at C10K and at Hight Performance Server Architecture pages.
Use a threadpool. You can use instantiate threads manually but since you have might have a huge number of connections, a threadpoool is more efficient.
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(processMessage), socket);
processMessage is the method that will process the message. And there will be one thread per connection. Really simple actually.