C# while remote TCP connection - c#

I am trying to have a server allow TCP connections and and echo out any newline delimited messages being sent. I want multiple clients to be able to connect one after another, maintaining the same server socket. Here's my code:
TcpClient client;
while (true) {
Console.Write("Waiting for connection... ");
client = listener.AcceptTcpListener();
nStream = client.GetStream();
sReader = new StreamReader(nStream);
Console.WriteLine("Connected!");
while (client.Connected) {
string line = sReader.ReadLine();
Console.WriteLine(line);
}
Console.WriteLine("#Client Disconnected")
}
Unfortunately, when the remote client disconnects, it never escapes the "while (client.Connected)" loop. Instead I get an infinite write to STDOUT.

Basically, the property that you're using TcpClient.Connection does not do what you think it does. From the MSDN documentation:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.connected.aspx
Because the Connected property only reflects the state of the connection as of the most recent operation, you should attempt to send or receive a message to determine the current state. After the message send fails, this property no longer returns true. Note that this behavior is by design. You cannot reliably test the state of the connection because, in the time between the test and a send/receive, the connection could have been lost.
The gist is that the property TcpClient.Connection was not updated after the host disconnected but before your server blocked waiting to read another line from the stream. You need a more reliable way to detect if the connection is active before you block.
Turns out, this question has been asked before. So, I borrowed the answer from here and adapted it to the format that you're using in the OP.
https://stackoverflow.com/a/8631090
static void Main(string[] args)
{
TcpClient client = new TcpClient();
TcpListener listener = new TcpListener(IPAddress.Loopback, 60123);
listener.Start();
while (true)
{
Console.WriteLine("Waiting for connection...");
client = listener.AcceptTcpClient();
Console.WriteLine("Connection found");
StreamReader reader = new StreamReader(client.GetStream());
string line = string.Empty;
while (TestConnection(client))
{
line = reader.ReadLine();
Console.WriteLine(line);
}
Console.WriteLine("Disconnected");
}
}
private static bool TestConnection(TcpClient client)
{
bool sConnected = true;
if (client.Client.Poll(0, SelectMode.SelectRead))
{
if (!client.Connected) sConnected = false;
else
{
byte[] b = new byte[1];
try
{
if (client.Client.Receive(b, SocketFlags.Peek) == 0)
{
// Client disconnected
sConnected = false;
}
}
catch { sConnected = false; }
}
}
return sConnected;
}
This works for me when I test it, and the reason that it works is that you cannot tell if the connection is closed until you attempt to read or write from it. You can do that by blindly trying to read/write and then handling the IO exceptions that come when the socket is closed, or you can do what this tester method is doing and peek to see if the connection is closed.
Hope this helps you
EDIT:
It should be noted that this may or may not be the most efficient way to check if the connection is closed, but it is purely to illustrate that you must check the connection yourself on the server side by reading/writing instead of relying on TcpClient.Connection.
EDIT 2:
My sample doesn't clean up old resources very well, apologies to anyone who had an OCD reaction.

Related

C# - Memory release for an asynchronous TcpClient Connection

I am trying to create an asynchronous methode to verify if i can connect with an host Through TCP. It seem like i am not releasing correctly all the memory i use.
I'm i forgetting something ?
My Connection Indicator is :
Bool CanConnectToHost = false;
My Function is :
private async void TryToConnectToHost()
{
// host IP Address and communication port
string ipAddress = Properties.Settings.Default.HostIPaddr;
int port = 9100;
//Try to Connect with the host
try
{
TcpClient client = new TcpClient();
await client.ConnectAsync(ipAddress, port);
//Verify if connected succesfully
if (client.Connected)
{
//Connection with host
CanConnectToHost = true;
}
else
{
// No connection with host
CanConnectToHost = false;
}
//Close Connection
client.Close();
}
catch (Exception exception)
{
//Do Something
}
}
Thx a lot
I don't think you need to care about memory here. What you probably observe is that the Garbage Collection doesn't bother to clean up all memory immediatly after your method is finished. It will do so eventually when it has time or your process starts to run out of free memory.
TcpClient.ConnectAsync() throws a SocketException if the connection cannot be established. So your code has the flaw that in case of that exception, you don't set your CanConnectToHost correctly (though it is false by initialization).
I recommend to use using here. That also has the advantage that Close() will also be called in case of the exception. And Close() will also free any resources used by the TcpClient immediatly and not only if GC starts to work.
Your code with using:
private async void TryToConnectToHost()
{
// host IP Address and communication port
string ipAddress = Properties.Settings.Default.HostIPaddr;
int port = 9100;
//Try to Connect with the host
try
{
using (TcpClient client = new TcpClient())
{
await client.ConnectAsync(ipAddress, port);
CanConnectToHost = client.Connected; // no need for if
}
}
catch (Exception exception)
{
CanConnectToHost = false;
}
}

c# service to listen to a port

I believe what I am looking to create is a service that listens to a specific port, and when data is sent to that port, it sends off that data to another script for processing.
For some reason though, the service times out when I try to start it. My logs tells me TcpClient client = server.AcceptTcpClient(); is where it is stopping (actually, it is getting stuck on 'starting' in Services).
Since I have no experience with C#, making services, or working with servers in this manner, the code is pretty much just what I found online.
The OnStart method looks like this.
protected override void OnStart(string[] args)
{
try
{
TcpListener server = null;
// Set the TcpListener on port 13000.
Int32 port = 1234;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
// Enter the listening loop.
while (true)
{
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
TcpClient client = server.AcceptTcpClient();
data = null;
// Get a stream object for reading and writing
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
// Process the data sent by the client.
data = data.ToUpper();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
// Send back a response.
stream.Write(msg, 0, msg.Length);
}
// Shutdown and end connection
client.Close();
}
}
catch (SocketException e)
{
}
finally
{
}
}
As per MSDN, TcpServer.AcceptTcpClient blocks, so you're probably never returning from your Service's OnStart method, which causes the service to never actually "start".
You might consider using another thread and return from OnStart as soon as possible.
Cheers
As far as creating the Windows service itself, you should be able to use this link, even though it's dated. This companion link shows how to have the service install and uninstall itself. Finally, use this link to understand how to have your service run constantly and how to properly respond to start and stop commands.
To have your service interact with the socket, you'll want to modify the WorkerThreadFunc() from the last link. This is where you should start listening for and processing inbound socket connections.

How to do async udp networking right?

As many others here on SO I'm trying to create a networking library. The requirements basically look like this:
work asynchronously and get ready for real-time applications (I have FPS games in mind)
use UDP and set up a thin protocol layer on top as necessary
work with IPv6 natively
support multiple platforms (read: I want Mono support!)
Now after some reading about how to do this (most inspiring was Gaffer on Games) I set up my development environment, thought about how to do it and came up with this basic workflow:
Initialize a socket and tell it to use "UDPv6"
Bind that socket to a port and make exceptions not bother the user. There is a "Bound" propery that tells him that the socket is set up correctly.
Find out about the max MTU the NICs on the local machine support.
Initialize a number of SocketAsyncEventArgs, tell its Completed event to call the private dispatch method and set its buffer to the size of the max MTU from step 3.
Call the Sockets ReceiveFromAsync method with the first SAEA object around.
When data comes in, I do the following:
Call the ReceiveFromAsync method with the next free SAEA object
Get buffer and Sender information from the current SAEA object and make it available again
Fire a new event with the received message.
I did some testing on this approach and it is working quite good. I fired a message at it every 10 milliseconds with 200 bytes of data for 10000 cycles and there is pretty much no increase in CPU or memory load. Only NIC load is increasing. However I came up with some problems | questions:
When I dispose my PeerSocket class (that is holding the socket) I dispose every SAEA object. But since at least one of them is still listening for new messages, an ObjectDisposedException is thrown. Is there a way to tell it to stop listening?
The MTU may vary on the way to other peers, maybe the buffer of each SAEA object should use a different indicator for determining the buffers size?
I'm not sure how to handle fragmented datagrams yet. I will get on writing that "reliability header" into a datagram I am sending, but if a datagram is split I don't know about this header information, right?
The library will hopefully be of use to someone else one day and it's repository is publicly available. As of this question, the current commit can be found here
Wow, it is really huge subject. if you didn't learned about network sockets before you'd better learn. I can give you the gist but it is definitely not enough.
The Client:
public void Get()
{
string data;
string input;
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
socket.Connect(ipep);
}
catch (SocketException e)
{
Console.WriteLine("Unable to connect to server");
Console.WriteLine(e.ToString());
return;
}
NetworkStream ns = new NetworkStream(socket);
StreamWriter sw = new StreamWriter(ns);
StreamReader sr = new StreamReader(ns);
data = sr.ReadLine();
Console.WriteLine(data);
while (true)
{
input = Console.ReadLine();
if (input == "exite")
break;
sw.WriteLine(input);
sw.Flush();
data = sr.ReadLine();
Console.WriteLine(data);
}
Console.WriteLine("Disconnected from server...");
socket.Close();
ns.Close();
sr.Close();
sr.Close();
}
The Server:
public void Get()
{
string data;
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(ipep);
socket.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = socket.Accept();
IPEndPoint newclient = (IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with: {0}, at Port: {1}", newclient.Address, newclient.Port);
NetworkStream ns = new NetworkStream(client);
StreamReader sr = new StreamReader(ns);
StreamWriter sw = new StreamWriter(ns);
string welcome = "Welcome to my test server";
sw.Write(welcome);
sw.Flush();
while (true)
{
try
{
data = sr.ReadLine();
}
catch (IOException)
{
break;
}
Console.WriteLine(data);
sw.WriteLine(data);
sw.Flush();
}
Console.WriteLine("Disconnected from {0}", newclient.Address);
sw.Close();
ns.Close();
sr.Close();
}
Please try it out on Console application, see how it works.
Basically, the server opens the port (9050 in this example) waiting for the client connection then the client connects to the server and then starts the communication.
You mentioned you have to use UDP sockets, I presume you know about udp but if not you'd better check about the distinction between TCP and UDP especially about the way to verify that the data get to the desired destination (ad hoc concept and so on).

Socket's state changes from Connected to Disconnected

I have two applications, one connects to another via TCP Socket. I was having an issue and after a long troubleshooting I begun to think the root cause is due to the disconnection of the Socket, aka the Socket.state changes to Disconnected.
The reasons I came to above conclusion are just purely from reading the codes and analyze them. I need to prove that is the case and therefore my question is have you ever came accross this type of issue that the socket actually keep getting disconnected even after trying to connect to them?
Below is my Connect code, I have a loop that constantly check for the socket's state itself, if I detect the state is "Disconnected" I call this Connect() function again. Upon each and every time I call Connect() I noticed my socket state is back to Connected again.
So my questions are:
1. Have you seen this behavior yourself before?
2. Do you see any problem in me calling multiple Connect() again and again?
3. Is there a way to simulate this type of socket disconnections? I tried but I can't set the Socket.Connected flag.
public override void Connect()
{
try
{
sState = Defs.STATE_CONNECTING;
// send message to UI
string sMsg = "<Msg SocketStatus=\"" + sState + "\" />";
HandleMessage(sMsg);
// Create the socket object
sSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
string sIP = "";
// Define the Server address and port
if (Validate.IsIPAddress(sServer.ToString()))
{
sIP = sServer.ToString();
}
else
{
IPHostEntry iphost = Dns.GetHostEntry(sServer.ToString());
sIP = iphost.AddressList[0].ToString();
}
IPEndPoint epServer = new IPEndPoint(IPAddress.Parse(sIP), 1234);
// Connect to Server non-Blocking method
sSock.Blocking = false;
AsyncCallback onconnect = new AsyncCallback(OnConnect);
sSock.BeginConnect(epServer, onconnect, sSock);
}
catch (Exception ex)
{
LogException(new Object[] { ex });
}
}

Manage several/multiple tcp connections

I have a server application and client application with the functionality already working. Let me show you how I connect my client application to my server app:
//SERVER
// instantiate variables such as tempIp, port etc...
// ...
// ...
server = new TcpListener(tempIp, port); //tempIp is the ip address of the server.
// Start listening for client requests.
server.Start();
// Buffer for reading data
Byte[] bytes = new Byte[MaxChunkSize];
String data = null;
// Enter the listening loop.
while (disconect == false)
{
Console.Write("Waiting for a connection... ");
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
client = server.AcceptTcpClient(); // wait until a client get's connected...
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
stream = client.GetStream();
// now that the connection is established start listening though data
// sent through the stream..
int i;
try
{
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
// etc..
....
ok now on the client side lets say I want to establish a connection then send some data through the stream
//Client
client = new TcpClient(serverIP, port);
// Get a client stream for reading and writing.
stream = client.GetStream();
//then if I wish to send the string hello world to the server I would do:
sendString(stream, "Hello world");
protected void sendString(NetworkStream stream, string str)
{
sendBytes(stream, textToBytes(str));
}
protected void sendBytes(NetworkStream stream, Byte[] data)
{
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
}
protected static Byte[] textToBytes(string text)
{
return System.Text.Encoding.ASCII.GetBytes(text);
}
since I am able to send bytes I am able to send files or everything that I want. the technique that I use is that if I send the string file for example to the server then the server will start listening for a file. It will open a stream and write the received bytes to that file. If a different keyword is send the server will start listening on a different method etc..
So when dealing with one server and one client everything works great. Now I want to add more clients and need them to also connect to the server. I know that several connections can be establish on the same port just like we do it with por 80 on websites... I do not know how to manage several connections. so one thing I was thinking was to leave everything as it is. if a connection is established then tell the server to start another thread listening for other connections on the same port. with this technique I will have several threads running plus I just know the basics of multrythreading. If this technique is my best option I will start implementing it. You guys out there are really knowledgeable about all this so it will be nice if someone can point me on the right direction. Or maybe I should listen on several ports. if the server is already connected on port 7777 for example then do not accept connections from that port and start listening on port 7778 for example. I mean there could be so many different ways of achieving what I need and you guys probably know the best way. I just know the basics of networking...
You could use threading:
var client = server.AcceptTcpClient();
var t = new Thread(new ParameterizedThreadStart(AccentClient));
t.Start(client);
The target method would look like this
public void AccentClient(object clientObj)
{
var client = clientObj as TcpClient;
// Do whatever you need to do with the client
}
If you are not familiar with multithreading, it is important you learn at least the basics first.
You could implement a class that encapsulates TCP behavior. Check this class:
public class SimpleListener
{
private System.Net.Sockets.TcpListener _tcpListen;
//declare delegate to handle new connections
public delegate void _new_client(System.Net.Sockets.TcpClient tcpclient);
//declare a clients container (or something like...). OPTION 1
List<System.Net.Sockets.TcpClient> _connected_clients;
//declare an event and event handler (the same for _new_client) for new connections OPTION 2
public event _new_client new_tcp_client;
//public (The list of connected clients).
public List<System.Net.Sockets.TcpClient> ConnectedClients { get { return _connected_clients; } }
public SimpleListener(string ip, int listenport)
{
System.Net.IPAddress ipAd = System.Net.IPAddress.Parse(ip);
_tcpListen = new System.Net.Sockets.TcpListener(new System.Net.IPEndPoint(ipAd,listenport));
_connected_clients = new List<System.Net.Sockets.TcpClient>();
}
//Fire this method to start listening...
public void Listen()
{
_tcpListen.Start();
_set_listen();
}
//... and this method to stop listener and release resources on listener
public void Stop()
{
_tcpListen.Stop();
}
//This method set the socket on listening mode...
private void _set_listen()
{
//Let's do it asynchronously - Set the method callback, with the same definition as delegate _new_client
_tcpListen.BeginAcceptTcpClient(new AsyncCallback(_on_new_client), null);
}
//This is the callback for new clients
private void _on_new_client(IAsyncResult _async_client)
{
try
{
//Lets get the new client...
System.Net.Sockets.TcpClient _tcp_cl = _tcpListen.EndAcceptTcpClient(_async_client);
//Push the new client to the list
_connected_clients.Add(_tcp_cl);
//OPTION 2 : Fire new_tcp_client Event - Suscribers will do some stuff...
if (new_tcp_client != null)
{
new_tcp_client(_tcp_cl);
}
//Set socket on listening mode again... (and wait for new connections, while we can manage the new client connection)
_set_listen();
}
catch (Exception ex)
{
//Do something...or not
}
}
}
You could use this in your code:
//SERVER
// instantiate variables such as tempIp, port etc...
// ...
// ...
SimpleListener server = new SimpleListener(tempIp, port); //tempIp is the ip address of the server.
//add handler for new client connections
server.new_tcp_client += server_new_tcp_client;
// Start listening for client requests.
server.Listen();
.... //No need to loop. The new connection is handled on server_new_tcp_client method
void server_new_tcp_client(System.Net.Sockets.TcpClient tcpclient)
{
// Buffer for reading data
Byte[] bytes = new Byte[MaxChunkSize];
String data = null;
Console.WriteLine("Connected!");
// Get a stream object for reading and writing
System.IO.Stream stream = tcpclient.GetStream();
// now that the connection is established start listening though data
// sent through the stream..
int i;
try
{
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
Console.WriteLine("Received: {0}", data);
// etc..
....
}

Categories

Resources