tls相关

大致原理

为了让两个之间实现安全传输,(我们把服务端统一叫做TcpServer,客户端统一叫做TcpClient),TcpServer在listen完了accept之后要用一个证书来声明自己是谁,而TcpClient在connect之后要问TcpServer是否具有自己想要的一个证书(确认服务端身份),如果是自己指定的那个证书,就说明是自己要连接的那个TcpServer,这时候连接就会建立成功,以后发给TcpServer的数据,都会用TcpServer声明的证书里面的公钥来加密后再发送给TcpServer,TcpServer会用自己机器里的私钥对数据解密。

以上保证了TcpClient不会连接到非法的TcpServer,第三方截取TcpClient发送的数据也解不开。

然后TcpServer也可以(可选)要求TcpClient必须提供证书,用以证明是传入的TcpClient自己信任的TcpClient。TcpClient会把证书(从某个CA申请的)进行签名后发送给TcpServer,TcpServer会确认TcpClient提供的证书发行者是否是自己信任的发行者(就是是否装有这个发行者的根证书),如果信任就会建立连接成功。

以上保证了TcpServer和TcpClient之间实现了双向的身份验证,建立了信任连接。这时候TcpServer和TcpClient会各自用一定的算法生成一个密钥做为会话密钥,并通知给对方,之后相互传输数据就用这个会话密钥进行对称加密后传给对方,这样做是因为对称加密比非对称加密性能要好一个数量级。(密钥交换一般是服务端用一段随机数传给客户端,客户端用一段随机数传给服务端,这个传输是安全传输,然后双方用两个随机数合并起来的一个数做为会话密钥)

其中的用sha1做为消息完整性算法,3des做为消息机密性算法,rsa做为密钥交换算法(在安全策略里打开fips选项 )。

证书相关操作

申请服务端证书

先找一台机器装上证书颁发服务(在添加/删除程序-添加删除windows组件里),然后再另一台机器通过浏览器申请证书,该网址类似如下(其中ms-onlytiancai为证书服务器机器名):

http://ms-onlytiancai/certsrv/

选择高级申请证书,如下图,识别信息要填全,否则客户端验证的时候会出现证书链(我测的时候确实如此,但证书链的概念是根CA和多级的中级CA之间信任关系的一个链,具体看相关链接)失败。d

证书类型要选择“服务器身份验证证书(有些CA可能没有单独的这样的模板,那就选择“计算机副本”证书,该证书可以用来验证服务器身份和客户端身份)”,其它选项不要动,最后点申请,然后再在CA服务器的【管理工具】-【证书颁发机构】的“挂起的证书”里把刚申请的证书颁发一下,最后还在证书申请网页上点“查看挂起的证书申请的状态”,通过向导,安装证书,提示你是否信任该CA时,点是,这时候会自动把该证书安装到“个人”区域,并把该CA证书安装到“受信任的根证书颁发机构”。这一步是必须的,这样做服务端就会信任该CA发行的所有证书(如果这一步没有安装根证书,后面可以从控制台里把CA证书单独导入到本地计算机的受信任颁发机构里,CA证书不是申请的,是直接在证书申请页面的下方的链接下载的),后面申请客户端证书的时候也从这个CA来申请,服务端才会信任这个客户端。

最后申请下来的证书,大致如上图所示,必须是服务器身份认证证书(至少证书目的里由“保证远程计算机身份”),而且必须得有一个该证书对应的私钥,这个私钥应该是在DPAPI(CAPI)存储器里存着呢,按照上面的操作应该会得到这样的一个证书。用makecert -r -pe -n "CN=TestCert" -e 01/01/2036 -sr localMachine c:" TestCert.cer生成的证书不会有对应的私钥,这样的证书是不能用的,到时候客户端验证的时候会抛一个异常,提示你没有私钥(需要一个关联私钥的证书)。
查看本机已安装的证书,在IE的选项-内容-证书选项里(在控制台里添加/删除管理单元里添加“证书管理单元”也可以管理)。
 
申请服务端证书,姓名字段一定要写成服务器的名称,netbios名或者dns名称。

申请客户端证书

过程和申请服务端证书一样,只是证书类型选择“客户端身份验证证书”。

导出证书

在证书管理控制台里把服务端证书和客户端证书全部导出到本地,导出选项全部为默认。

服务器为:C:"certs"huhao.pxe(带私钥)

客户端为:C:"certs"client.cer

如果服务端为windows服务,需要把服务端证书导入到本地计算机里,默认服务器证书只安装到了当前用户的个人区域,需要从当前用户的个人区域导出来,再导入到本地计算机的个人区域,导出的时候记着选上导出私钥,否则导入到本地计算机里的证书就不会关联私钥了。

应用相关

服务端代码

类库
using System;
using System.Net.Sockets;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Security.Authentication;
using System.Threading;

class TCPServer_SSL
{
    private TcpListener _listener = null;
    private IPAddress _address = IPAddress.Parse("127.0.0.1");
    private int _port = 55555;

    CTORs#region CTORs
    public TCPServer_SSL()
    {
    }

    public TCPServer_SSL(string address, string port)
    {
        _port = Convert.ToInt32(port);
        _address = IPAddress.Parse(address);
    }
    #endregion // CTORs

    Properties#region Properties
    public IPAddress Address
    {
        get { return _address; }
        set { _address = value; }
    }

    public int Port
    {
        get { return _port; }
        set { _port = value; }
    }
    #endregion

    public void Listen()
    {
        try
        {
            _listener = new TcpListener(_address, _port);

            // Fire up the server.
            _listener.Start();

            // Enter the listening loop.
            while (true)
            {
                Console.Write("Looking for someone to talk to… ");

                // Wait for connection.
                TcpClient newClient = _listener.AcceptTcpClient();
                Console.WriteLine("Connected to new client");

                // Spin a thread to take care of the client.
                ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessClient),
                                         newClient);
            }


        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: {0}", e);
        }
        finally
        {
            // Shut it down.
            _listener.Stop();
        }

        Console.WriteLine("/nHit any key (where is ANYKEY?) to continue…");
        Console.Read();
    }

    private void ProcessClient(object client)
    {
        using (TcpClient newClient = (TcpClient)client)
        {
            // Buffer for reading data.
            byte[] bytes = new byte[1024];
            string clientData = null;

            //第三个参数是验证客户端证书的回调,最后一个参数是用来指定多个证明自己的证书的回调,这里为空
            //前两个参数分别是一个流和是否在关闭sslstrem关闭内部流的选项
            using (SslStream sslStream = new SslStream(newClient.GetStream(), false, ValidateClientCertificate,null))
            {
                try
                {
                    //该方法的第一个参数是用于服务端身份验证的证书,第二个参数指定是否需要验证客户端的身份
                    //第三个参数是指定安全传输的协议,最后一个参数指定是否检查吊销证书
                    sslStream.AuthenticateAsServer(GetServerCert("117f32ff000000000007"), true, SslProtocols.Tls, false);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }

                // Loop to receive all the data sent by the client.
                int bytesRead = 0;

                while ((bytesRead = sslStream.Read(bytes, 0, bytes.Length)) != 0)
                {
                    // Translate data bytes to an ASCII string.
                    clientData = Encoding.ASCII.GetString(bytes, 0, bytesRead);
                    Console.WriteLine("Client says: {0}", clientData);

                    // Thank them for their input.
                    bytes = Encoding.ASCII.GetBytes("Thanks call again!");

                    // Send back a response.

                    sslStream.Write(bytes, 0, bytes.Length);
                }
            }
        }
    }

    public static bool ValidateClientCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        Console.WriteLine("ValidateClientCertificate-certificate.Subject:/r/n{0}", certificate.Subject);
        if (sslPolicyErrors != SslPolicyErrors.None && sslPolicyErrors != SslPolicyErrors.RemoteCertificateChainErrors)
            return false;
        if (sslPolicyErrors != SslPolicyErrors.RemoteCertificateChainErrors)
        {
            //不判断吊销证书
            foreach (X509ChainStatus s in chain.ChainStatus)
            {
                Console.WriteLine("ValidateClientCertificate-chain.ChainStatus:/r/n{0}-{1}", s.Status, s.StatusInformation);
                if (s.Status != X509ChainStatusFlags.OfflineRevocation && s.Status != X509ChainStatusFlags.RevocationStatusUnknown)
                {
                    return false;
                }
            }
        }
        return true;
    }
    //该方法从本地计算机的个人证书区域按证书序列号查找指定的证书用于服务器身份验证
    //以及打印出证书的详细信息
    private static X509Certificate GetServerCert(string serialNumber)
    {
        X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        try
        {
            store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection certificate =
                    store.Certificates.Find(X509FindType.FindBySerialNumber,
                                            serialNumber, true);
            X509Certificate2 x509 = certificate[0];
            byte[] rawdata = x509.RawData;
            Console.WriteLine("509 count :{0}", store.Certificates.Count);
            Console.WriteLine("Content Type: {0}{1}", X509Certificate2.GetCertContentType(rawdata), Environment.NewLine);
            Console.WriteLine("Friendly Name: {0}{1}", x509.FriendlyName, Environment.NewLine);
            Console.WriteLine("Certificate Verified?: {0}{1}", x509.Verify(), Environment.NewLine);
            Console.WriteLine("Simple Name: {0}{1}", x509.GetNameInfo(X509NameType.SimpleName, true), Environment.NewLine);
            Console.WriteLine("Signature Algorithm: {0}{1}", x509.SignatureAlgorithm.FriendlyName, Environment.NewLine);
            Console.WriteLine("Private Key: {0}{1}", x509.PrivateKey.ToXmlString(false), Environment.NewLine);
            Console.WriteLine("Public Key: {0}{1}", x509.PublicKey.Key.ToXmlString(false), Environment.NewLine);
            Console.WriteLine("Certificate Archived?: {0}{1}", x509.Archived, Environment.NewLine);
            Console.WriteLine("Length of Raw Data: {0}{1}", x509.RawData.Length, Environment.NewLine);
            Console.WriteLine("x509.SerialNumber: {0}{1}", x509.SerialNumber, Environment.NewLine);

            if (certificate.Count > 0)
                return (certificate[0]);
            else
                return (null);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            return null;
        }
        finally
        {
            store.Close();
        }
    }
}
控制台代码
 static void Main(string[] args)
        {
            try
            {
                TCPServer_SSL server = new TCPServer_SSL("127.0.0.1", "8000");
                server.Listen();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            Console.Read();
        }

客户端

类库
using System;
using System.Net.Sockets;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
class TCPClient_SSL
{
    private TcpClient _client = null;
    private IPAddress _address = IPAddress.Parse("127.0.0.1");
    private int _port = 5;
    private IPEndPoint _endPoint = null;

    public TCPClient_SSL(string address, string port)
    {
        _address = IPAddress.Parse(address);
        _port = Convert.ToInt32(port);
        _endPoint = new IPEndPoint(_address, _port);
    }

    public void ConnectToServer(string msg)
    {
        try
        {
            using (_client = new TcpClient())
            {
                _client.Connect(_endPoint);

                //SslStream第一个参数是一个流,可以是由用Socket类new的一个NetworkStream
                //第二个参数为false的时候,关闭sslStream就会关闭对应的NetworkStream
                //第三个参数是一个回调,用来控制服务端的验证
                using (SslStream sslStream = new SslStream(_client.GetStream(),
                                false, new RemoteCertificateValidationCallback(
                                    ValidateServerCertificate)))
                {

                    X509CertificateCollection cert = new X509CertificateCollection();
                    //下面是从一个导出证书文件里加载证书
                    X509Certificate cer = X509Certificate2.CreateFromCertFile("c://certs//huhao.cer");
                    cert.Add(cer);
                    //AuthenticateAsClient方法第一个参数要写服务端证书的名字,和服务器的机器名和dns名应一致
                    //第二个参数是一个证书集合,如果是多个证书,可以在一个回调函数里选择指定证书用以验证客户端
                    //第三个参数指定安全传输的协议,可以是ssl,tls的不同版本
                    //最后一个参数表示是否检查吊销证书列表,吊销证书是定时推给服务器的,验证起来比较耗性能
                    sslStream.AuthenticateAsClient("ms-7fa82788ed1e", cert, System.Security.Authentication.SslProtocols.Tls, false);
                    sslStream.ReadTimeout = 5000;
                    sslStream.WriteTimeout = 5000;

                    // Get the bytes to send for the message.
                    byte[] bytes = Encoding.ASCII.GetBytes(msg);

                    // Send message.
                    Console.WriteLine("Sending message to server: " + msg);

                    //这里可以使用BeginWrite
                    sslStream.Write(bytes, 0, bytes.Length);

                    // Get the response.
                    // Buffer to store the response bytes.
                    bytes = new byte[1024];

                    // Display the response.
                    //这里可以使用BeginRead
                    int bytesRead = sslStream.Read(bytes, 0, bytes.Length);
                    string serverResponse = Encoding.ASCII.GetString(bytes, 0,
                          bytesRead);
                    Console.WriteLine("Server said: " + serverResponse);
                }
            }
        }
        catch (SocketException e)
        {
            Console.WriteLine("There was an error talking to the server: {0}",
            e.ToString());
        }
    }


    private bool ValidateServerCertificate(object sender,
                                               X509Certificate certificate,
                                               X509Chain chain,
                                               SslPolicyErrors sslPolicyErrors)
    {
        if (sslPolicyErrors == SslPolicyErrors.None)
        {
            return true;
        }
        else
        {
            if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
            {
                Console.WriteLine("The X509Chain.ChainStatus returned an array " +
                   "of X509ChainStatus objects containing error information.");
            }
            else if (sslPolicyErrors ==
                     SslPolicyErrors.RemoteCertificateNameMismatch)
            {
                Console.WriteLine("There was a mismatch of the name " +
                  "on a certificate.");
            }
            else if (sslPolicyErrors ==
                     SslPolicyErrors.RemoteCertificateNotAvailable)
            {
                Console.WriteLine("No certificate was available.");
            }
            else
            {
                Console.WriteLine("SSL Certificate Validation Error!");
            }
        }

        Console.WriteLine(Environment.NewLine +
                          "SSL Certificate Validation Error!");
        Console.WriteLine(sslPolicyErrors.ToString());

        return false;
    }
}


控制台

static void Main(string[] args)
        {
            try
            {
                TCPClient_SSL client = new TCPClient_SSL("127.0.0.1", "8000");
                client.ConnectToServer("11111");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            Console.Read();
        }

注意事项

1.         如果TcpServer是一个windows服务,用于服务端的证书不能用X509Certificate2.CreateFromCertFile方法加载导出的证书文件来获取,而应该用相关API来读取本地计算机证书存储器的my区域的证书,查找可以按证书序列号来查,具体代码大约如下。

X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

store.Open(OpenFlags.ReadOnly);

X509Certificate2Collection cert = store.Certificates.Find(X509FindType.FindBySerialNumber,

“611cea09000000000002”, false);

_certificate = cert[0];

2.         如果是服务端是windows服务,由于windows服务运行账户是本地系统账户,并不是某个具体用户,所以这时候用于服务端验证的证书应该导入到本地计算机的my(个人)区域,然后本地计算的“受信任的根证书颁发机构“要导入客户端证书的CA证书(在客户端证书申请页有下载链接)。

3.         出现“启用服务端SSL必须使用关联私钥的证书“(The server mode SSL must use a certificate with the associated private key.)是因为服务端用的证书是从文件里取的,而不是通过证书存储API取出来的,一般是这个问题。

4.         出现“没有识别提供给安全软件包的凭证“(System.Net.SSPIWrapper.AcquireCredentialsHandle方法)的错误,可能是因为你的机器是虚拟机,或者你试着重启一下试试能否解决,该问题出现后,代码几乎没变,后来就好了。

5.         通过证书申请页面申请的证书一般会安装在当前用户的个人存储区,如果要把这个证书安装到计算机里,可以在证书管理控制台里把用户个人区域里的证书连私钥导出成pfx文件(不是.cer文件),然后在在证书管理控制台(开始-运行-输入mmc.exe,在添加删除管理单元里把“证书“单元添加进来,可以选择当前用户和计算机)里导入到计算机的个人区域里。

6.         可以使用SslStream的异步读写方法来提高性能

7.         从证书存储区获取证书的时候用证书序列号比较容易精确的获取证书,比用subject等要准确

8.         SslStream.AuthenticateAsClientd的targetHost参数为客户端验证的服务端证书名称,就是服务器认证证书的“颁发给“字段。这里一定要写对,既不是CA的服务器地址,也不是类似http://ms-onlytiancai/certsrv/的字符串,也不是TcpServer的地址(实际上是TcpServer的netbios名称或dns名称,和申请服务器证书时的姓名字段是一个,必须相同)。如果填写其它字符串,在客户端验证的时候会出RemoteCertificateNameMismatch错误。

https webServices

服务端配置SSL(https)

1.         在IIS的默认网站的属性-目录安全性-安全通信-服务器证书对话框里,选择新建一个证书,按照向导,一路向下,到“站点公用名称列”,在“公用名称”里输入服务器的dns名称或者netbios名称,这里一定要填写对,最后会在硬盘上生成一个cerreq.txt文件的服务器证书申请单。

2.         把上一步生成的申请单传给CA,在CA服务器的“证书颁发机构”管理器上右键点“新建证书申请”,在弹出的对话框里选择cerreq.txt,确定后“挂起的证书”节点会多一个证书申请,右键点“颁发”。颁发后在到“已颁发的证书”节点里找到刚刚颁发的证书,右键点“导出”,对话框里在“包含二进制的列”下拉框里选择“二进制证书”,然后选择“保存证书到一个文件”,最后会在硬盘上生成一个.cer文件(应该是带私钥的)。

3.         在服务器上拷贝一下上一步生成的.cer文件,再在IIS属性的目录安全性-安全通信-服务器证书,弹出一个“欢迎使用web服务器证书向导”对话框,下一步后选择“处理已挂起的证书申请”,下一步中选择拷贝过来的.cer文件,再下一步选443端口。

4.         然后在你的web服务的虚拟目录-目录安全性-安全通信-点编辑按钮,把“要求安全通道(ssl)”的复选框打上,如果需要验证客户端证书的话,在“客户端证书”单选框列表里选择“要求客户端证书”。如果选择了“要求客户端证书”,可以在下面的“启用客户端证书映射”的“编辑”对话框里把证书映射到服务器的指定账户。

5.         如果启用了“要求客户端证书”,服务器要信任客户端证书的CA,具体操作如下。开始-运行,输入mmc.exe。在控制台里点文件-添加/删除管理单元,选择“证书”单元,然后点添加的时候选择“计算机账户-本地计算机”(一定要选对,如果选择“我的用户账户的话,只是当前账户信任某个CA,当前计算机不会信任指定CA的”)。然后在证书控制台里的“受信任的颁发机构”节点上右键点导入,把在证书申请页面上下载的CA证书导入进来。这样这台服务器就新人所有这个CA颁发的客户端证书了。

客户端访问

1、 先为客户端申请一个客户端证书,CA就用服务器计算机信任的CA。

2、 编码,如下,假设cxz计算机上有一个service的服务,有个helloworld方法

源码下载地址
http://files.cnblogs.com/onlytiancai/ssltest.rar

相关链接:
Securing Stream Data
http://codeidol.com/csharp/csharpckbk2/Security/Securing-Stream-Data/
构建基于windows证书服务的公钥基础结构
http://bbs.51cto.com/thread-426225-1-1.html
Windows 2000 公钥基础结构详解
http://www.cnblogs.com/coldwine/archive/2005/08/31/227071.html
声明:本文代码修改自相关链接的第一篇文章

原文出自:
http://www.cnblogs.com/onlytiancai/archive/2007/10/15/925425.html

using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using CallSslWebService.cxz;

namespace CallSslWebService
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //挂接验证服务端证书的回调
                ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidationCallback;

cxz.Service service = new Service(); //实例一个web服务

//如果web服务没有启用匿名访问,要声明credentials
                ICredentials credentials = new NetworkCredential("administrator", "1234%^@");
                service.Credentials = credentials;
                
                //如果服务器要求提供客户端证书,下面代码提供了客户端证书
                X509Certificate cer = X509Certificate.CreateFromCertFile("C://certs//client.cer");
                service.ClientCertificates.Add(cer);

//调用web服务
                Console.WriteLine(service.HelloWorld());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            Console.Read();
        }

public static bool RemoteCertificateValidationCallback(Object sender,
            X509Certificate certificate,
            X509Chain chain,
            SslPolicyErrors sslPolicyErrors)
        {
            //如果没有错就表示验证成功
            if (sslPolicyErrors == SslPolicyErrors.None)
                return true;
            return false;
        }
    }
}

ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref10/html/T_System_Net_Security_SslStream_Members.htm

提供一个用于客户端-服务器通信的流,此流使用安全套接字层 (SSL) 安全协议对服务器及客户端(可选)进行身份验证。

下表列出了由 SslStream 类型公开的成员。

转载于:https://www.cnblogs.com/BinZeng/p/3373434.html

用TLS实现安全TCP传输及配置和访问https的web服务(转)相关推荐

  1. WebGateway系列(4): 配置HTTPS访问IRIS的Web服务

    经常被问到有关IRIS如何支持SSL,HTTPS的问题,有必要写个东西介绍一下. HTTPS的原理 简单的说,https实现两个目的:一是访问网站加密,2是确认被访问的网站是真的. 首先,被访问的网站 ...

  2. frps 多个_使用frp工具实现内网的穿透以及配置多个ssh和web服务

    frp简介 frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 http 和 https 应用协议提供了额外的能力,且尝试性支持了点对点穿透. 环境准备 ssh连接 ...

  3. frp工具实现内网穿透以及配置多个ssh和web服务

    frp简介 frp简介 环境准备 安装及配置步骤 frp简介 frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp 协议,为 http 和 https 应用协议提供了额外的能力, ...

  4. centos8 配置 dns_Linux搭建DHCP+DNS+WEB服务

    实验环境: 一台GNS3 一台Centos7的Linux系统 一台server2016服务器 两台PC机 实验目的: 搭建一台DHCP服务自动分配IP地址给两台PC机 搭建一台DNS解析服务器解析域名 ...

  5. 【VMCloud云平台】SCVMM配置(九)创建Web服务模板

    继续上一篇完成SCVMM创建SQL服务模板后,本篇将继续讲述云平台中的第一个组件--SCVMM创建第一个Web服务模板(即下图中的SCVMM01,蓝色为未实现,绿色为计划中,红色为实施中). 1. 登 ...

  6. TCP传输连接建立与释放详解

    一直以来有许多读者朋友对TCP的传输连接建立和释放过程不是很理解,而这又是几乎网络认证中必考的知识点,包括软考.CCNA\CCNP.H3CNA\H3CNE等,为此再把笔者年度巨作,广受好评的--< ...

  7. 2、nginx常用配置----作为web服务端

    目录 环境及目的 nginx配置文件特点和结构 1 特性 2 主配置文件结构 常用全局配置 1 main段 2 events段 web服务相关配置 1 server_namerootlisten 11 ...

  8. nginx工作笔记005---nginx配置负载均衡_在微服务中实现网关集群_实现TCP传输层协议__http协议的负载均衡

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 我们在微服务中,由于网关的存在,后来,在nginx中都不需要在配置其他服务的地址了,只需要,配置一 ...

  9. 计算机网络基础知识--TCP/IP协议、IP分组、TCP传输

    转 计算机网络基础知识--TCP/IP协议.IP分组.TCP传输 2017年12月08日 08:35:09 孔维昊 阅读数 1820 查看全文 http://www.taodudu.cc/news/s ...

最新文章

  1. 【C#】详解使用Enumerable.Distinct方法去重
  2. Spring-Boot 2.1.x和主要的bean定义
  3. oracle 更改启动内存,Oracle 11gR2修改内存参数后无法启动问题
  4. MUI - 自动轮播图 实现
  5. 网络批量后修改服务器,企业网络批量安装服务器搭建案例
  6. JavaSE基础语法-笔记
  7. Tricks(二十九)—— 2^10000 的位数
  8. Qt视频播放器界面Demo
  9. GVRP和VTP的比较与区别
  10. iphone相册源码下载(仿three20)
  11. 数据化运营需要的四个层次
  12. Javaweb后端技术(下)02-Mybatis
  13. Apple 软件产品使用的 TCP 和 UDP 端口
  14. lisp语言绘制路灯_LISP语言在AD道路设计方案中各种应用
  15. 网络安全关于Windows下BAT脚本使用
  16. IT行业吃香技能TOP榜,欢迎补充
  17. UR机器人的优点 | 推动制造生产可持续性
  18. 创业公司如何留住人才
  19. 使用ffmpeg缩小视频体积的几种方式
  20. 比KMP算法更简单更快的字符串匹配算法

热门文章

  1. ffmpeg 怎么处理udp音频_视音频数据处理入门:UDP-RTP协议解析
  2. python while函数_详解python while 函数及while和for的区别
  3. 业界首个机密计算容器运行时—Inclavare Containers正式进入CNCF!
  4. vi 命令linux退不出来,Linux 基本命令 vi的退出方法
  5. html制作表格保存为txt文件,可将HTML表格导出为Excel|csv|txt文件的jQuery插件
  6. hbase shell 查看列名_hbase shell 命令行的操作
  7. html距离已过去多久,用javascript写的倒计时,从某年某月距离到今天还有多少时间...
  8. java利用poi读取excel_java利用POI 读取EXCEL
  9. python anaconda下载包_【Python开发】anaconda3 安装python包
  10. mysql图片路径varchar大小_Mysqlvarchar大小长度问题_MySQL