I choose not the use the asynchronous calls since it requires a callback, I'm just curious if there's a way to solve this by utilizing Unix-alike non-blocking socket method: Poll(), as Asyn is created specifically for the Windows environment. I'm researching if this could be done without asynchronous.
To be noted: NON-BLOCKING != ASYNCHRONOUS:)
Therefore I have the following approach by turning off the blocking flag of socket & Poll() method:
try
{
IPEndPoint hostEp = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);
Socket hostSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
hostSock.Blocking = false;
hostSock.Connect(hostEp);
}
catch (Win32Exception se)
{
if (ex.ErrorCode == 10035) // WSAEWOULDBLOCK is expected, means connect is in progress
while (true)
{
Console.WriteLine("Connecting in progress");
bool connected = hostSock.Poll(1000000, SelectMode.SelectWrite);
if (connected)
{
Console.WriteLine("Connected");
break;
}
}
}
But then SelectMode.SelectWrite doesn't seems reinitiates an connection attempts for me. So, what's the problem? And how could I solve this? Should I use Select() instead of Poll()?
Just use the asynchronous methods (ConnectAsync()), they're meant for this. Don't use exceptions for program logic.
You can synchronously Connect() a TCP socket without blocking:
Manual:
The Connect method will block, unless you specifically set the Blocking property to false prior to calling Connect. If you are using a connection-oriented protocol like TCP and you do disable blocking, Connect will throw a SocketException because it needs time to make the connection.
You can use SocketException.ErrorCode to obtain the specific error code. After you have obtained this code, refer to the Windows Sockets version 2 API error code documentation in the MSDN library for a detailed description of the error.
If the error returned WSAEWOULDBLOCK, the remote host connection has been initiated by a connection-oriented Socket, but has not yet completed successfully. Use the Poll method to determine when the Socket is finished connecting.
But that is exactly what your code does, so that should just work.
You can use threads or tasks in order to launch the Connect without blocking the main thread.
This will add complexity if interaction with UI (WinForms / WPF) is needed, due to the Cross-Thread protection.
Also you can use a BackgroundWorker to avoid this issues.
Actually, your code is working on my system. However, you need of course a server which accepts your TCP connection. If you do not have that, then you will wait forever. So I guess you are missing a server.
I had the exact question, but for me the answer was rather silly: my code had the stock code for fetching the IpAddress from a string (from microsoft):
var ipHostInfo = Dns.GetHostEntry(hostname);
return ipHostInfo.AddressList[0];
This was all and good, but my tests was testing against "127.0.0.1:9000", which for some reason gnerated the ip address of my actual ethernet connection. Changing the parsing mechanism to:
if (hostname.Equals("localhost"))
{
return IPAddress.Parse("127.0.0.1");
}
try
{
return IPAddress.Parse(hostname);
}
catch (FormatException e)
{
var ipHostInfo = Dns.GetHostEntry(hostname);
return ipHostInfo.AddressList[0];
}
did the trick (at least for me!)
Related
in one of my projects I have implemented a small HTTP server to stream the video data of a connected webcam. For this task I'm utilizing the System.Net.Sockets.TcpListener from .NET Framework 4.5, which listens to a pre-configured endpoint and uses the AcceptSocketAsync() mtehod to wait for incomming requests. You can see the relevant code parts below:
this.server = new TcpListener(endpoint);
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, 0));
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.server.Start();
...
this.listenTask = Task.Factory.StartNew(this.Listen);
...
private async void Listen()
{
try
{
while (this.server.Server.IsBound)
{
Socket socket = await this.server.AcceptSocketAsync();
if (socket == null)
{
break;
}
Task.Factory.StartNew(() => this.ClientThread(socket));
}
}
catch (ObjectDisposedException)
{
Log.Debug("Media HttpServer closed.");
}
}
This works fine, when I start the application and the HTTP server is started for the first time. However, when I stop the HTTP server (done via CheckBox in the settings of the application) the unverlying listening socket is sometimes not closed. When I check for the state of the sockets via console (netstat -ano) I can see that the socket is still in state LISTENING. The resulting problem is, when I restart the HTTP server again I get an System.Net.Sockets.SocketException with the message "Only one usage of each socket address is normally permitted", which is not surprising.
The relevant code part for stopping the HTTP server is as follows:
...
if (this.server != null)
{
if (this.server.Server != null)
{
if (this.server.Server.Connected)
{
this.server.Server.Shutdown(SocketShutdown.Both);
this.server.Server.Disconnect(true);
}
this.server.Server.Close();
}
this.server.Stop();
}
...
I also keep track of my open connections and close them after finishing the transmission of data and when stopping the server. None of the connection sockets stays opened, so I believe only the listening socket should be relevant for this problem.
I already tried various combinations/orders of the Shutdown(), Disconnect(), Close() and Stop() methods when stopping the server, as well as setting/unsetting several options when starting the server like Linger and ReuseAddress, which sometimes seemed to fix the problem at first, but then a few days later the problem occurred again.
I also tried to "force" the listening socket to close when stopping the server using GetTcpTable(...) and SetTcpEntry(...) from iphlpapi.dll, as described in this question: How to close a TCP connection by port?
Unfortunately, this approach did not work for me (it change anything about the state of the listening socket at all).
As I'm a little bit clueless of what else I could do, I'm asking here if somebody has an idea of what might cause the discribed problem or how to solve it. Any help would be greatly appreciated.
Kind regards,
Chris
You should almost always leave TcpListener.Server alone. It's there so you can set socket options on it, not use it for control purposes.
So your Listen should be:
private async void Listen()
{
try
{
while (true)
{
Socket socket = await this.server.AcceptSocketAsync();
if (socket == null)
{
break;
}
Task.Run(() => this.ClientThread(socket));
}
}
catch (ObjectDisposedException)
{
Log.Debug("Media HttpServer closed.");
}
}
(assuming you do actually want one thread per client, an architecture I do not recommend in general).
When you're ready to stop, just stop:
if (this.server != null)
{
this.server.Stop();
}
If you do not have any special requirement, it is suggested to make use of TcpListener class and its methods only or if you have such requirement, do not use TcpListener and start with the Raw socket.
TcpListener class is self sufficient to provide method like
Start(), AcceptTcpClient() and Stop().
You can create a List<TcpClient> and loop through each client and call client.close() after calling Stop() on the TcpListener instance.
A very good example of client server communication is on MSDN:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener(v=vs.110).aspx
Regards
On server socket, shutdown & disconnect is not needed for listening sockets. Those calls are needed only for connected sockets. Replace the socket stop with below code:
if (this.server != null)
{
if (this.server.Server != null)
{
this.server.Server.Close();
this.server.Server = NULL;
}
}
I would dispose of your socket connections once you have closed them. The documentation says they should be disposed after closed but personally I like to say when to dispose of anything that use the IDisposable interface.
I am experimenting in creating a small IRC server to learn some new programming concepts (and others I haven't used in forever). The first step is to get a basic client connecting via TCP to send plaintext commands to the server.
To listen for connection I have the following code:
public NetworkClient(Server server, TcpClient socket, int id)
{
_socket = socket;
_id = id;
_server = server;
}
private async void ListenForClients()
{
int numClients = 0;
while (IsRunning)
{
var tcpClient = await _listener.AcceptTcpClientAsync();
var netClient = new NetworkClient(this, tcpClient, numClients);
netClient.Start();
Console.WriteLine("Client Connected");
numClients++;
}
}
Then in my NetworkClient class my Start() method looks like:
public async void Start()
{
using (var reader = new StreamReader(_socket.GetStream()))
{
while (_server.IsRunning)
{
var line = await reader.ReadLineAsync();
Console.WriteLine("Client {0} wrote: {1}", _id, line);
}
}
}
This works well while a telnet client is connected, however once I close my telnet client reader.ReadLineAsync(); constantly returns null. I would add a check to see if line == null but I'm not sure that is the correct way to detect if a client has disconnected.
To make matters worse, _socket.Connected is constantly returning true all while nulls are getting "received" by reader.ReadLineAsync().
What is the proper way to detect when tcp clients have been disconnected?
A read on a TCP/IP socket will return 0 bytes when the connection has been gracefully closed. This situation causes ReadLineAsync to return null. So, yes, you should check for null and treat it as a graceful socket closure.
Sockets may be closed other ways, too; any socket operation may throw an exception if the socket is abortively closed. If the exception happens at an acceptable part of the protocol (where a close is not considered an error), then you should treat that exception as though it were a graceful closure as well.
Oh, and TcpClient.Connected (like Socket.Connected) is practically useless; it only tells you whether the socket was connected, not whether it is connected. Just pretend that property doesn't exist.
Finally, a couple of notes:
Avoid async void. If your methods return Task, then you have a "handle" to see when they complete (and whether they raised exceptions). My recent MSDN article explains why async void is not recommended.
It's best to periodically send data over the connection to determine if it is still viable. I wrote a TCP/IP .NET sockets FAQ that covers this in more detail.
I'm writing a server for a game, and I want to be able to handle thousands of concurrent users. For this reason, I went with non-blocking sockets and use the poll method. However, I do create multiple threads to handle database and web calls, and some of these threads will send a response to the user. In one of these threads, on send, I get the error "A non-blocking socket operation could not be completed immediately". What could cause this problem? I imagine it's because a poll is occurring at the same time as send is called. If I used beginAsync, would it take stop this error? I thought about locking the socket, but I don't want my main thread to be blocked for this.
I don't know what kind of non-blocking-polling socket calls are you using, but I would recommend that you use the Async socket calls (instead of the Begin). For more information on the difference between Async calls vs Begin see: What's the difference between BeginConnect and ConnectAsync?
The asynchronous calls automatically do "polling" on the OS level, which will be much more efficient than your polling. As a matter of fact, they use IO completion ports, which are probably the fastest and most efficient thing you can use on Windows to handle a large amount of client connections/requests.
As far as the error, I would consider this to be the normal operation of non-blocking sockets, so you just have to handle it gracefully.
Update
Your server should probably do something like this:
// Process the accept for the socket listener.
private void ProcessAccept(SocketAsyncEventArgs e)
{
Socket s = e.AcceptSocket;
if (s.Connected)
{
try
{
SocketAsyncEventArgs readEventArgs = this.readWritePool.Pop();
if (readEventArgs != null)
{
// Get the socket for the accepted client connection and put it into the
// ReadEventArg object user token.
readEventArgs.UserToken = new Token(s, this.bufferSize);
Interlocked.Increment(ref this.numConnectedSockets);
Console.WriteLine("Client connection accepted.
There are {0} clients connected to the server",
this.numConnectedSockets);
if (!s.ReceiveAsync(readEventArgs))
{
this.ProcessReceive(readEventArgs);
}
}
else
{
Console.WriteLine("There are no more available sockets to allocate.");
}
}
catch (SocketException ex)
{
Token token = e.UserToken as Token;
Console.WriteLine("Error when processing data received from {0}:\r\n{1}",
token.Connection.RemoteEndPoint, ex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
// Accept the next connection request.
this.StartAccept(e);
}
}
Code sample courtesy of code project: http://www.codeproject.com/Articles/22918/How-To-Use-the-SocketAsyncEventArgs-Class
When a non-blocking socket tries to read data but finds none you get that error: the socket would like to wait for data but can't because it has to return immediately, being non-blocking.
I'd suggest you switch to blocking sockets, find out why data is missing, adjust accordingly then revert to non-blocking ones. Or, you could handle the error and retry the operation.
I was also receiving this exception on sending data and just found the solution.
You get the exception because the socket's send buffer is full. Because you are trying to send the data via a non-blocking send, the exception is raised to let you know that you MUST send it via a blocking send.
The data is not sent once the exception is raised, so you have to resend it. Your individual send call now becomes;
try
{
m_socket.Send(buffer, bufferSize, SocketFlags.None);
}
catch (SocketException e)
{
if(e.SocketErrorCode == WouldBlock)
{
m_socket.Blocking = true;
m_socket.Send(buffer, bufferSize, SocketFlags.None);
m_socket.Blocking = false;
}
}
It would also be a good idea to increase the socket's SendBufferSize. By default I think it is 8kb. For my needs I had to increase it to 2MB, and afterwards the Send call no longer threw that exception.
This exception is too general. Per MSDN,
If you receive a SocketException, use the SocketException.ErrorCode property to obtain the specific error code. After you have obtained this code, refer to the Windows Sockets version 2 API error code documentation in the MSDN library for a detailed description of the error.
Sockets error codes are here.
I'm having some problems reusing a server socket in a test application I've made. Basically, I have a program that implements both the client side and the server side. I run two instances of this program for testing purposes, one instance starts to host and the other connects. This is the listening code:
private void Listen_Click(object sender, EventArgs e)
{
try
{
server = new ConnectionWrapper();
HideControls();
alreadyReset = false;
int port = int.Parse(PortHostEdit.Text);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, port);
server.connection.Bind(iep); // bellow explanations refer to this line in particular
server.connection.Listen(1);
server.connection.BeginAccept(new AsyncCallback(OnClientConnected), null);
GameStatus.Text = "Waiting for connections on port " + port.ToString();
}
catch (Exception ex)
{
DispatchError(ex);
}
}
private void OnClientConnected(IAsyncResult iar)
{
try
{
me = Player.XPlayer;
myTurn = true;
server.connection = server.connection.EndAccept(iar); // I will only have one client, so I don't care for the original listening socket.
GameStatus.Text = server.connection.RemoteEndPoint.ToString() + " connected";
StartServerReceive();
}
catch (Exception ex)
{
DispatchError(ex);
}
}
This works fine the first time. However, after a while (when my little game ends), I call Dispose() on the server object, implemented like this:
public void Dispose()
{
connection.Close(); // connection is the actual socket
commandBuff.Clear(); // this is just a StringBuilder
}
I also have this in the object constructor:
public ConnectionWrapper()
{
commandBuff = new StringBuilder();
connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
connection.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
}
I get no error when I click the Listen button a second time. The client side connects just fine, however my server side does not detect the client connection a second time, which basically renders the server useless anyway. I'm guessing it's connecting to the old, lingering socket, but I have no idea why this is happening to be honest. Here's the client connection code:
private void Connect_Click(object sender, EventArgs e)
{
try
{
client = new ConnectionWrapper();
HideControls();
alreadyReset = false;
IPAddress ip = IPAddress.Parse(IPEdit.Text);
int port = int.Parse(PortConnEdit.Text);
IPEndPoint ipe = new IPEndPoint(ip, port);
client.connection.BeginConnect(ipe, new AsyncCallback(OnConnectedToServer), null);
}
catch (Exception ex)
{
DispatchError(ex);
}
}
If I do netstat -a in CMD, I see that the port I use is still bound and its state is LISTENING, even after calling Dispose(). I read that this is normal, and that there's a timeout for that port to be "unbound".
Is there a way I can force that port to unbind or set a very short timeout until it automatically gets unbound? Right now, it only gets unbound when I exit the program. Maybe I'm doing something wrong in my server? If so, what could that be? Why does the client connect fine, yet the server side doesn't detect it a second time?
I could make the socket always listen, not dispose it, and use a separate socket to handle the server connection, which would probably fix it, but I want other programs to be able to use the port between successive play sessions.
I remember seeing another question asking this, but there was no satisfactory answer for my case there.
There may be a couple of reasons why the port would stay open, but I think you should be able to resolve your issue by using an explicit LingerOption on the socket:
LingerOption lo = new LingerOption(false, 0);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
This basically turns the socket shutdown into an abortive shutdown instead of a graceful shutdown. If you want it to be graceful but just not wait as long, then use true in the constructor and specify a small but nonzero value for the timeout.
I just noticed this line, which is almost undoubtedly part of your problem:
server.connection = server.connection.EndAccept(iar); // I will only have one client, so I don't care for the original listening socket.
The comment you've written here is, well, wrong. Your wrapper class really shouldn't allow connection to be written to at all. But you cannot simply replace the listening socket with the client socket - they're two different sockets!
What's going to happen here is that (a) the listening socket goes out of scope and therefore never gets explicitly closed/disposed - this will happen at a random time, possibly at a nasty time. And (b) the socket that you do close is just the client socket, it will not close the listening socket, and so it's no wonder that you're having trouble rebinding another listening socket.
What you're actually witnessing isn't a socket timeout, it's the time it takes for the garbage collector to realize that the listening socket is dead and free/finalize it. To fix this, you need to stop overwriting the listening socket; the Dispose method of your wrapper class should dispose the original listening socket, and the client socket should be tracked separately and disposed whenever you are actually done with it.
In fact, you should really never need to rebind another listening socket at all. The listening socket stays alive the whole time. The actual connection is represented by just the client socket. You should only need to dispose the listening socket when you finally shut down the server.
I agree with the previous answer, you should also "shutdown" to allow any existing activity to complete and then close the socket flagging it for reuse...
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(true);
I have a server that listens for a connection on a socket:
public class Server
{
private Socket _serverSocket;
public Server()
{
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, 1234));
_serverSocket.Listen(1);
}
public void Start()
{
_serverSocket.BeginAccept(HandleAsyncConnectionMethod, null);
}
public void Stop()
{
//????? MAGIC ?????
}
//... rest of code here
}
What is the correct (clean) way to close down the socket?
Is it sufficient to call:
_serverSocket.Disconnect(true);
in the Stop() method? or is there other work that needs to happen to close the connection cleanly?
TCP connection termination correctly involves a four-way handshake. You want both ends to inform the other that they're shutting down and then acknowledge each other's shutdown.
Wikipedia explains the process: http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_termination
This post explains how to make it happen in C#: http://vadmyst.blogspot.com/2008/04/proper-way-to-close-tcp-socket.html
2 ways to close it properly without exceptions
1) create temporary connecting socket and connect it to listening one so it could have its handler triggered then just finish it with normal EndAccept and after that close both.
2) just Close(0) listening socket which will result in false shot to its callback, if you then look into your listening socket you will see that its state is "closed" and "disposed". This is why calling EndAccept would cause exception. You may just ignore it and do not call EndAccept. Listening socket will go down immediately without timeout.
Since you are listening for incoming TCP connections, you could use System.Net.Sockets.TcpListener which does have a Stop() method. It does not have asynchronous operations though.
The cleanest way to have Accept call break immediately is to call _serverSocket.Dispose();
Any other call to methods in the like of Shutdown or Disconnect will throw an exception.
First, you need to make sure you're keeping track of any client sockets that were created in the process of BeginAccept. Shut those down first using the Socket.Shutdown() and Socket.Close() methods. Once those have all been shut down then do the same on the listening socket itself.
That should handle it...but if you need to make absolutely sure, you could always kill it with fire:
Not for sockets, but same idea applies., which is to close it in every way possible, then finally set the socket to null.
You should use Socket.Shutdown() and then Socket.Close(). Socket.Disconnect() is usually only used if you intend on reconnecting the same socket.