private void CloseClientSocket(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; try { token.Socket.Shutdown(SocketShutdown.Send); } catch (Exception ex) { } token.Socket.Close(); Threading.Interlocked.Decrement(ref _numConnections); _maxNumberAcceptedClients.Release(); _readWritePool.Push(e); Console.WriteLine(_readWritePool.Count); }
private void ProcessSend(SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { AsyncUserToken token = (AsyncUserToken)e.UserToken; // ' TODO: LEFT OFF HERE // Dim x As SocketAsyncEventArgs = _readWritePool.Pop // x.UserToken = token // Dim willRaiseEvent As Boolean = token.Socket.ReceiveAsync(e) CloseClientSocket(e); // If Not willRaiseEvent Then // ProcessReceive(e) // End If } else { CloseClientSocket(e); } }
// '' <summary> // '' Handles the client request/response cycle, replying to a request with a response by default. May be overridden during implementation for custom response handling. // '' </summary> // '' <param name="req"></param> // '' <param name="res"></param> // '' <param name="client"></param> // '' <remarks></remarks> private void _HandleRequest(Request req, Response res, SocketAsyncEventArgs client) { // serve the requested resource from the output cache or from disk; better yet, store the entire response and serve that up to save some time if (OutputCache.ContainsKey(req.AbsoluteUrl)) { Response cachedResponse = (Response)OutputCache[req.AbsoluteUrl]; res = cachedResponse; DebugMessage(("Serving resource from cache: " + (req.AbsoluteUrl + ".")), DebugMessageType.UsageMessage, "ClientRequest event"); // TODO: we might want to move the res.GetAllBytes call into the Else condition here so it doesn't get called again for an already cached response } else { // serve the file from disk // TODO: depending on TransferMethod requested by the client, we should implement StoreAndForward or ChunkedEncoding, but for now we will just use StoreAndForward if (IO.File.Exists(req.AbsoluteUrl)) { // determine how to the process the client's request based on the requested uri's file type // this is where we might load a resourince, maybe using Interops to parse dynamic scripts (e.g. PHP and ASP.NET) if (req.MimeType.Handler == "") { // no custom handler for this mimetype, serve as a static file res.ContentType = req.MimeType.Name; // GetContentType(req.AbsoluteUrl) res.SetContent(IO.File.ReadAllBytes(req.AbsoluteUrl)); res.StatusCode = 200; } else { // TODO: there is a custom handler assigned to this filetype, but handlers are not implemented yet so we just serve it as a static file res.ContentType = req.MimeType.Name; // GetContentType(req.AbsoluteUrl) res.SetContent(IO.File.ReadAllBytes(req.AbsoluteUrl)); res.StatusCode = 200; } // cache the response for future use to improve performance, avoiding the need to process the same response frequently if (OutputCache.ContainsKey(req.AbsoluteUrl)) { OutputCache.Add(req.AbsoluteUrl, res); } else { // page not found, return 404 status code res.StatusCode = 404; } } // send the response to the client who made the initial request byte[] responseBytes = res.GetResponseBytes(); // Dim sendEventArg As SocketAsyncEventArgs = _readWritePool.Pop // Dim ar As AsyncUserToken = client // sendEventArg.UserToken = ar // sendEventArg.SetBuffer(responseBytes, 0, responseBytes.Length) client.SetBuffer(responseBytes, 0, responseBytes.Length); AsyncUserToken token = (AsyncUserToken)client.UserToken; bool willRaiseEvent = token.Socket.SendAsync(client); if (!willRaiseEvent) { // TODO: this never fires!! why not? Beep(); } // handle keep-alive or disconnect if (res.Headers["Connection"] == "keep-alive") { // receive more from the client // Dim readEventArgs As SocketAsyncEventArgs = _readWritePool.Pop // token.Socket.ReceiveAsync(readEventArgs) } else { // token.Socket.Disconnect(False) // token.Socket.Close() // TODO: maybe move this into the CompleteReceive where we call ReceiveAsync... CloseClientSocket(client); } // Dim sendState As New AsyncSendState(client) // sendState.BytesToSend = responseBytes // sendState.Tag = req.AbsoluteUrl // If res.Headers["Connection") = "keep-alive" Then // sendState.Persistent = True // End If // Try // client.BeginSend(responseBytes, 0, responseBytes.Length, SocketFlags.None, AddressOf CompleteSend, sendState) // Catch ex As Exception // LogEvent("Could not send data to this client. An unhandled exception occurred.", LogEventType.UsageMessage, "ClientRequest", ex.Message) // End Try // ' call BeginReceive again, so we can receive more data from this client socket (either not needed for http server or only for persistent connections...reimplement for binary rpc server) // If sendState.Persistent = True Then // Dim receiveState As New AsyncReceiveState // receiveState.Socket = client // Try // receiveState.Socket.BeginReceive(receiveState.Buffer, 0, gBufferSize, SocketFlags.None, New AsyncCallback(AddressOf CompleteRequest), receiveState) // Catch ex As Exception // LogEvent("Could not receive more data from this client. An unhandled exception occurred.", LogEventType.UsageMessage, "ClientRequest", ex.Message) // End Try // End If } }