Skip to content

Instantly share code, notes, and snippets.

@esdrubal
Created June 2, 2014 17:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save esdrubal/d6447be5566371766a27 to your computer and use it in GitHub Desktop.
Save esdrubal/d6447be5566371766a27 to your computer and use it in GitHub Desktop.
WebClient CancelAsync
//
// Copyright 2012 Xamarin Inc. (http://www.xamarin.com)
//
using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
class Program
{
static void Main(string[] args)
{
var ret = UploadFileAsyncCancelEvent();
Console.WriteLine((ret)? "It Works!" : "Bug!");
}
public static bool UploadFileAsyncCancelEvent()
{
return UploadAsyncTest((webClient, uri, cancelEvent) =>
{
string tempFile = Path.GetTempFileName();
webClient.UploadFileCompleted += (sender, args) =>
{
if (args.Cancelled)
cancelEvent.Set();
};
webClient.UploadFileAsync(uri, "PUT", tempFile);
});
}
public static bool UploadAsyncTest(Action<WebClient, Uri, EventWaitHandle> uploadAction)
{
var ep = new IPEndPoint(IPAddress.Loopback, 8000);
string url = "http://" + IPAddress.Loopback + ":8000/test/";
using (var responder = new SocketResponder(ep, EchoRequestHandler))
{
responder.Start();
var webClient = new WebClient();
var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.Token.Register(webClient.CancelAsync);
var cancelEvent = new ManualResetEvent(false);
uploadAction.Invoke(webClient, new Uri(url), cancelEvent);
cancellationTokenSource.Cancel();
return cancelEvent.WaitOne(1000);
}
}
/*
* HELPERS
*/
static byte[] EchoRequestHandler(Socket socket)
{
MemoryStream ms = new MemoryStream();
byte[] buffer = new byte[4096];
int bytesReceived = socket.Receive(buffer);
while (bytesReceived > 0)
{
ms.Write(buffer, 0, bytesReceived);
// We don't check for Content-Length or anything else here, so we give the client a little time to write
// after sending the headers
Thread.Sleep(200);
if (socket.Available > 0)
{
bytesReceived = socket.Receive(buffer);
}
else
{
bytesReceived = 0;
}
}
ms.Flush();
ms.Position = 0;
StringBuilder sb = new StringBuilder();
string expect = null;
StreamReader sr = new StreamReader(ms, Encoding.UTF8);
string line = null;
byte state = 0;
while ((line = sr.ReadLine()) != null)
{
if (state > 0)
{
state = 2;
sb.Append(line);
sb.Append("\r\n");
} if (line.Length == 0)
{
state = 1;
}
else if (line.StartsWith("Expect:"))
{
expect = line.Substring(8);
}
}
StringWriter sw = new StringWriter();
if (expect == "100-continue" && state != 2)
{
sw.WriteLine("HTTP/1.1 100 Continue");
sw.WriteLine();
sw.Flush();
socket.Send(Encoding.UTF8.GetBytes(sw.ToString()));
// receive body
ms = new MemoryStream();
buffer = new byte[4096];
bytesReceived = socket.Receive(buffer);
while (bytesReceived > 0)
{
ms.Write(buffer, 0, bytesReceived);
Thread.Sleep(200);
if (socket.Available > 0)
{
bytesReceived = socket.Receive(buffer);
}
else
{
bytesReceived = 0;
}
}
ms.Flush();
ms.Position = 0;
sb = new StringBuilder();
sr = new StreamReader(ms, Encoding.UTF8);
line = sr.ReadLine();
while (line != null)
{
sb.Append(line);
sb.Append("\r\n");
line = sr.ReadLine();
}
}
sw = new StringWriter();
sw.WriteLine("HTTP/1.1 200 OK");
sw.WriteLine("Content-Type: text/xml");
sw.WriteLine("Content-Length: " + sb.Length.ToString(CultureInfo.InvariantCulture));
sw.WriteLine();
sw.Write(sb.ToString());
sw.Flush();
return Encoding.UTF8.GetBytes(sw.ToString());
}
public delegate byte[] SocketRequestHandler(Socket socket);
public class SocketResponder : IDisposable
{
private TcpListener tcpListener;
private readonly IPEndPoint _localEndPoint;
private Thread listenThread;
private SocketRequestHandler _requestHandler;
private bool _stopped = true;
private readonly object _syncRoot = new object();
private const int SOCKET_CLOSED = 10004;
private const int SOCKET_INVALID_ARGS = 10022;
public SocketResponder(IPEndPoint localEP, SocketRequestHandler requestHandler)
{
_localEndPoint = localEP;
_requestHandler = requestHandler;
}
public IPEndPoint LocalEndPoint
{
get { return _localEndPoint; }
}
public void Dispose()
{
Stop();
}
public bool IsStopped
{
get
{
lock (_syncRoot)
{
return _stopped;
}
}
}
public void Start()
{
lock (_syncRoot)
{
if (!_stopped)
return;
_stopped = false;
tcpListener = new TcpListener(LocalEndPoint);
tcpListener.Start();
listenThread = new Thread(new ThreadStart(Listen));
listenThread.Start();
}
}
public void Stop()
{
lock (_syncRoot)
{
if (_stopped)
return;
_stopped = true;
if (tcpListener != null)
{
tcpListener.Stop();
tcpListener = null;
Thread.Sleep(50);
}
}
}
private void Listen()
{
while (!_stopped)
{
Socket socket = null;
try
{
socket = tcpListener.AcceptSocket();
socket.Send(_requestHandler(socket));
try
{
socket.Shutdown(SocketShutdown.Receive);
socket.Shutdown(SocketShutdown.Send);
}
catch
{
}
}
catch (SocketException)
{
}
finally
{
Thread.Sleep(500);
if (socket != null)
socket.Close();
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment