Skip to content

Instantly share code, notes, and snippets.

@jkingry
Created May 6, 2011 13:32
Show Gist options
  • Save jkingry/958955 to your computer and use it in GitHub Desktop.
Save jkingry/958955 to your computer and use it in GitHub Desktop.
How do you close TCP connections gracefully without exceptions?
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace Example
{
class Channel
{
private readonly TcpClient client;
private readonly NetworkStream stream;
private readonly string name;
private readonly ManualResetEvent quit = new ManualResetEvent(false);
public Channel(string name, TcpClient client)
{
this.name = name;
this.client = client;
stream = client.GetStream();
}
public void Run()
{
Console.WriteLine(name + ": connected");
byte[] buffer = new byte[client.Client.ReceiveBufferSize];
stream.BeginRead(buffer, 0, buffer.Length, this.Read, buffer);
var writer = new StreamWriter(stream, Encoding.ASCII);
while (true)
{
var line = Console.ReadLine();
if (String.IsNullOrEmpty(line) || !this.client.Connected) break;
writer.WriteLine(line);
writer.Flush();
}
if (client.Connected)
{
Console.WriteLine(name + " shutting down send.");
client.Client.Shutdown(SocketShutdown.Send);
Console.WriteLine(name + " waiting for read to quit.");
quit.WaitOne();
}
else
{
Console.WriteLine(name + " socket already closed");
}
Console.WriteLine(name + " quit, press key to exit.");
Console.ReadKey();
}
private void Read(IAsyncResult result)
{
var bytesRead = this.stream.EndRead(result);
if (bytesRead == 0)
{
Console.WriteLine(name + " read stopped, closing socket.");
this.client.Close();
this.quit.Set();
return;
}
var buffer = (byte[])result.AsyncState;
Console.WriteLine(name + " recieved:" + Encoding.ASCII.GetString((byte[])result.AsyncState, 0, bytesRead));
stream.BeginRead(buffer, 0, buffer.Length, this.Read, buffer);
}
}
}
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
public class Channel
{
private readonly TcpClient client;
private readonly NetworkStream stream;
private readonly TextReader reader;
private readonly TextWriter writer;
private readonly string name;
public Channel(string name, TcpClient client)
{
SocketAsyncEventArgs
this.name = name;
this.client = client;
stream = client.GetStream();
stream.ReadTimeout = 1000;
reader = new StreamReader(stream, Encoding.ASCII);
writer = new StreamWriter(stream, Encoding.ASCII);
}
public void Run()
{
Console.WriteLine(name + ": connected");
Thread readThread = new Thread(Read);
readThread.Start();
while (true)
{
var line = Console.ReadLine();
if (String.IsNullOrEmpty(line)) break;
writer.WriteLine(line);
writer.Flush();
}
Console.WriteLine(name + " quitting");
stream.Flush();
client.Close();
}
private void Read()
{
while (true)
{
var line = reader.ReadLine();
Console.WriteLine(name + " recieved: " + line);
}
}
}
class Server
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(IPAddress.Loopback, 5000);
listener.Start();
Console.WriteLine("server: listener started");
var channel = new Channel("server", listener.AcceptTcpClient());
channel.Run();
listener.Stop();
}
}
class Client
{
static void Main(string[] args)
{
TcpClient client = new TcpClient(AddressFamily.InterNetwork);
Console.WriteLine("client: created, press key to connect");
Console.ReadKey();
client.Connect(IPAddress.Loopback, 5000);
var channel = new Channel("client", client);
channel.Run();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment