zoukankan      html  css  js  c++  java
  • Java调用Http/Https接口(2)--HttpURLConnection/HttpsURLConnection调用Http/Https接口

    HttpURLConnection是JDK自身提供的网络类,不需要引入额外的jar包。文中所使用到的软件版本:Java 1.8.0_191。

    1、服务端

    参见Java调用Http接口(1)--编写服务端 

    2、调用Http接口

    2.1、GET请求

        public static void get() {
            try {
                String requestPath = "http://localhost:8080/demo/httptest/getUser?userId=1000&userName=" + URLEncoder.encode("李白", "utf-8");
                URL url = new URL(requestPath);
                //设置代理
                //InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 8888);  
                //Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
                //connection = (HttpURLConnection)url.openConnection(proxy);
                
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("GET");
                connection.connect();
                
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    byte[] b = getBytesFromInputStream(connection.getInputStream());
                    String back = new String(b);
                    System.out.println("GET返回结果:" + back);
                } else {
                    System.out.println("GET请求状态码:" + connection.getResponseCode());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    2.2、POST请求(发送键值对数据)

        public static void post() {
            try {
                String requestPath = "http://localhost:8080/demo/httptest/getUser";
                URL url = new URL(requestPath);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                connection.connect();
                
                String param = "userId=1000&userName=李白";
                bytesToOutputStream(param.getBytes(), connection.getOutputStream());
                
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    byte[] b = getBytesFromInputStream(connection.getInputStream());
                    String back = new String(b);
                    System.out.println("POST返回结果:" + back);
                } else {
                    System.out.println("POST返回状态码:" + connection.getResponseCode());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    2.3、POST请求(发送JSON数据)

        public static void post2() {
            try {
                String requestPath = "http://localhost:8080/demo/httptest/addUser";
                URL url = new URL(requestPath);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                connection.setRequestProperty("Content-type", "application/json");
                connection.connect();
                
                String param = "{"userId": "1001","userName":"杜甫"}";
                bytesToOutputStream(param.getBytes(), connection.getOutputStream());
                
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    byte[] b = getBytesFromInputStream(connection.getInputStream());
                    String back = new String(b);
                    System.out.println("POST2返回结果:" + back);
                } else {
                    System.out.println("POST2返回状态码:" + connection.getResponseCode());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    2.4、上传文件

        public static void upload() {
            try {
                String requestPath = "http://localhost:8080/demo/httptest/upload";
                URL url = new URL(requestPath);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                connection.setRequestProperty("Content-type", "file/*");
                connection.connect();
                
                FileInputStream fileInputStream = new FileInputStream("d:/a.jpg");
                inputStreamToOutputStream(fileInputStream, connection.getOutputStream());
                
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    byte[] b = getBytesFromInputStream(connection.getInputStream());
                    String back = new String(b);
                    System.out.println("upload返回结果:" + back);
                } else {
                    System.out.println("upload返回状态码:" + connection.getResponseCode());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    2.5、上传文件及发送键值对数据

    2.5.1、分析数据结构

    通过抓包工具分析页面表单上传文件的过程,可以看出传输数据的结构:

     

    2.5.2、根据分析出的数据结构编写代码

        public static void multi() {
            String BOUNDARY = java.util.UUID.randomUUID().toString();
            String TWO_HYPHENS = "--";
            String LINE_END = "
    ";
            FileInputStream in = null;
            try {
                String requestPath = "http://localhost:8080/demo/httptest/multi";
                URL url = new URL(requestPath);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setRequestProperty("Content-type", "multipart/form-data; BOUNDARY=" + BOUNDARY);
                connection.connect();
                
                StringBuffer sb = new StringBuffer();
                //封装键值对数据1
                sb.append(TWO_HYPHENS).append(BOUNDARY).append(LINE_END);
                sb.append("Content-Disposition: form-data; name="param1"").append(LINE_END);
                sb.append(LINE_END);
                sb.append("参数1").append(LINE_END);
                
                //封装键值对数据2
                sb.append(TWO_HYPHENS).append(BOUNDARY).append(LINE_END);
                sb.append("Content-Disposition: form-data; name="param2"").append(LINE_END);
                sb.append(LINE_END);
                sb.append("参数2").append(LINE_END);
                
                //封装文件数据
                sb.append(TWO_HYPHENS).append(BOUNDARY).append(LINE_END);
                sb.append("Content-Disposition: form-data; name="file"; filename="a.jpg"").append(LINE_END);
                sb.append("Content-Type: file/*").append(LINE_END);
                sb.append(LINE_END);
    
                bytesToOutputStream(sb.toString().getBytes(), connection.getOutputStream());
    
                in = new FileInputStream("d:/a.jpg");
                inputStreamToOutputStream(in, connection.getOutputStream());
                
                //写入标记结束位
                String end = (LINE_END + TWO_HYPHENS + BOUNDARY + TWO_HYPHENS + LINE_END);
                bytesToOutputStream(end.getBytes(), connection.getOutputStream());
                
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    byte[] b = getBytesFromInputStream(connection.getInputStream());
                    String back = new String(b);
                    System.out.println("multi返回结果:" + back);
                } else {
                    System.out.println("multi返回状态码:" + connection.getResponseCode());
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                FileUtil.close(in);
            }
        }

    2.5.3、上传文件方法变通

    这种方式上传文件完全是模拟页面的提交行为来编码的,比较繁琐。可以把文件转成字符串,然后通过键值对传给服务端,服务端执行相反的过程来存储文件:

    客户端:文件-> 字节数组->Base64字符串

    服务端:Base64字符串-> 字节数组->文件

    按照这种方式来实现应该比较容易,这里就不演示了。

    2.6、下载文件

        public static void download() {
            FileOutputStream out = null;
            try {
                String requestPath = "http://localhost:8080/demo/httptest/download";
                URL url = new URL(requestPath);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.connect();
                System.out.println("download返回状态码:" + connection.getResponseCode());
                String contentDisposition = connection.getHeaderField("Content-Disposition");//attachment; filename="a.jpg"
                String fileName = "none";
                if (contentDisposition != null && contentDisposition.indexOf("filename") > -1) {
                    fileName = contentDisposition.substring(contentDisposition.indexOf(""") + 1, contentDisposition.length() - 1);
                    fileName = java.net.URLDecoder.decode(fileName, "utf-8");
                }
                out = new FileOutputStream("d:/temp/dowload_" + System.currentTimeMillis() + "_" + fileName);
                inputStreamToOutputStream(connection.getInputStream(), out);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                FileUtil.close(out);
            }
        }

    2.7、完整例子

    package com.inspur.demo.http.client;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.HttpURLConnection;
    //import java.net.InetSocketAddress;
    //import java.net.Proxy;
    import java.net.URL;
    import java.net.URLEncoder;
    
    import com.inspur.demo.common.util.FileUtil;
    
    /**
     * 
     * 通过HttpURLConnection调用Http接口
     *
     */
    public class HttpURLConnectionCase {
        /**
         * GET请求
         */
        public static void get() {
            try {
                String requestPath = "http://localhost:8080/demo/httptest/getUser?userId=1000&userName=" + URLEncoder.encode("李白", "utf-8");
                URL url = new URL(requestPath);
                //设置代理
                //InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 8888);  
                //Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
                //connection = (HttpURLConnection)url.openConnection(proxy);
                
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("GET");
                connection.connect();
                
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    byte[] b = getBytesFromInputStream(connection.getInputStream());
                    String back = new String(b);
                    System.out.println("GET返回结果:" + back);
                } else {
                    System.out.println("GET请求状态码:" + connection.getResponseCode());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /**
         * POST请求,发送键值对数据
         */
        public static void post() {
            try {
                String requestPath = "http://localhost:8080/demo/httptest/getUser";
                URL url = new URL(requestPath);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                connection.connect();
                
                String param = "userId=1000&userName=李白";
                bytesToOutputStream(param.getBytes(), connection.getOutputStream());
                
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    byte[] b = getBytesFromInputStream(connection.getInputStream());
                    String back = new String(b);
                    System.out.println("POST返回结果:" + back);
                } else {
                    System.out.println("POST返回状态码:" + connection.getResponseCode());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /**
         * POST请求,发送json格式数据
         */
        public static void post2() {
            try {
                String requestPath = "http://localhost:8080/demo/httptest/addUser";
                URL url = new URL(requestPath);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                connection.setRequestProperty("Content-type", "application/json");
                connection.connect();
                
                String param = "{"userId": "1001","userName":"杜甫"}";
                bytesToOutputStream(param.getBytes(), connection.getOutputStream());
                
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    byte[] b = getBytesFromInputStream(connection.getInputStream());
                    String back = new String(b);
                    System.out.println("POST2返回结果:" + back);
                } else {
                    System.out.println("POST2返回状态码:" + connection.getResponseCode());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 上传文件
         */
        public static void upload() {
            try {
                String requestPath = "http://localhost:8080/demo/httptest/upload";
                URL url = new URL(requestPath);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                connection.setRequestProperty("Content-type", "file/*");
                connection.connect();
                
                FileInputStream fileInputStream = new FileInputStream("d:/a.jpg");
                inputStreamToOutputStream(fileInputStream, connection.getOutputStream());
                
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    byte[] b = getBytesFromInputStream(connection.getInputStream());
                    String back = new String(b);
                    System.out.println("upload返回结果:" + back);
                } else {
                    System.out.println("upload返回状态码:" + connection.getResponseCode());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 上传文件及发送键值对数据
         */
        public static void multi() {
            String BOUNDARY = java.util.UUID.randomUUID().toString();
            String TWO_HYPHENS = "--";
            String LINE_END = "
    ";
            FileInputStream in = null;
            try {
                String requestPath = "http://localhost:8080/demo/httptest/multi";
                URL url = new URL(requestPath);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setRequestProperty("Content-type", "multipart/form-data; BOUNDARY=" + BOUNDARY);
                connection.connect();
                
                StringBuffer sb = new StringBuffer();
                //封装键值对数据1
                sb.append(TWO_HYPHENS).append(BOUNDARY).append(LINE_END);
                sb.append("Content-Disposition: form-data; name="param1"").append(LINE_END);
                sb.append(LINE_END);
                sb.append("参数1").append(LINE_END);
                
                //封装键值对数据2
                sb.append(TWO_HYPHENS).append(BOUNDARY).append(LINE_END);
                sb.append("Content-Disposition: form-data; name="param2"").append(LINE_END);
                sb.append(LINE_END);
                sb.append("参数2").append(LINE_END);
                
                //封装文件数据
                sb.append(TWO_HYPHENS).append(BOUNDARY).append(LINE_END);
                sb.append("Content-Disposition: form-data; name="file"; filename="a.jpg"").append(LINE_END);
                sb.append("Content-Type: file/*").append(LINE_END);
                sb.append(LINE_END);
    
                bytesToOutputStream(sb.toString().getBytes(), connection.getOutputStream());
    
                in = new FileInputStream("d:/a.jpg");
                inputStreamToOutputStream(in, connection.getOutputStream());
                
                //写入标记结束位
                String end = (LINE_END + TWO_HYPHENS + BOUNDARY + TWO_HYPHENS + LINE_END);
                bytesToOutputStream(end.getBytes(), connection.getOutputStream());
                
                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    byte[] b = getBytesFromInputStream(connection.getInputStream());
                    String back = new String(b);
                    System.out.println("multi返回结果:" + back);
                } else {
                    System.out.println("multi返回状态码:" + connection.getResponseCode());
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                FileUtil.close(in);
            }
        }
        
        /**
         * 下载文件
         */
        public static void download() {
            FileOutputStream out = null;
            try {
                String requestPath = "http://localhost:8080/demo/httptest/download";
                URL url = new URL(requestPath);
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.connect();
                System.out.println("download返回状态码:" + connection.getResponseCode());
                String contentDisposition = connection.getHeaderField("Content-Disposition");//attachment; filename="a.jpg"
                String fileName = "none";
                if (contentDisposition != null && contentDisposition.indexOf("filename") > -1) {
                    fileName = contentDisposition.substring(contentDisposition.indexOf(""") + 1, contentDisposition.length() - 1);
                    fileName = java.net.URLDecoder.decode(fileName, "utf-8");
                }
                out = new FileOutputStream("d:/temp/dowload_" + System.currentTimeMillis() + "_" + fileName);
                inputStreamToOutputStream(connection.getInputStream(), out);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                FileUtil.close(out);
            }
        }
        
        /**
         * 从输入流获取数据
         * @param in
         * @return
         * @throws IOException
         */
        private static byte[] getBytesFromInputStream(InputStream in) throws IOException {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int len;
            while ((len = in.read(b)) != -1) {
                out.write(b, 0, len);
            }
            byte[] bytes = out.toByteArray();
            out.close();
            return bytes;
        }
        
        /**
         * 把字节数组写入输出流
         * @param bytes
         * @param out
         * @throws IOException
         */
        private static void bytesToOutputStream(byte[] bytes, OutputStream out) throws IOException {
            ByteArrayInputStream in = new ByteArrayInputStream(bytes);
            byte[] b = new byte[1024];
            int len;
            while ((len = in.read(b)) != -1) {
                out.write(b, 0, len);
            }
            out.flush();
            in.close();
        }
        
        /**
         * 从输入流读取数据并写入输出流
         * @param out
         * @param bytes
         * @throws IOException
         */
        private static void inputStreamToOutputStream(InputStream in, OutputStream out) throws IOException {
            byte[] b = new byte[1024];
            int len;
            while ((len = in.read(b)) != -1) {
                out.write(b, 0, len);
            }
            out.flush();
        }
        
        public static void main(String[] args) {
            get();
            post();
            post2();
            upload();
            multi();
            download();
        }
    }
    View Code

    3、调用Https接口

    调用Https接口需要用HttpsURLConnection,与调用Http接口不一样的部分主要在设置ssl部分,下面用GET请求来演示ssl的设置,其他调用方式类似。

    3.1、导入cer证书

    对于自定义证书的网站,需把证书用java自带的工具keytool导入本地,如导入到d:/temp目录下

    cd d:/temp
    keytool -import -alias aa -keystore cacerts -file aa.cer -trustcacerts

    如果当前目录已有cacerts证书库,则需输入密码;如果没有则需设置密码,会在当前目录下生成cacerts证书库。

    也可以不导入,使用默认实现的DefaultTrustManager,信任所有,将导致不安全。

    3.2、示例

    package com.inspur.demo.http.client;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    import java.security.KeyStore;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.KeyManager;
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.TrustManagerFactory;
    import javax.net.ssl.X509TrustManager;
    
    import com.inspur.demo.common.util.FileUtil;
    
    
    /**
     * 通过HttpsURLConnection调用Https接口
     */
    public class HttpsURLConnectionCase {
        public static void main(String[] args) {
            try {
                /*
                 * 请求有权威证书的地址
                 */
                String requestPath = "https://www.baidu.com/";
                HttpsURLConnection connection = getHttpsURLConnection(requestPath, "GET");
                String result = new String(getBytesFromInputStream(connection.getInputStream()));
                System.out.println("GET1返回结果:" + result);
                
                /*
                 * 请求自定义证书的地址
                 */
                //获取信任库
                KeyStore trustStore = getkeyStore("jks", "d:/temp/cacerts", "123456");
                
                //不需客户端证书
                requestPath = "https://x.x.x.x:9010/zsywservice";
                connection = getHttpsURLConnection(requestPath, "GET", null, null, trustStore);
                result = new String(getBytesFromInputStream(connection.getInputStream()));
                System.out.println("GET2返回结果:" + result);
              
                //需客户端证书
                requestPath = "https://x.x.x.x:9016/zsywservice";
                KeyStore keyStore = getkeyStore("pkcs12", "d:/client.p12", "123456");
                connection = getHttpsURLConnection(requestPath, "GET", keyStore, "123456", trustStore);
                result = new String(getBytesFromInputStream(connection.getInputStream()));
                System.out.println("GET3返回结果:" + result);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
    
        /**
         * 获取证书
         * @return
         */
        private static KeyStore getkeyStore(String type, String filePath, String password) {
            KeyStore keySotre = null;
            FileInputStream in = null;
            try {
                keySotre = KeyStore.getInstance(type);
                in = new FileInputStream(new File(filePath));
                keySotre.load(in, password.toCharArray());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                FileUtil.close(in);
            }
            return keySotre;
        }
    
        private static HttpsURLConnection getHttpsURLConnection(String uri, String method) throws Exception {
            URL url = new URL(uri);
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
            connection.setRequestMethod(method);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            return connection;
        }
        
        /**
         * 获取连接
         * @param uri
         * @param method
         * @param keyStore
         * @param trustStore
         * @return
         * @throws Exception
         */
        private static HttpsURLConnection getHttpsURLConnection(String uri, String method, KeyStore keyStore, String keyStorePassword, KeyStore trustStore) throws Exception {
            KeyManager[] keyManagers = null;
            TrustManager[] trustManagers = null;
            if (keyStore != null) {
                KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
                keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
                keyManagers = keyManagerFactory.getKeyManagers();
            }
            if (trustStore != null) {
                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
                trustManagerFactory.init(trustStore);
                trustManagers = trustManagerFactory.getTrustManagers();
            } else {
                trustManagers = new TrustManager[] { new DefaultTrustManager()};
            }
            
            //设置服务端支持的协议
            SSLContext context = SSLContext.getInstance("TLSv1.2");
            context.init(keyManagers, trustManagers, null);
            SSLSocketFactory sslFactory = context.getSocketFactory();
    
            URL url = new URL(uri);
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
            connection.setSSLSocketFactory(sslFactory);
            //验证URL的主机名和服务器的标识主机名是否匹配
            connection.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    //if ("xxx".equals(hostname)) {
                    //    return true;
                    //} else {
                    //    return false;
                    //}
                    return true;
                }
            });
            connection.setRequestMethod(method);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            return connection;
        }
        
        /**
         * 默认的TrustManager实现,不安全
         */
        private static final class DefaultTrustManager implements X509TrustManager {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
    
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
    
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        }
        
        /**
         * 从输入流获取数据
         * @param in
         * @return
         * @throws IOException
         */
        private static byte[] getBytesFromInputStream(InputStream in) throws IOException {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int len;
            while ((len = in.read(b)) != -1) {
                out.write(b, 0, len);
            }
            byte[] bytes = out.toByteArray();
            out.close();
            return bytes;
        }
    }

    3.2、Received fatal alert:handshake_failure

     出现这种这种问题的一种情况是由于客户端使用的协议,服务端不支持造成的;修改为服务端所支持的协议即可。在getHttpsURLConnection方法中修改:

    SSLContext context = SSLContext.getInstance("TLSv1.2");

    可选的协议参数有:SSL、SSLv2、SSLv3、TLS、TLSv1、TLSv1.1、TLSv1.2;TLS是SSL标准化的产物,故现在基本只使用TLS相关的参数。

    可以用linux的curl命令来测试服务端支持哪些协议:

    curl -k https://x.x.x.x:9016/zsywservice --tlsv1.2 -v

    可选协议有:--tlsv1、--tlsv1.0、--tlsv1.1、--tlsv1.2、--tlsv1.3

    如果出现如下信息,则表示不支持:

  • 相关阅读:
    Makefile.am, Makefile.in 与 Makefile的关系(转)
    Linux vim命令记录
    重启nginx后丢失nginx.pid的解决方法(转)
    tail -f 不断刷新
    转:Json 语法 格式
    转:mongoDB 修改 ulimit
    转:Android IOS WebRTC 音视频开发总结 (系列文章集合)
    转: WebRTC音视频引擎研究(1)--整体架构分析
    转:WebRTC技术及应用2 – NAT穿越技术的使用
    转: How to Install MongoDB 3.2 on CentOS/RHEL & Fedora (简单易懂)
  • 原文地址:https://www.cnblogs.com/wuyongyin/p/11915587.html
Copyright © 2011-2022 走看看