-
-
Save peters/32ed54c9dc9e3f5262983acda993ace0 to your computer and use it in GitHub Desktop.
How do you close TCP connections gracefully without exceptions?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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