2020.8.27

一直不明白为什么网络socket编程默认都是阻塞的,阻塞了程序不就停了不响应了吗,好纠结。

现在有点了解了,阻塞时是等待状态,类似于内核把它sleep,不占用CPU,对操作系统正常运转是非常有利的。

非阻塞方式:程序不会停止响应,socket函数会马上返回,但程序需要一直轮询socket,如果socket没有动作,那其实就是在while(1)啊,CPU占用是100%啊。不行啊,操作系统要完蛋的。

所以还是用阻塞方式吧,内核已经把最优方案给我们了。

但是,一个socket这么用是没问题的,多个socket就麻烦了。

主要有二个方法:

1. 多线程:
一个socket放入一个线程,阻塞了后,线程处于停止状态,不影响主程序和其它socket。
线程程序是按正常socket通讯交互流程走,符合正常编程思路,编程容易些,但开销大,线程多了扛不住。
线程要占用内存,有人试过linux大约是可以开到300个线程,每个线程占10MB,好大。
所以一般十几、几十个socket可以用多线程玩一玩。

2. IO多路复用:select,poll,epoll等。
主程序一个线程就可以处理所有socket。
编程比较麻烦,得判断各个socket是在通讯交互流程的哪一步。
read/recv()取决于对方有没有发来数据,阻塞可能性很大,write/send()则是自己发送数据,一般不阻塞,所以一般只判断读取标志即可,发送则直接用write()或send(),这样程序比较简单。

参考网友说的:

qeesung
如果只有一个套接字的情况下,使用阻塞IO是极好的,读到数据就返回。
但是如果在有很多套接字的情况下,比如有100个套接字:
1.    如果使用阻塞IO,可能因为读取一个没有数据的套接字而阻塞剩下的99个套接字的数据处理,那么就会造成服务器的响应性很差。
2.    如果使用非阻塞IO,那么就需要轮询这一百个套接字到底可不可以读取到数据,这个轮询操作会浪费CPU时间片,照样也不是一个高效的方式,套接字多了,照样性能很差。
那有没有一种比较好的方式来同时检测多个套接字是否可读可写,并且不浪费CPU时间片呢?那就是要用IO多路复用了,使用IO多路复用可以同时检测多个不同的套接字是否就绪。有多种IO多路复用的实现,其中包括select,poll, epoll, /dev/poll, kqueue等。

————————————————
版权声明:本文为CSDN博主「wxlfreewind」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wxlfreewind/article/details/108274842

2020.8.27一直不明白为什么网络socket编程默认都是阻塞的,阻塞了程序不就停了不响应了吗,好纠结。现在有点了解了,阻塞时是等待状态,类似于内核把它sleep,不占用CPU,对操作系统正常运转是非常有利的。非阻塞方式:程序不会停止响应,socket函数会马上返回,但程序需要一直轮询socket,如果socket没有动作,那其实就是在while(1)啊,CPU占用是100%啊。不行啊,操作系统要完蛋的。所以还是用阻塞方式吧,内核已经把最优方案给我们了。但是,一个socket这么用是没问题的,多个soc import java. io .BufferedReader; import java. io . IO Except io n; import java. io .InputStreamReader; import java. io .PrintWriter; 第一个概念:用户空间与内核空间 1. 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方) 2. 操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。 3. 为了保证用户进程不能直接操作内核(kernel),保证内核的安全,操心系统将虚拟空间划分为两部分:一部分为内核空间,一部分为用户空间 4. 针对 linux 操作系统而言,将最高的1G字节(从虚拟地 多线程 是程序设计中的一个重要方面,尤其是在 服务器 Deamon程序方面。无论何种系统,线程调度的开销都比传统的进程要快得多。   Python可以方便地支持 多线程 。可以快速创建线程、互斥锁、信号量等等元素,支持线程读写同步互斥。美中不足的是,Python的运行在Python 虚拟机上,创建的 多线程 可能是虚拟的线程,需要由Python虚拟机来 轮询 调度,这大大降低了Python 多线程 的可用性。希望高版本的Python可以 解决这个问题,发挥多 CPU 的最大效率。   网上有些朋友说要获得真正多 CPU 的好处,有两种方法:   1.可以创建多个进程而不是线程,进程数和 cpu 一样多。 这种 IO 方式为事件驱动 IO (event driven IO )。 我们都知道,select/epoll的好处就在于单个进程process就可以同时处理多个 网络 连接的 IO 。它的基本原理就是select/epoll这个funct io n会不断的 轮询 所负责的所有 socket ,当某个 socket 有数据到达了,就通知用户进程。它的流程如图: select是多路 复用 的一种 当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的 socket , 当任何一个 socket 中的数据准备好了,select就会返回
1.接手的项目apk中基于JT808协议用 Socket 上传位置等消息,用命令top -m 10 -s cpu 查看 cpu 消耗时发现此app 占用 cpu 超过10% 先把GPS停了,重新运行还是会很耗 cpu 用Android Profiler查了下点record 最终定位到 线程里 Socket Channel里的read方法 while (true) {
1、 socket 默认是 阻塞 的, 阻塞 时: send函数如果可用空间大小小于要发送的数据长度,则send会被 阻塞 ,直到缓冲区中的数据被发送到目标主机,有了足够的空间之后,send函数才会将数据写入输出缓冲区。 要写入的数据大于输出缓冲区的最大长度的时候,要分多次写入,直到所有数据都被写到缓冲区之后,send函数才会返回。 recv函数,函数先检查输入缓冲区,如果输入缓冲区中有数据,读取出缓冲区中的数据,否则的话,recv函数会被 阻塞 ,等待 网络 上传来数据。如果每次读取的数据长度小于buffer的数据长度.
在用自定义线程池的时候,遇到 cpu 100%,经过验证后,发现问题来源于我定义的子线程。 子线程的主要功能是从任务队列(LinkedBlockingQueue)里面持续拿出任务,并且执行。 以下为令 CPU 100的代码。 private class WorkThread extends Thread @Override public void ru...
1. 非阻塞 IO 模型: - 在 非阻塞 IO 模型中,当应用程序发起一个 IO 操作后,不会 阻塞 等待数据准备好或传输完成,而是立即返回控制权给应用程序,继续执行其他任务。 - 应用程序需要通过 轮询 的方式主动查询 IO 操作的状态,以确定数据是否准备好或传输完成。 - 非阻塞 IO 适用于处理大量的短连接、低并发的情况,但会带来频繁的 轮询 开销,降低了 CPU 利用率。 2. 多路 复用 IO 模型: - 在多路 复用 IO 模型中,应用程序通过将多个 IO 操作注册到一个统一的事件管理器(如select、poll、epoll等),然后将控制权交给操作系统。 - 操作系统负责监听所有注册的 IO 事件,并在有事件发生时通知应用程序进行处理。 - 多路 复用 IO 模型使用事件通知机制,应用程序只需要等待事件通知,并处理已触发的事件,显著降低了 轮询 开销和系统资源 占用 。 - 多路 复用 IO 适用于处理高并发、大量长连接的情况,提高了系统的可扩展性和性能。 非阻塞 IO 模型需要应用程序主动 轮询 IO 状态,适用于低并发的情况;而多路 复用 IO 模型利用操作系统的事件通知机制,避免了频繁的 轮询 开销,适用于高并发的情况。选择哪种 IO 模型取决于应用程序的需求和场景。