草庐IT

java - 谁能解释 Windows (7 Pro N) 和 Linux ( Ubuntu 12-04) 之间的套接字吞吐量差异

coder 2024-06-15 原文

在评估 3rd 方软件(使用 NIO 的 Java 框架)时,我们发现该框架在 Windows 上的吞吐量约为 Linux 上的 50%。

假设有一些影响 Windows 的 JVM 或操作系统设置,我们将开始测试跨两个平台的简单计算(Fibonacci、heapsort、strcat 等)和对象构建。在所有情况下,操作系统都差不多。然而,当我们使用简单的 ServerSocket 和 Client Socket (java.net jdk 1.7u5) 执行吞吐量测试时,我们注意到 Linux 吞吐量可以高达 Windows 的 10 倍,尤其是对于小消息(100 字节)。

我们的直接假设是操作系统套接字发送/接收缓冲区大小不同,并且它们在吞吐量中发挥着重要作用。或者这与在一个操作系统上启用 TcpNoDelay 而不是另一个有关。

操作系统套接字选项默认值为 ...

Linux: rcvBuf: 43690, sndBuf:86700, TcpNoDelay: No (Nagle On)
Windows7: rcvBuf: 8192, sndBuf:8192, TcpNoDelay: No (Nagle On)

结果如下...



这些结果引发了许多问题,尽管以下是最具挑战性的(我根本无法解释)和最直接的问题,因为当前的目标平台是 Windows。
  • 为什么不管缓冲区大小如何,100 字节消息的 Windows 时间(使用 Nagle On)几乎比 Linux 慢 10 倍
  • 为什么 100 字节消息的所有 Windows 时间(无论 Nagle 设置或缓冲区大小如何)大约为 7000 毫秒
  • 为什么所有的 Windows 时间都是 100 字节的消息(无论 Nagle 设置或缓冲区大小如何)都比它们的 1000 字节等值慢。我怀疑这与有效使用缓冲和/或 Nagling On/Off 有关,尽管我并不完全理解。

  • 我们在 Windows 上执行了额外的测试,我们从 50 字节开始消息大小,并在每 100 万条消息后增加 100 字节。结果很奇怪(但可以预测);在 50 到 400-450 字节之间,时间是 ~7000 毫秒,从 450-1000 字节,它们的范围是 ~5500 毫秒 - 7000 毫秒。一遍又一遍地重复这个测试显示了相同的模式。这就像需要将小消息填充到特定大小(可能是 MTU 或其他约束)。我们再次无法解释这种行为。

    任何解释或方向将不胜感激。请不要将其简化为 Windows v Linux 主题,改天再说吧。

    服务器代码
    public class SimpleMultiClientServer implements Runnable {
    
        private static ExecutorService threadPool = null;
        public static void main(String[] args) throws IOException {
    
            //ExecutorService threadPool;
            AppConfiguration configurations = null;
            if ((configurations = AppConfiguration.readAppConfiguration(args)) == null )
                System.exit(1);
    
            //create thread pool and execute
            threadPool = Executors.newCachedThreadPool();
            threadPool.execute( new SimpleMultiClientServer(configurations) );
    
            System.out.println("Hit any key to exit ....");
            System.in.read();
    
            //stop listening
            threadPool.shutdown();
        }
    
        //------------------------------------------------------------------------------
    
        private ServerSocket theServerSocket;
        private boolean listening = true;
        private AppConfiguration theConfigurations;
    
        private SimpleMultiClientServer(AppConfiguration configurations) {
    
            this.theConfigurations = configurations;
        }
    
        @Override
        public void run() {
    
            try {
                theServerSocket = new ServerSocket(theConfigurations.port);
                System.out.println(String.format("ServerSocket listening on port [%d]", theConfigurations.port));
    
                if ( theConfigurations.printSocketDetails )
                    printSocketDetials();
                setServerSocketConditioning();
    
            } catch (IOException e) {
                System.err.println(String.format("Could not listen on port: %d.", theConfigurations.port));
                System.exit(-1);
            }
    
            //TODO interrupt the listending thread in order to shutdown
            while (listening) {
                try {
                    threadPool.execute( new SimpleMultiClientServerThread( theServerSocket.accept() ) );
                    System.out.println("Accept new client on socket ....");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
    
            try {
                theServerSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private static class SimpleMultiClientServerThread implements Runnable {
    
            private Socket theSocket = null;
            @SuppressWarnings("unused")
            private long messageCount = 0;
    
            public SimpleMultiClientServerThread(Socket socket) {
    
                this.theSocket = socket;
            }
    
            public void run() {
    
                PrintWriter out = null;
                BufferedReader in = null;
    
                try {
                    out = new PrintWriter(theSocket.getOutputStream(), true);
                    in = new BufferedReader(new InputStreamReader( theSocket.getInputStream() ));
    
                    @SuppressWarnings("unused")
                    String inputLine;
    
                    while ((inputLine = in.readLine()) != null) {
    
                        messageCount++;
    
                        //TODO client should send shutdown message or end of stream marker on closing 
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
    
                    try {
    
                        if ( null != out )
                            out.close();
                        if ( null != in )
                            in.close();
                        if ( null != theSocket )
                            theSocket.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }   
    
        private void printSocketDetials() {
    
            //write to file
            FileOutputStream fos = null;
            PrintWriter pw = null;
            try {
    
                fos = new FileOutputStream("socketserver-details.log", true);
                pw = new PrintWriter(fos);
                pw.println("Socket (Server) details ....");
    
                try {
    
                    if ( null != this.theServerSocket ) {
                        pw.println(String.format("isBound [%b]", this.theServerSocket.isBound()));
                        //SO_RCVBUF
                        pw.println(String.format("getReceiveBufferSize [%d]", this.theServerSocket.getReceiveBufferSize()));
                        //SO_REUSEADDR
                        pw.println(String.format("getReuseAddress [%b]", this.theServerSocket.getReuseAddress()));
                        //SO_TIMEOUT
                        pw.println(String.format("getSoTimeout [%d]", this.theServerSocket.getSoTimeout()));
                        pw.println("----------------------------------------------------------");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                System.out.println();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
    
                if ( null != pw ) {
                    pw.flush();
                    pw.close();
    
                    if ( null != fos )
                        pw.close();
                }
            }       
        }
    
        private void setServerSocketConditioning() {
    
            try {
    
                if ( theConfigurations.rcvBufSpecified )
                    theServerSocket.setReceiveBufferSize(theConfigurations.rcvBuf);
    
                if ( ( theConfigurations.rcvBufSpecified ) &&
                       theConfigurations.printSocketDetails ) {
                    printSocketDetials();
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        private static class AppConfiguration {
    
            public int port;
    
            //socket conditioning
            public boolean printSocketDetails;
    
            public int rcvBuf;
            public boolean rcvBufSpecified;
    
            public static AppConfiguration readAppConfiguration(String[] args) {
    
                AppConfiguration configurations = new AppConfiguration();
    
                try {
    
                    configurations.port = Integer.parseInt(args[0]);
    
                    if ( args.length > 1 ) {
    
                        String[] socketConditioningDetails = args[1].split("\\|");
    
                        configurations.printSocketDetails = Integer.parseInt(socketConditioningDetails[0]) == 1 ? true : false;
    
                        if ( socketConditioningDetails.length > 1 ) {
                            configurations.rcvBuf = Integer.parseInt(socketConditioningDetails[1]);
                            configurations.rcvBufSpecified = true;
                        }
                    }
                } catch (Exception e) {
                    System.out.println(String.format("Exception caught while parsin app configurations, %s", e.getMessage()));
                    return null;
                }
    
                return configurations;
            }
    
        }
    }
    

    客户代码...
    public class SimpleSocketClient implements Runnable {
    
        public static void main(String[] args) throws IOException {
    
            AppConfiguration configurations = null;
            if ((configurations = AppConfiguration.readAppConfiguration(args)) == null )
                System.exit(1);
    
            if ( configurations.iterateThruByteRange ) {
    
                //set starting message size
                configurations.msgSize = configurations.startingMsgSize;
                for (int i = 0; i < configurations.numIterations; i++) {
    
                    SimpleSocketClient client = new SimpleSocketClient(configurations);
                    client.run();
    
                    if ( configurations.msgSizeIncrementSpecified )
                        configurations.msgSize += configurations.msgSizeIncrement;
                    else //double message size for next iteration
                        configurations.msgSize *= 2;
    
                    if ( configurations.reduceMsgSize )
                        configurations.msgCount = Math.max(1000, configurations.msgCount / 2);
    
                    try {
                        Thread.sleep(2500);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            } else {
                SimpleSocketClient client = new SimpleSocketClient(configurations);
                client.run();
            }
        }
    
        //------------------------------------------------------------------------------
    
        private AppConfiguration theConfigurations;
        private Socket theSocket;
        private boolean isRunning = true;
        private OutputStream obStream = null;
        private PrintWriter obWriter = null;
        private long[] sendTimeRecorder = null;
    
        private SimpleSocketClient(AppConfiguration configurations) {
    
            this.theConfigurations = configurations;
    
            //prepare send time recorder
            //sendTimeRecorder = new long[theConfigurations.msgCount];
            //Arrays.fill(sendTimeRecorder, 0);
        }
    
        @Override
        public void run() {
    
            try {
                if ( !connectToServer() )
                    return;
    
                if ( theConfigurations.printSocketDetails )
                    printSocketDetials();
    
                setSocketConditioning();
    
                System.out.println(String.format("[%s] About to send msg len [%d] [%d] times ",
                        new Date().toString(), 
                        theConfigurations.msgSize,
                        theConfigurations.msgCount));
    
                if ( !theConfigurations.iterateThruByteRange ||
                     ( theConfigurations.iterateThruByteRange && !theConfigurations.alreadyWaited) ) {
    
                    waitToContinue();
                    theConfigurations.alreadyWaited = true;
                }
    
                long startTimeInMillis = System.currentTimeMillis();
    
                sendMessages();
    
                System.out.println(String.format("All messages sent [%d] in timeMS [%d]",
                        theConfigurations.msgCount,
                        System.currentTimeMillis() - startTimeInMillis
                        ));
    
                //printSendTimes();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
    
                    if ( null != obWriter )
                        obWriter.close();
    
                    if ( null != theSocket )
                        theSocket.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }    
    
        private void sendMessages() {
    
            //prepare fixed length message
            byte[] fixedLengthMessage = new byte[theConfigurations.msgSize+1];
            Arrays.fill(fixedLengthMessage, (byte)0x41);
            fixedLengthMessage[fixedLengthMessage.length-1] = (byte)0x0D; //carriage return 
    
            //long startTimeInNanos = 0;
            int messageCount = 0;
    
            while ( isRunning && messageCount < theConfigurations.msgCount ) {
    
                try {
                    //startTimeInNanos = System.nanoTime();
                    obStream.write(fixedLengthMessage);
                    //sendTimeRecorder[messageCount] = System.nanoTime() - startTimeInNanos;
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
    
                messageCount++;
            }
        }
    
        private boolean waitToContinue() {
    
            boolean exit = false;
    
            System.out.println("Hit any key to continue ...");
            try {
                int keyValue = System.in.read();
    
                if ( keyValue == 'q' )
                    exit = true;
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
    
            return exit;
        }
    
        private boolean connectToServer() {
    
            boolean connected = false;
    
            try {
                theSocket = new Socket(theConfigurations.host, theConfigurations.port);
                obStream = theSocket.getOutputStream();
                obWriter = new PrintWriter(theSocket.getOutputStream(), true);
                connected = true;
    
            } catch (UnknownHostException e) {
                System.err.println(String.format("Don't know about host: %s.", theConfigurations.host));
                System.exit(1);
            } catch (IOException e) {
                System.err.println(String.format("Couldn't get I/O for the connection to: %s.", theConfigurations.host));
                System.exit(1);
            } 
    
            return connected;
        }
    
        private void printSocketDetials() {
    
            //write to file
            FileOutputStream fos = null;
            PrintWriter pw = null;
            try {
    
                fos = new FileOutputStream("socket-details.log", true);
                pw = new PrintWriter(fos);
                pw.println("Socket (Client) details ....");
    
                try {
    
                    if ( null != this.theSocket ) {
    
                        pw.println(String.format("IsConnected [%b]", this.theSocket.isConnected()));
                        //SO_KEEPALIVE
                        pw.println(String.format("getKeepAlive [%b]", this.theSocket.getKeepAlive()));
                        //OOBINLINE
                        pw.println(String.format("getOOBInline [%b]", this.theSocket.getOOBInline()));
                        //SO_RCVBUF
                        pw.println(String.format("getReceiveBufferSize [%d]", this.theSocket.getReceiveBufferSize()));
                        //SO_REUSEADDR
                        pw.println(String.format("getReuseAddress [%b]", this.theSocket.getReuseAddress()));
                        //SO_SNDBUF
                        pw.println(String.format("getSendBufferSize [%d]", this.theSocket.getSendBufferSize()));
                        //SO_LINGER
                        pw.println(String.format("getSoLinger [%d]", this.theSocket.getSoLinger()));
                        //SO_TIMEOUT
                        pw.println(String.format("getSoTimeout [%d]", this.theSocket.getSoTimeout()));
                        //TCP_NODELAY
                        pw.println(String.format("getTcpNoDelay [%b]", this.theSocket.getTcpNoDelay()));
                        pw.println("----------------------------------------------------------");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                System.out.println();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
    
                if ( null != pw ) {
                    pw.flush();
                    pw.close();
    
                    if ( null != fos )
                        pw.close();
                }
            }       
        }
    
        private void setSocketConditioning() {
    
            try {
    
                if ( theConfigurations.rcvBufSpecified )
                    theSocket.setReceiveBufferSize(theConfigurations.rcvBuf);
                if ( theConfigurations.sndBufSpecified )
                    theSocket.setSendBufferSize(theConfigurations.sndBuf);
                if ( theConfigurations.naglingEnabledSpecified )
                    theSocket.setTcpNoDelay(!theConfigurations.naglingEnabled);
    
                if ( ( theConfigurations.rcvBufSpecified || 
                       theConfigurations.sndBufSpecified ||
                       theConfigurations.naglingEnabledSpecified ) &&
                       theConfigurations.printSocketDetails ) {
    
                    printSocketDetials();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        private void printSendTimes() {
    
            //write to file
            FileOutputStream fos = null;
            PrintWriter pw = null;
            try {
    
                String fileName = String.format("sendTimes-%d-%d-%s.log", 
                        theConfigurations.msgSize, 
                        theConfigurations.msgCount,
                        theConfigurations.naglingEnabledSpecified &&  !theConfigurations.naglingEnabled ? "WithNoNagle" : "WithNagle");
    
                fos = new FileOutputStream(fileName, false);
                pw = new PrintWriter(fos);
    
                pw.println(Arrays.toString(this.sendTimeRecorder));
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
    
                if ( null != pw ) {
                    pw.flush();
                    pw.close();
    
                    if ( null != fos )
                        pw.close();
                }
            }       
    
        }
    
        private static class AppConfiguration {
    
            public String host;
            public int port;
            public int msgSize;
            public int msgCount;
            @SuppressWarnings("unused")
            public int msgRatePerSecond;
    
            //socket conditioning
            public boolean printSocketDetails;
    
            public int rcvBuf;
            public boolean rcvBufSpecified;
    
            public int sndBuf;
            public boolean sndBufSpecified;
    
            public boolean naglingEnabled;
            public boolean naglingEnabledSpecified;
    
            //testing byte ranges
            public boolean iterateThruByteRange;
            public int startingMsgSize;
            public int numIterations;
            public boolean reduceMsgSize;
            public int msgSizeIncrement;
            public boolean msgSizeIncrementSpecified;
            public boolean alreadyWaited = false;       
    
            public static AppConfiguration readAppConfiguration(String[] args) {
    
                AppConfiguration configurations = new AppConfiguration();
    
                try {
    
                    configurations.host = args[0];
                    configurations.port = Integer.parseInt(args[1]);
                    configurations.msgSize = Integer.parseInt(args[2]);
    
                    String[] msgCountDetails = args[3].split(":");
                    configurations.msgCount = Integer.parseInt(msgCountDetails[0]);
                    if ( msgCountDetails.length == 2 )
                        configurations.msgRatePerSecond = Integer.parseInt(msgCountDetails[1]);
    
                    if ( args.length > 4 ) {
    
                        String[] socketConditioningDetails = args[4].split("\\|");
                        configurations.printSocketDetails = Integer.parseInt(socketConditioningDetails[0]) == 1 ? true : false;
    
                        if ( socketConditioningDetails.length > 1 ) {
                            configurations.rcvBuf = Integer.parseInt(socketConditioningDetails[1]);
                            configurations.rcvBufSpecified = true;
                        }
                        if ( socketConditioningDetails.length > 2 ) {
                            configurations.sndBuf = Integer.parseInt(socketConditioningDetails[2]);
                            configurations.sndBufSpecified = true;
                        }
                        if ( socketConditioningDetails.length > 3 ) {
                            configurations.naglingEnabled = Integer.parseInt(socketConditioningDetails[3]) == 1 ? true : false;
                            configurations.naglingEnabledSpecified = true;
                        }
                    }
    
                    if ( args.length > 5 ) {
    
                        String[] byteRangeSettings = args[5].split("\\|");
                        configurations.iterateThruByteRange = Integer.parseInt(byteRangeSettings[0]) == 1 ? true : false;
    
                        if ( byteRangeSettings.length > 1 )
                            configurations.startingMsgSize = Integer.parseInt(byteRangeSettings[1]);
                        if ( byteRangeSettings.length > 2 )
                            configurations.numIterations = Integer.parseInt(byteRangeSettings[2]);
                        if ( byteRangeSettings.length > 3 )
                            configurations.reduceMsgSize = Integer.parseInt(byteRangeSettings[3]) == 1 ? true : false;
                        if ( byteRangeSettings.length > 4 ) {
    
                            configurations.msgSizeIncrement = Integer.parseInt(byteRangeSettings[4]);
                            configurations.msgSizeIncrementSpecified = true;
                        }
    
                    }
    
                } catch (Exception e) {
                    System.out.println(String.format("Exception caught while parsin app configurations, %s", e.getMessage()));
                    return null;
                }
    
                return configurations;
            }
    
    
        }
    
    }
    

    命令行

    服务器:
    java –cp . SimpleMultiClientServer 9090 [“printSocketConditioning|rbuffer size”]
    

    可选 printSocketConditioning : 1/0,打印到 'socketserver-details.log'rbuffer size : 以字节为单位的接收缓冲区

    例如java –cp . SimpleMultiClientServer 9090
    客户:

    基本:
    java –cp . SimpleSocketClient localhost 9090 msgSize numMessages
    
    msgSize : 消息大小(以字节为单位)numMessages : 要发送的消息数

    例如java –cp . SimpleSocketClient localhost 9090 100 1000000
    设置 socket 调节:
    java –cp . SimpleSocketClient localhost 9090 <msgSize> <numMessages> “printSocketConditioning|rbuffer|sbuffer|nagle on”]
    
    printSocketConditioning: 1/0rbuffer : 接收缓冲区大小(以字节为单位)
    sbuffer : 以字节为单位发送缓冲区大小
    nagle on: 1/0 (相当于 TcpNoDelay 关/开)

    例如java –cp . SimpleSocketClient localhost 9090 100 1000000 “1|8192|8192|1”
    通过字节范围迭代的套接字调节:
    java –cp . SimpleSocketClient localhost 9090 msgSize numMessages [“printSocketConditioning|rbuffer|sbuffer|nagle on” 
       [“iterateByteRange|startSize|numIterations|reduceMsgCount|incMsgSizeBy”]
    ]
    
    iterateByteRange: 1/0 ,从消息大小开始执行一系列测试 startSize并通过加倍(默认)或 incMsgSizeBy 递增, 重复 numIterationsstartSize : 以字节为单位的消息起始大小(例如 100)
    numIterations :例如1000000
    reduceMsgCount: 1/0 , 每次迭代减半或保持不变
    incMsgSizeBy :在每次迭代时按字节增加消息大小(例如 100)

    *例如。 java –cp . SimpleSocketClient localhost 9090 100 1000000 “1|8192|8192|1” "1|100|20|0|100"*
    请注意,上面发布的所有结果都是在相同的硬件上执行的,客户端和服务器都在同一台机器上。

    最佳答案

    Microsoft 在 Windows(客户端)操作系统中专门针对 TCP 连接实现了限制,以防止将其用作服务器 (reference)。在 Windows Server 2008 R2 上再次运行您的测试,看看是否有任何不同。

    关于java - 谁能解释 Windows (7 Pro N) 和 Linux ( Ubuntu 12-04) 之间的套接字吞吐量差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11565777/

    有关java - 谁能解释 Windows (7 Pro N) 和 Linux ( Ubuntu 12-04) 之间的套接字吞吐量差异的更多相关文章

    1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

      我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

    2. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

      我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

    3. ruby - 如何在 Ubuntu 中清除 Ruby Phusion Passenger 的缓存? - 2

      我试过重新启动apache,缓存的页面仍然出现,所以一定有一个文件夹在某个地方。我没有“公共(public)/缓存”,那么我还应该查看哪些其他地方?是否有一个URL标志也可以触发此效果? 最佳答案 您需要触摸一个文件才能清除phusion,例如:touch/webapps/mycook/tmp/restart.txt参见docs 关于ruby-如何在Ubuntu中清除RubyPhusionPassenger的缓存?,我们在StackOverflow上找到一个类似的问题:

    4. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

      这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

    5. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

      之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

    6. 网络编程套接字 - 2

      网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

    7. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

      深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

    8. 在VMware16虚拟机安装Ubuntu详细教程 - 2

      在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

    9. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

      需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

    10. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

      s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

    随机推荐