Im trying to connect to my router inside local network. I've used the TcpClient so far.
Check my code:
public static void RouterConnect()
{
TcpClient tcpClient = new TcpClient("192.168.180.1",23); <-- Timeout comes up here
tcpClient.ReceiveTimeout = 2000; // Not working
tcpClient.SendTimeout = 2000; // Also not working
NetworkStream nStream = tcpClient.GetStream(); <-- thought Timeout would raise here
// Further code here. But already tested while commented out.
// So everything else expect the code above shouldnt be relevant.
}
I would like to add a settings-form (router-ip/user/password). Therefore there could be a fail on the user-side where the user types in a not existing host-ip.
The current timeout is at about 20 seconds which is way too high. TcpClient.ReceiveTimeout and TcpClient.SendTimeout arnt the right timeouts to set as I already tried it. Google wasnt helping me out with this.
So, anyone knows how to set the timeout in the right way for this? I've read about async. connections which I wouldnt like to use. A cleaner 1-line-timeout-set would be nice. Possible?
Thanks very much!
Edit 1:
With a closer look while debugging I noticed, the timeout is already raising at the initialization of the tcpClient (as edited above in my code) not as I thought before at .GetStream().
EDIT SOLUTION:
As no one posted the working code from the solution I picked, here it is how its working:
public static void RouterConnect()
{
TcpClient tcpClient = new TcpClient();
if(tcpClient.ConnectAsync("192.168.80.1",23).Wait(TimeSpan.FromSeconds(2)))
{
NetworkStream nStream = tcpClient.GetStream();
}
else
{
MessageBox.Show("Could not connect!");
}
}
The only way i know is to use the Async methods.
There is a nice new async method in .Net 4.5 which returns a Task that you could Wait like this:
tcpClient.ConnectAsync().Wait(timeout)
It returns a false if it doesn't succeed.
Yeah the cleanest way I suppose would be to use the TcpClient.BeginConnect
method.
So you would have a asynchronous feedback whether you could connect to the endpoint or not.
Also see this:
Async Connect
The current constructor overloading method your using is also connecting and thus blocking you until it get connected.
Furthermore, There are no properties on TcpClient to control the TcpClient timeout.
From MSDN: TcpClient(String, Int32)
Initializes a new instance of the TcpClient class and connects to the
specified port on the specified host.
Alternative code from Social MSDN
using (vartcp = new TcpClient())
{
IAsyncResult ar = tcp.BeginConnect("192.168.180.1", 23, null, null);
System.Threading.WaitHandle wh = ar.AsyncWaitHandle;
try
{
if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(2), false))
{
tcp.Close();
throw new TimeoutException();
}
tcp.EndConnect(ar);
}
finally
{
wh.Close();
}
}
Related
I am writing a network layer on top of TCP and I am facing some troubles during my UnitTest phase.
Here is what I'm doing (My library is composed of multiple classes but I only show you the native instructions causing my problems, to limit the size of the post):
private const int SERVER_PORT = 15000;
private const int CLIENT_PORT = 16000;
private const string LOCALHOST = "127.0.0.1";
private TcpClient Client { get; set; }
private TcpListener ServerListener { get; set; }
private TcpClient Server { get; set; }
[TestInitialize]
public void MyTestInitialize()
{
this.ServerListener = new TcpListener(new IPEndPoint(IPAddress.Parse(LOCALHOST), SERVER_PORT));
this.Client = new TcpClient(new IPEndPoint(IPAddress.Parse(LOCALHOST), CLIENT_PORT));
this.ServerListener.Start();
}
// In this method, I just try to connect to the server
[TestMethod]
public void TestConnect1()
{
var connectionRequest = this.ServerListener.AcceptTcpClientAsync();
this.Client.Connect(LOCALHOST, SERVER_PORT);
connectionRequest.Wait();
this.Server = connectionRequest.Result;
}
// In this method, I assume there is an applicative error within the client and it is disposed
[TestMethod]
public void TestConnect2()
{
var connectionRequest = this.ServerListener.AcceptTcpClientAsync();
this.Client.Connect(LOCALHOST, SERVER_PORT);
connectionRequest.Wait();
this.Server = connectionRequest.Result;
this.Client.Dispose();
}
[TestCleanup]
public void MyTestCleanup()
{
this.ServerListener?.Stop();
this.Server?.Dispose();
this.Client?.Dispose();
}
First of all, I HAVE TO dispose the server first if I want to connect earlier to the server on the same port from the same endpoint:
If you run my tests like this, it will run successfully the first time.
The second time, it will throw an exception, in both tests, on the Connect method, arguing the port is already in use.
The only way I found to avoid this exception (and to be able to connect on the same listener from the same endpoint) is to provoke a SocketException within the Server by sending bytes to the disposed client twice (on the first sending, there is no problem, the exception is thrown only on the second sending).
I don't even need to Dispose the Server if I provoke an Exception ...
Why is the Server.Dispose() not closing the connection and freeing the port ??? Is there a better way to freeing the port than by provoking an Exception ?
Thanks in advance.
(Sorry for my English, I am not a native speaker)
Here is an example within a main fonction, to be checkout more easily:
private const int SERVER_PORT = 15000;
private const int CLIENT_PORT = 16000;
private const string LOCALHOST = "127.0.0.1";
static void Main(string[] args)
{
var serverListener = new TcpListener(new IPEndPoint(IPAddress.Parse(LOCALHOST), SERVER_PORT));
var client = new TcpClient(new IPEndPoint(IPAddress.Parse(LOCALHOST), CLIENT_PORT));
serverListener.Start();
var connectionRequest = client.ConnectAsync(LOCALHOST, SERVER_PORT);
var server = serverListener.AcceptTcpClient();
connectionRequest.Wait();
// Oops, something wrong append (wrong password for exemple), the client has to be disposed (I really want this behavior)
client.Dispose();
// Uncomment this to see the magic happens
//try
//{
//server.Client.Send(Encoding.ASCII.GetBytes("no problem"));
//server.Client.Send(Encoding.ASCII.GetBytes("oops looks like the client is disconnected"));
//}
//catch (Exception)
//{ }
// Lets try again, with a new password for example (as I said, I really want to close the connection in the first place, and I need to keep the same client EndPoint !)
client = new TcpClient(new IPEndPoint(IPAddress.Parse(LOCALHOST), CLIENT_PORT));
connectionRequest = client.ConnectAsync(LOCALHOST, SERVER_PORT);
// If the previous try/catch is commented, you will stay stuck here,
// because the ConnectAsync has thrown an exception that will be raised only during the Wait() instruction
server = serverListener.AcceptTcpClient();
connectionRequest.Wait();
Console.WriteLine("press a key");
Console.ReadKey();
}
You may need to restart Visual Studio (or wait some time) if you trigger the bug and the program refuse to let you connect.
Your port is already in use. Run netstat and see. You'll find ports still open in the TIME_WAIT state.
Because you have not gracefully closed the sockets, the network layer must keep these ports open, in case the remote endpoint sends more data. Were it to do otherwise, the sockets could receive spurious data meant for something else, corrupting the data stream.
The right way to fix this is to close the connections gracefully (i.e. use the Socket.Shutdown() method). If you want to include a test involving the remote endpoint crashing, then you'll need to handle that scenario correctly as well. For one, you should set up an independent remote process that you can actually crash. For another, your server should correctly accommodate the situation by not trying to use the port again until an appropriate time has passed (i.e. the port is actually closed and is no longer in TIME_WAIT).
On that latter point, you may want to consider actually using the work-around you've discovered: TIME_WAIT involves the scenario where the status of the remote endpoint is unknown. If you send data, the network layer can detect the failed connection and effect the socket cleanup earlier.
For additional insights, see e.g.:
Port Stuck in Time_Wait
Reconnect to the server
How can I forcibly close a TcpListener
How do I prevent Socket/Port Exhaustion?
(But do not use the recommendation found among the answers to use SO_REUSEADDR/SocketOptionName.ReuseAddress…all that does is hide the problem, and can result in corrupted data in real-world code.)
I've been having some trouble lately while trying to learn how to do an asynchronous receive using visual C#. I have a console based server program that receives data from a client and then sends it back. My problem is on the client side. It has to send data to the server every 100 or so milliseconds and then receive it back.
The problem is getting it back because I can't have the program stop and wait for data. Here's what it looks like so far...
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 16487);
TcpClient client = new TcpClient();
bool blnOnOFF;
private void SendServerData()
{
string strData = "TEST DATA";
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(strData);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
// Ticks Every 100ms
private void tmrDataTransfer_Tick(object sender, EventArgs e)
{
SendServerData();
}
private void btnStart(object sender, EventArgs e)
{
if (blnOnOFF == false)
{
tmrDataTransfer.Start();
blnOnOFF = true;
}
else
{
tmrDataTransfer.Stop();
blnOnOFF = false;
}
}
As you can see, all it does right now is send "TEST DATA". If there is another way to receive the data that is simpler than asynchronous please let me know, also i would like to learn how to do this for future projects.
thanks in advanced.
EDIT: added client sorry i forgot about it
Ok, so, what you need to do is when your app is waiting for incoming data, you need to employ the TcpListener class.
Try this SO answer
The TcpListener class listens for incoming connections, and when it finds one, it creates a TcpClient which does its thing. Meanwhile, the listener has already gone back to looking for new connections. It's pretty much only ever doing just that, and moving the work off to other places.
I think (70% sure) that the TcpClient it creates for a new connection will be operating on a different port than the one your listener is using. You're thus always listening on the same port, while your processing is done on other threads on other ports.
Make sense? I can elaborate more if desired.
I got a strange problem, I never actually expirienced this before, here is the code of the server (client is firefox in this case), the way I create it:
_Socket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
_Socket.Bind( new IPEndPoint( Settings.IP, Settings.Port ) );
_Socket.Listen( 1000 );
_Socket.Blocking = false;
the way i accept connection:
while( _IsWorking )
{
if( listener.Socket.Poll( -1, SelectMode.SelectRead ) )
{
Socket clientSocket = listener.Socket.Accept();
clientSocket.Blocking = false;
clientSocket.SetSocketOption( SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true );
}
}
So I'm expecting it hang on listener.Socket.Poll till new connection comes, but after first one comes it hangs on poll forever. I tried to poll it constantly with smaller delay, let's say 10 microseconds, then it never goes in SelectMode.SelectRead. I guess it maybe somehow related on client's socket reuse? Maybe I don't shutdown client socket propertly and client(firefox) decides to use an old socket?
I disconnect client socket this way:
Context.Socket.Shutdown( SocketShutdown.Both ); // context is just a wrapper around socket
Context.Socket.Close();
What may cause that problem?
Have you considered accepting remote clients asynchronously? I answered a similar question recently on TCPListener, but the same pattern can be used for on the Socket Class.
I have never seen this used before to check if a client is available to connect:
listener.Socket.Poll( -1, SelectMode.SelectRead ) )
I had a look inside the Sockets.TCPListener.Pending() method using .NET reflector and they have this instead, maybe you can try it:
public bool Pending()
{
if (!this.m_Active)
{
throw new InvalidOperationException(SR.GetString("net_stopped"));
}
return this.m_ServerSocket.Poll(0, SelectMode.SelectRead);
}
Just bear in mind that according to MSDN the TCPListener.Pending() method is non-blocking so not sure if it helps you 100%?
I am wondering whether I can set a timeout value for UdpClient receive method.
I want to use block mode, but because sometimes udp will lost packet, my program udpClient.receive will hang there forever.
any good ideas how I can manage that?
There is a SendTimeout and a ReceiveTimeout property that you can use in the Socket of the UdpClient.
Here is an example of a 5 second timeout:
var udpClient = new UdpClient();
udpClient.Client.SendTimeout = 5000;
udpClient.Client.ReceiveTimeout = 5000;
...
What Filip is referring to is nested within the socket that UdpClient contains (UdpClient.Client.ReceiveTimeout).
You can also use the async methods to do this, but manually block execution:
var timeToWait = TimeSpan.FromSeconds(10);
var udpClient = new UdpClient( portNumber );
var asyncResult = udpClient.BeginReceive( null, null );
asyncResult.AsyncWaitHandle.WaitOne( timeToWait );
if (asyncResult.IsCompleted)
{
try
{
IPEndPoint remoteEP = null;
byte[] receivedData = udpClient.EndReceive( asyncResult, ref remoteEP );
// EndReceive worked and we have received data and remote endpoint
}
catch (Exception ex)
{
// EndReceive failed and we ended up here
}
}
else
{
// The operation wasn't completed before the timeout and we're off the hook
}
There is a ReceiveTimeout property you can use.
Actually, it appears that UdpClient is broken when it comes to timeouts. I tried to write a server with a thread containing only a Receive which got the data and added it to a queue. I've done this sort of things for years with TCP. The expectation is that the loop blocks at the receive until a message comes in from a requester. However, despite setting the timeout to infinity:
_server.Client.ReceiveTimeout = 0; //block waiting for connections
_server.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 0);
the socket times out after about 3 minutes.
The only workaround I found was to catch the timeout exception and continue the loop. This hides the Microsoft bug but fails to answer the fundamental question of why this is happening.
you can do like this:
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 5000);
I'm struggling a bit with socket programming (something I'm not at all familiar with) and I can't find anything which helps from google or MSDN (awful). Apologies for the length of this.
Basically I have an existing service which recieves and responds to requests over UDP. I can't change this at all.
I also have a client within my webapp which dispatches and listens for responses to that service. The existing client I've been given is a singleton which creates a socket and an array of response slots, and then creates a background thread with an infinite looping method that makes "sock.Receive()" calls and pushes the data received into the slot array. All kinds of things about this seem wrong to me and the infinite thread breaks my unit testing so I'm trying to replace this service with one which makes it's it's send/receives asynchronously instead.
Point 1: Is this the right approach? I want a non-blocking, scalable, thread-safe service.
My first attempt is roughly like this, which sort of worked but the data I got back was always shorter than expected (i.e. the buffer did not have the number of bytes requested) and seemed to throw exceptions when processed.
private Socket MyPreConfiguredSocket;
public object Query()
{
//build a request
this.MyPreConfiguredSocket.SendTo(MYREQUEST, packet.Length, SocketFlags.Multicast, this._target);
IAsyncResult h = this._sock.BeginReceiveFrom(response, 0, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), this._sock);
if (!h.AsyncWaitHandle.WaitOne(TIMEOUT)) { throw new Exception("Timed out"); }
//process response data (always shortened)
}
private void ARecieve (IAsyncResult result)
{
int bytesreceived = (result as Socket).EndReceiveFrom(result, ref this._target);
}
My second attempt was based on more google trawling and this recursive pattern I frequently saw, but this version always times out! It never gets to ARecieve.
public object Query()
{
//build a request
this.MyPreConfiguredSocket.SendTo(MYREQUEST, packet.Length, SocketFlags.Multicast, this._target);
State s = new State(this.MyPreConfiguredSocket);
this.MyPreConfiguredSocket.BeginReceiveFrom(s.Buffer, 0, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), s);
if (!s.Flag.WaitOne(10000)) { throw new Exception("Timed out"); } //always thrown
//process response data
}
private void ARecieve (IAsyncResult result)
{
//never gets here!
State s = (result as State);
int bytesreceived = s.Sock.EndReceiveFrom(result, ref this._target);
if (bytesreceived > 0)
{
s.Received += bytesreceived;
this._sock.BeginReceiveFrom(s.Buffer, s.Received, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), s);
}
else
{
s.Flag.Set();
}
}
private class State
{
public State(Socket sock)
{
this._sock = sock;
this._buffer = new byte[BUFFER_SIZE];
this._buffer.Initialize();
}
public Socket Sock;
public byte[] Buffer;
public ManualResetEvent Flag = new ManualResetEvent(false);
public int Received = 0;
}
Point 2: So clearly I'm getting something quite wrong.
Point 3: I'm not sure if I'm going about this right. How does the data coming from the remote service even get to the right listening thread? Do I need to create a socket per request?
Out of my comfort zone here. Need help.
Not the solution for you, just a suggestion - come up with the simplest code that works peeling off all the threading/events/etc. From there start adding needed, and only needed, complexity. My experience always was that in the process I'd find what I was doing wrong.
So is your program SUDO outline as follows?
Socket MySocket;
Socket ResponceSocket;
byte[] Request;
byte[] Responce;
public byte[] GetUDPResponce()
{
this.MySocket.Send(Request).To(ResponceSocket);
this.MySocket.Receive(Responce).From(ResponceSocket);
return Responce;
}
ill try help!
The second code post is the one we can work with and the way forward.
But you are right! the documentation is not the best.
Do you know for sure that you get a response to the message you send? Remove the asynchronous behavior from the socket and just try to send and receive synchronously (even though this may block your thread for now). Once you know this behavior is working, edit your question and post that code, and I'll help you with the threading model. Once networking portion, i.e., the send/receive, is working, the threading model is pretty straightforward.
One POSSIBLE issue is if your send operation goes to the server, and it responds before windows sets up the asynchronous listener. If you arent listening the data wont be accepted on your side (unlike TCP)
Try calling beginread before the send operation.