I made a server-client program with auto connection.
But the program only works if I first start the server application because the client needs to connect.
My goal is for the client to check with a delay of 2 seconds if the server is already created.
I made a while statement for a trial and error cycle
try
{
int a = 1;
while (a == 1)
{
cliente.Connect(IP_End);
if (cliente.Connected)
{
connectRead();
a = 2;
}
else
{
while (!cliente.Connected)
{
int milliseconds = 2000;
Thread.Sleep(milliseconds);
cliente.Connect(IP_End);
MessageBox.Show(text);
if (cliente.Connected)
{
connectRead();
}
}
}
}
}
catch(SocketException se)
{
MessageBox.Show(se.Message);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
the error is :
No connection can be made because the target computer actively refused them 192.168.254.28:100
the method is here :
private void connectRead()
{
STW = new StreamWriter(cliente.GetStream());
STR = new StreamReader(cliente.GetStream());
STW.AutoFlush = true;
backgroundWorker1.RunWorkerAsync();
backgroundWorker1.WorkerSupportsCancellation = true;
}
Based on the code you almost got it right. I believe the "Connect" extension method should update the value within the client. If it does the way I'd do it would be to introduce a separate method that returns a boolean and it would help to simplify the code. For example:
private bool ConnectClient(SomeClient clientToConnect, IPAddress ipToConnectTo, int delay)
{
System.Threading.Thread.Sleep(delay);
clientToConnect.Connect(ipToConnectTo);
return clientToConnect.Connected;
}
try
{
bool successfulConnection;
while (!successfulConnection)
{
successfulConnection = ConnectClient(yourClient, "10.10.10.10", 2000);
}
}
catch
{
// ...
}
Without knowing more about errors or desired functionality, I can tell you will call connectRead(); twice if you hit the second loop. To fix this replace your second loop with this:
while (!cliente.Connected)
{
int milliseconds = 2000;
Thread.Sleep(milliseconds);
cliente.Connect(IP_End);
if (cliente.Connected)
{
connectRead();
a = 2;
}
}
EDIT:
I also took out the MessageBox because that seems unnecessary and will pause the program until you hit Ok on the MessageBox.
EDIT 2:
Question on actively refused connections
Question on determination of open port
Related
I want to make connection conformation
what I have now is
internal bool connect(remoteIP)
{
if ( network.startping(RemoteIP))
{
peer1.write("Hello!") ---> waits for "connected" until time out
if (Isconnected) return true
}
else
{
try again after few sec with finite number of repeats
}
return false
}
1) what can I do to wait
I saw a way with Task wait = new task.factory(()=> doDwaiting())
with I think can work , but I I'm missing some logic here
2) how can I make the return
i think I can Do it with int Counter and goto but it deosnt look like the "good" way to go
what can I do?
I've used the BeginConnect from the TcpClient class to verify the connection is valid. A System.Timer object would be used to reconnect if the connection failed. An example of a connection method would be as follows:
public void Connect(IPAddress ipAddress, int port, double reconnectInterval)
{
_reconnectTimer = new Timer { Interval = _reconnectInterval, Enabled = false, AutoReset = false };
_reconnectTimer.Elapsed += ReconnectTimer_Elapsed;
_tcpClient = new TcpClient();
try
{
_tcpClient.BeginConnect(ipAddress, port, ConnectionRequestCallback, null);
}
catch (Exception exception)
{
LostConnection(exception.Message);
}
}
The LostConnection method is called when there is any type of connection failure. The responsibility of the LostConenction method is to start the timer.
_reconnectTimer.Start();
Finally the timer's callback calls the same code shown above to attempt a new connection to the remote host.
Connect(_endPoint.Address, _endPoint.Port, _reconnectTimer.Interval);
}
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 windows service which runs and starts a thread which listen/receive heartbeat via tcp/ip. i'm having a hard time finding ways to sync between getting information from the tcp thread and using that value to update something in the main thread.
i try to use a thread.sleep method and keep on looping it for a few times while awaiting the answer back from the thread and then getting the value, but that method seems to be a bit volatile with the method sometimes working and sometimes not.
so what's a good way to sync between these two?
basically what i want to do is to start the listening tcp thread, get specific value and the update the main program.
attached are the receive function and the function which i used to start the thread.
p.s: i'm a totally noobie when it comes to tcp/ip and c# so any comments on any part of the code or the design is more than welcome :)
public virtual void Receive()
{
string eventMessage = string.Empty;
int bytesRcvd = 0;
int totalBytesRcvd = 0;
byte[] byteBuffer = new byte[maxBufferSize];
NetworkStream listenStream;
try
{
if (client.Connected)
{
listenStream = client.GetStream();
}
else
{
return;
}
while (true)
{
//message that is slot in from the object will get sent here.
if (!string.IsNullOrEmpty(MessageToSend))
{
Send(MessageToSend);
MessageToSend = string.Empty;
}
// must convert it back and look for the delimiter, cannot wait for the three heartbeat to pass
string leftoverMsg = string.Empty;
bytesRcvd = listenStream.Read(byteBuffer, totalBytesRcvd, maxBufferSize - totalBytesRcvd);
totalBytesRcvd += bytesRcvd;
//if more than heart beat size, can process to see if it's a heartbeat and proceed to send
if (totalBytesRcvd > msgHeartbeatSize)
{
eventMessage = Encoding.ASCII.GetString(byteBuffer, 0, totalBytesRcvd);
ProcessMessage(eventMessage, ref leftoverMsg, ref totalBytesRcvd, ref byteBuffer);
}
}
}
catch (ThreadAbortException thEx)
{
//do nothing as main thread has aborted and waiting to close
logger.Info(Thread.CurrentThread.Name + " is stopped. ");
}
catch (Exception exce)
{
bIsActive = false;
logger.Error(exce);
CleanUp();
}
finally
{
logger.Info(String.Format("Thread {0} Exiting. ", Thread.CurrentThread.Name));
}
}
public virtual void StartReceivingThread()
{
Thread thrReceive = new Thread(Receive);
try
{
if (!bIsActive && Connect())
{
//NOTE: exception thrown by a thread can only be captured by that thread itself
//start a listen thread
//wait until heartbeat message is accepted
thrReceive.Name = "thr" + serviceType.Name;
thrReceive.Start();
bIsActive = true;
//wait to get the heartbeat message
for (int i = 0; i < maxRetry; i++)
{
Thread.Sleep(maxTimeOutValue);
if (bIsReceivingHeartbeat)
break;
}
//if nothing happens close the connection and try again
if (!bIsReceivingHeartbeat)
{
bIsActive = false;
CleanUp();
logger.Info("Closing receiver thread - " + thrReceive.Name);
}
else
{
logger.Info("Starting receiver thread - " + thrReceive.Name);
}
}
}
catch(Exception ex)
{
logger.Error(ex);
}
//finally
//{
// logger.Info("Exiting receiver thread - " + thrReceive.Name);
//}
}
I assume bIsReceivingHeartbeat is a bool member variable of the class. If the value changed in one thread (receiver) is not visible in the other thread this is most likely due to memory barrier. I am saying this from my Java background but this is most likely true in .net as well.
Try declaring the variables volatile or use a property and make the getter and setter synchronized:
private bool bIsReceivingHeartbeat;
public bool IsReceivingHeartbeat
{
[MethodImpl(MethodImplOptions.Synchronized)]
get { return bIsReceivingHeartbeat; }
[MethodImpl(MethodImplOptions.Synchronized)]
set { bIsReceivingHeartbeat = value; }
}
And in the calling code:
if (!IsReceivingHeartbeat) ....
I am writing from Java background but the situation most likely similar
(Looks like you also posted this code in refactormycode.com.)
Anyway, instead of the loop with a sleep delay, I recommend using an Event object that pulsed by the code that sets IsReceivingHeartbeat. See the ManualResetEvent and AutoResetEvent classes in MSDN.
We're using named pipes to communicate between a C# .Net service and a native C++ application. The service creates a message mode pipe, then kicks off a timer.
m_pipeServer = new NamedPipeServerStream ("Cyber_Srv_EventPipe",
PipeDirection.InOut,
1,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous,
4096,
4096,
pipeSa);
m_OutputQueue = new List<My_Message>();
In the timer tick routine is the main service loop, which looks like this:
do
{
if (!m_bClientAttached)
{
try
{
m_pipeServer.WaitForConnection ();
m_bClientAttached = true;
}
catch (InvalidOperationException invope)
{
sDebug = string.Format ("Pipe wait exception InvOpEx: {0}",
invope.Message);
DebugMessage (sDebug);
}
}
// the message-pumping part of the loop.
if (m_bClientAttached)
{
try
{
if (!m_bReadInProgress)
{
m_bReadInProgress = true;
m_pipeServer.BeginRead (byNewRead, 0, byNewRead.GetLength (0),
new AsyncCallback (this.PipeReadComplete),
m_iReadCount);
}
if (m_OutputQueue.Count () > 0)
{
if (!m_bWriteInProgress)
{
m_bWriteInProgress = true;
My_Message opmsg = m_OutputQueue.ElementAt (0);
m_pipeServer.BeginWrite (opmsg.ToByteArray (), 0,
(int)(opmsg.MsgLength),
new AsyncCallback (this.PipeWriteComplete),
m_iWriteCount);
}
}
}
catch (IOException ioe)
{
sDebug = string.Format ("Main loop raised exception: {1}",
ioe.Message);
DebugMessage (sDebug);
DetachClientPipe();
}
Thread.Sleep(1);
}
} while (m_bRunning);
m_pipeServer.Close ();
}
The read and write completion routines look like this:
private void PipeReadComplete (IAsyncResult iAR)
{
string sDebug;
int iByteCount;
My_Message ipmsg = new My_Message();
try
{
iByteCount = m_pipeServer.EndRead (iAR);
if (iByteCount > 0)
{
ipmsg.FromByteArray(byNewRead);
m_bReadInProgress = false;
... process message ...
}
else
{
try
{
DebugMessage ("PRC: Zero bytes read, disconnect pipe");
DetachClientPipe();
}
catch (InvalidOperationException invope)
{
sDebug = string.Format ("PRC - Pipe disconnect exception: {0}",
invope.Message);
DebugMessage (sDebug);
}
}
}
catch (IOException e)
{
sDebug = string.Format ("PRC: Read {0} raised exception: {1}",
(int)(iAR.AsyncState),
e.Message);
DebugMessage (sDebug);
DetachClientPipe();
}
}
// ------------------------------------------------------------------
private void PipeWriteComplete (IAsyncResult iAR)
{
string sDebug;
try
{
m_pipeServer.EndWrite (iAR);
lock (m_OutputQueue)
{
m_OutputQueue.RemoveAt(0);
}
m_bWriteInProgress = false;
}
catch (IOException e)
{
sDebug = string.Format ("Write {0} raised exception: {1}",
(int)(iAR.AsyncState),
e.Message);
DebugMessage (sDebug);
DetachClientPipe();
}
}
// ------------------------------------------------------------------
private void DetachClientPipe()
{
if (m_pipeServer.IsConnected)
{
m_pipeServer.Disconnect();
}
m_bClientAttached = false;
}
The client side code is known good code, re-used. So here's the problem. The client can connect fine. We then shut down the client, everything is fine. We start it up and conect again. All fine, then we close it and start it again. Boom - error 231, pipe busy. the server will now generate pipe busy errors on any connection attempt until hell freezes over, or we restart the service. Then we're back to two connections again.
I've been staring at this code for three straight days now, and I have no idea why it does this. I can't seem to see the wood for the trees, and I could use a fresh pair of eyes or three. Problem is no-one else in the team knows much of any C#.
Update
The reason this fails on the third connect attempt appears to be that on the first disconnect the PipeReadComplete returns and I get zero bytes read, so I detach the pipe and all is well. BUT... on the second disconnection, PipeReadComplete does NOT get called, so I don't force the disconnect. Weird.
Bob, for a quick fix: was wondering, have you tried setting the server instance parameter to more than 1 and see if it still fails after 2 tries? Instead of 1, put 10 and see if it will help things. Also, it will help if you post the unmanaged code as well. I'm currently doing the same thing, windows service plus unmanaged dll IPC.
m_pipeServer = new NamedPipeServerStream ("Cyber_Srv_EventPipe",
PipeDirection.InOut,
10,
PipeTransmissionMode.Message,
PipeOptions.Asynchronous,
4096,
4096,
pipeSa);
Or you actually need to have only one server pipe instance at all times?
Please see this related question for a possible answer. It appears Suma experienced and solved the same issue, and while not in C#, it should be pretty easy to translate.
I've written a very complex multi-server IRC bot recently, and have encountered an issue..
I have stripped down the code as much as I could which can be viewed here.
My issue is that when I call the Disconnect() the connection is voided instead of disconnecting and closing the given server. It also just freezes the calling class instead of stopping the correct instance of the Class.
Any help or experience with a similar issue would be greatly appreciated.
Please include code if you can.
First off, you need to add a break so that this:
foreach (Connection connect in connections)
{
if (searching == true)
{
if (connect.SERVERID == ServerID)
{
connect.Stop();
isFound = true;
searching = false;
connections.Remove(connect);
}
}
}
Becomes:
foreach (Connection connect in connections)
{
if (connect.SERVERID == ServerID)
{
connect.Stop();
isFound = true;
connections.Remove(connect);
break;
}
}
Because you are modifying the collection, rather than using the searching == true clause. Much more efficient.
Next, I would change your thread run to look like this:
public void Run()
{
bool WhileOn = true;
NetworkStream stream;
string inputLine;
StreamReader reader;
try
{
using(TcpClient irc = new TcpClient(SERVER, PORT))
{
...
}
}
catch (ThreadAbortException)
{
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Thread.Sleep(5000);
}
}
So that your connection gets properly disposed. You should do similarly for your stream.
And finally, I would add an Abort() call on your thread in the Stop function after a set timeout. If a TCP socket is blocked by the OS, however, I'm not sure if an abort call will interrupt it...