我有多线程异步套接字监听器.我想检查请求是否安全.但我想在AcceptCallBack方法中检查不是ReceiveCallBack.

我会这样做,因为我希望我的代码适用于HTTP和HTTPS.如果请求来自HTTPS,我将继续使用经过身份验证的SslStream而不是原始套接字.

这是我的代码:

using System;
using System.Net;
using System.Net.sockets;
using System.Threading;
using System.Text;

namespace LearnRequestType
{
    class StackOverFlow
    {
        private static readonly ManualResetEvent _manualResetEvent = new ManualResetEvent(false);

        private void StartListening()
        {
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any,9002);

            if (localEndPoint != null)
            {
                Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

                if (listener != null)
                {
                    listener.Bind(localEndPoint);
                    listener.Listen(10);

                    Console.WriteLine("Socket listener is running...");

                    listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
                }
            }
        }

        private void AcceptCallback(IAsyncResult ar)
        {
            _manualResetEvent.Set();

            Socket listener = (Socket)ar.AsyncState;

            Socket handler = listener.EndAccept(ar);

            StateObject state = new StateObject();
            state.workSocket = handler;

            // I want to understand if request comes from HTTP or HTTPS before this line.
            handler.BeginReceive(state.buffer,StateObject.BufferSize,new AsyncCallback(ReceiveCallback),state);

            listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
        }

        private void ReceiveCallback(IAsyncResult result)
        {
            StateObject state = (StateObject)result.AsyncState;
            Socket handler = state.workSocket;

            string clientIP = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();

            int numBytesReceived = handler.EndReceive(result);

            if (!handler.Connected)
            {
                handler.Close();
                return;
            }

            // Read incoming data...
            if (numBytesReceived > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(state.buffer,numBytesReceived));

                // Read incoming data line by line.
                string[] lines = state.sb.ToString().Split('\n');

                if (lines[lines.Length - 1] == "<EOF>")
                {
                    // We received all data. Do something...

                }
                else
                {
                    // We didn't receive all data. Continue reading...
                    handler.BeginReceive(state.buffer,state.buffer.Length,SocketFlags.None,state);
                }
            }
        }
    }
}

public class StateObject
{
    public Socket workSocket = null;
    public const int BufferSize = 256;
    public byte[] buffer = new byte[BufferSize];
    public StringBuilder sb = new StringBuilder();
}

如果我更改AcceptCallBack方法和StateObject类:

private void AcceptCallback(IAsyncResult ar)
{
    _manualResetEvent.Set();

    Socket listener = (Socket)ar.AsyncState;

    Socket handler = listener.EndAccept(ar);

    try
    {
        sslStream = new SslStream(new NetworkStream(handler,true));

        // try to authenticate
        sslStream.AuthenticateAsServer(_cert,false,System.Security.Authentication.SslProtocols.Tls,true);

        state.workStream = sslStream;
        state.workStream.ReadTimeout = 100000;
        state.workStream.WriteTimeout = 100000;

        if (state.workStream.IsAuthenticated)
        {
            state.workStream.BeginRead(state.buffer,ReceiveCallback,state);
        }
    }
    catch (IOException ex)
    {
        // ıf we get handshake Failed due to an unexpected packet format,this means incoming data is not HTTPS
        // Continue with socket not sslstream
        state.workSocket = handler;
        handler.BeginReceive(state.buffer,state);
    }

    StateObject state = new StateObject();
    state.workStream = handler;

    handler.BeginReceive(state.buffer,state);

    listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
}

public class StateObject
{
    public Socket workSocket = null;
    public SslStream workStream = null;
    public const int BufferSize = 1024;
    public byte[] buffer = new byte[BufferSize];
    public StringBuilder sb = new StringBuilder();
}

我可以决定传入的数据类型是HTTP还是HTTPS,但如果是HTTP,它每次都会被catch块处理,因此会降低应用程序性能.

还有另一种方式吗?

解决方法

如果我理解正确,您有一个端口,客户端可以使用HTTP或HTTPS进行连接,并且您希望在传输任何数据之前立即知道请求是如何进行的.

在从客户端接收数据之前无法知道这一点. HTTP和HTTPS是TCP之上的协议,它们不能在较低的协议级别上工作,因此没有标志或任何可以说明使用哪种协议的东西.此外,HTTPS只是包含在TLS / SSL流中的普通HTTP流.

您必须读取数据并根据使用的协议确定.或者你必须有单独的HTTP和HTTPS端口,这将使这一点变得微不足道.

要检测它是否是TLS / SSL,您可以查看几个字节并查看其中的内容.The TLS specification表示客户端Hello数据包以协议版本启动,协议版本以两个uint8发送.由于HTTP请求总是将动词作为第一个,因此您可以轻松检查是否有一些第一个字节是字符,然后尝试SSLStream(如果不是).

另请注意,如果您在套接字上启动SSLStream,它可能会从套接字中读取,这将消耗HTTP请求的开头,您无法正常处理它.

所以在你的Accept回调中使用这样的东西:

Socket handler = listener.EndAccept(ar);
byte[] tmp = new byte[2];
handler.Receive(tmp,2,SocketFlags.Peek);
if (!Char.IsLetter((char)tmp[0]) || !Char.IsLetter((char)tmp[1]))
{
  // Doesn't start with letters,so most likely not HTTP
} else {
  // Starts with letters,should be HTTP
}

如果您想确保它是TLS / SSL,您可以查看this question on SO

c# – 检查请求是否来自套接字侦听器中的HTTP或HTTPS的更多相关文章

  1. 配置iOS VoIP应用程序以在睡眠/后台模式下运行

    我正在开发基于VoIP的iOS(7.1)应用程序.它的底层套接字编程是用C而不是客观C编写的.应用程序在前台运行良好,但在进入睡眠/后台模式时,它无法从服务器接收任何通信.根据apple文档,我们必须为VoIP使用配置一个appsocket.我无法弄清楚如何配置C套接字.目的是在睡眠模式下运行应用程序,直到它被杀死.从SO中尝试了几个链接甚至几个链接,但由于我是新手,我希望这个配置有一步一步的过程.[注意:在某个地方我发现了CoreFoudation框架,我是否需要使用它?

  2. 我应该使用哪个高级API来管理iOS上的UDP套接字?

    在“NetworkProgrammingTopicsConceptualGuide”的“UsingSocketsandStreams”一章中,Apple说:Note:POSIXnetworkingdoesnotactivatethecellularradiooniOS.Forthisreason,thePOSIXnetworkingAPIisgenerallydiscouragediniOS.同样

  3. 通过AFNetworking 2.0上传iOS图像

    我一直在寻找新的AFNetworking2.0上传图像的例子.但是我正在撞墙,无法弄清楚代码有什么问题.所以这是我使用的代码TIA解决方法我最终使用了多部分请求

  4. ios – 在Objective-C中发送分块的HTTP 1.1请求

    我有以下问题:我正在创建一个非常大的SOAP请求(数据是一个编码为Base64字符串的视频),因此我不能将其作为原始SOAP请求发送,而是需要在HTTP1.1块中发送它.我似乎无法弄明白该怎么做.我在这里使用了代码:WhatarealternativestoNSURLConnectionforchunkedtransferencoding但它似乎没有做我认为应该做的事情–我可以看到请求作为单个请求

  5. iOS:使用CFStreamCreatePairWithSocketToHost的套接字网络基础

    >每次要发送新数据对象时,是否设置了新套接字?>我是否必须重置outputStream并发送更多数据.码大部分代码来自CocoaStreamsDocumentation:响应:请注意,在发送数据后,outputStream流将关闭.我尝试在[selfsendString:@“AnotherTest”]之前重新启动outputStream.我也试过了idz的回答.根据文档,我相信len:0的发送缓冲区是我的问题.IfthedelegatereceivesanNsstreamEventHasspaceAvai

  6. ios – AFNetworking / NSURLConnection接收NSPOSIXErrorDomain代码= 9“操作无法完成.坏文件描述符“

    有人在他们的AFNetworking操作中遇到这个错误吗?此外,如果我真的想要,如何故意关闭这个文件描述符?

  7. ios – Swift2.0 HTTP请求无法正常工作

    参见英文答案>TransportsecurityhasblockedacleartextHTTP23个HelloStackoverflow,我将swift应用程序移动到Swift2.0后,我不断收到此错误:我看了下面的链接https://forums.developer.apple.com/thread/5835并将以下代码添加到我的info.plist中它仍然不起作用,任何人都有替代解决方案?解

  8. iOS:无法完成套接字错误操作断管

    我每隔一段时间就会从iOS应用程序向套接字服务器发送一些数据.它正确地发送数据.我看到一个奇怪的问题,如果iOS设备屏幕在从iOS应用程序发送数据时关闭,然后如果我在设备上屏幕,然后我收到以下错误,应用程序已经与套接字断开连接或有时它会崩溃应用程序:当设备屏幕关闭时,我的iOS应用程序停止向套接字发送数据.然后再打开屏幕,插座连接断开/断开管道错误.怎么解决?

  9. 如何在Swift语言中创建http请求

    概述:本文通过实例从同步和异步两种方式上回答了”如何在Swift语言中创建http请求“的问题。如果你对Objective-C比较了解的话,对于如何创建http请求你一定驾轻就熟了,而新语言Swift与其相比只有语法上的区别。但是,对才接触到这个崭新平台的初学者来说,他们仍然想知道“如何在Swift语言中创建http请求?”。在这里,我将作出一些建议来回答上述问题。常见的创建http请求的方式主要

  10. Swift HTTP请求集合

    )->Voidinprintln})带参数的get请求varrequest=HTTPTask()request.GET("http://google.com",parameters:["param":"param1","array":["firstarrayelement","second","third"],"num":23],arial;font-size:14px;line-height:21px">println("response:\(response.responSEObject!)")POS

随机推荐

  1. c# – (wpf)Application.Current.Resources vs FindResource

    所以,我正在使用C#中的WPF创建一个GUI.它看起来像这样:它现在还没有完成.这两行是我尝试制作一种数据表,它们在XAML中是硬编码的.现在,我正在C#中实现添加新的水果按钮功能.我在XAML中有以下样式来控制行的背景图像应该是什么样子:因此,在代码中,我为每列col0,col1和col2创建一个图像,如果我使用以下代码,它添加了一个如下所示的新行:如你所见,它不太正确……为什么一个似乎忽略了一些属性而另一个没有?

  2. c# – 绑定DataGridTemplateColumn

    似乎我已经打了个墙,试图在DataGrid上使用DataTemplates.我想要做的是使用一个模板来显示每个单元格的两行文本.但是似乎无法以任何方式绑定列.以下代码希望显示我想做的事情.注意每个列的绑定:模板列没有这样的东西,因此,这个xaml不可能工作.我注定要将整个DataTemplate复制到每个列,只是对每个副本都有不同的约束?解决方法我不完全确定你想要做什么,但如果您需要获取整行的DataContext,可以使用RelativeSource绑定来移动视觉树.像这样:

  3. c# – 学习设计模式的资源

    最近我来到了这个设计模式的概念,并对此感到非常热情.你能建议一些帮助我深入设计模式的资源吗?

  4. c# – 是否有支持嵌入HTML页面的跨操作系统GUI框架?

    我想开发一个桌面应用程序来使用跨系统,是否有一个GUI框架,允许我为所有3个平台编写一次代码,并具有完全可脚本化的嵌入式Web组件?我需要它有一个API来在应用程序和网页之间进行交流.我知道C#,JavaScript和一些python.解决方法Qt有这样的事情QWebView.

  5. c# – 通过字符串在对象图中查找属性

    我试图使用任意字符串访问嵌套类结构的各个部分.给出以下(设计的)类:我想要从Person对象的一个实例的“PersonsAddress.HousePhone.Number”获取对象.目前我正在使用反思来做一些简单的递归查找,但是我希望有一些忍者有更好的想法.作为参考,这里是我开发的(crappy)方法:解决方法您可以简单地使用标准的.NETDataBinder.EvalMethod,像这样:

  6. c# – 文件下载后更新页面

    FamilyID=0a391abd-25c1-4fc0-919f-b21f31ab88b7&displaylang=en&pf=true它呈现该页面,然后使用以下元刷新标签来实际向用户提供要下载的文件:你可能需要在你的应用程序中做类似的事情.但是,如果您真的有兴趣在文件完全下载后执行某些操作,那么您的运气不佳,因为没有任何事件可以与浏览器进行通信.执行此操作的唯一方法是上传附件时使用的AJAXupload.

  7. c# – 如何在每个机器应用程序中实现单个实例?

    我必须限制我的.net4WPF应用程序,以便每台机器只能运行一次.请注意,我说每个机器,而不是每个会话.我使用一个简单的互斥体实现单实例应用程序,直到现在,但不幸的是,这样一个互斥是每个会话.有没有办法创建机器互连,还是有其他解决方案来实现每个机器应用程序的单个实例?

  8. c# – WCF和多个主机头

    我的雇主网站有多个主机名,都是同一个服务器,我们只是显示不同的皮肤来进行品牌宣传.不幸的是,在这种情况下,WCF似乎不能很好地工作.我试过overridingthedefaulthostwithacustomhostfactory.这不是一个可以接受的解决方案,因为它需要从所有主机工作,而不仅仅是1.我也看过thisblogpost,但是我无法让它工作,或者不是为了解决我的问题.我得到的错误是“这

  9. c# – ASP.NET MVC模型绑定与表单元素名称中的虚线

    我一直在搜索互联网,试图找到一种方式来容纳我的表单元素的破折号到ASP.NET的控制器在MVC2,3或甚至4中的默认模型绑定行为.作为一名前端开发人员,我更喜欢在我的CSS中使用camelCase或下划线进行破折号.在我的标记中,我想要做的是这样的:在控制器中,我会传入一个C#对象,看起来像这样:有没有办法通过一些正则表达式或其他行为来扩展Controller类来适应这种情况?我讨厌这样的事实,我必须这样做:甚至这个:思考?

  10. c# – 用户界面设计工具

    我正在寻找一个用户界面设计工具来显示文档中可能的GUI.我不能生成代码.我知道MicrosoftVisio提供了一个功能.但有什么办法吗?您使用哪种软件可视化GUI?

返回
顶部