群晖找到上传流量最大的服务

需求 发现群晖比较卡,查看当前状态,发现上传跑满了,需要找出到底是哪个服务的问题。 解决 找到端口 使用 ssh 登陆群晖系统 使用 docker run -it --rm --net host janten/iftop -P -i eth0 来安装 iftop 镜像,并通过 iftop 来获取当前端口使用流量的情况。找到流量最大的端口。 使用 netstat -pantu | grep [port] 来获取这个端口对应的软件名称 参考 监控群晖异常上传流量,查看是哪个应用在上传 群晖上查找占用带宽最大的进程的一种解决方案 群晖NAS网络流量异常 在群晖上查找占用带宽的进程 如何利用资源监视器查看群晖NAS的状态?

<span title='2024-05-05 00:08:00 +0800 CST'>2024-05-05</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;36 words&nbsp;·&nbsp;RamLife

linux 和 windows 的 Gui 区别介绍

需求 了解 linux 和 windows 的 gui 大概的区别 解决 90年代 windows: gdi32.dll linux: x 普通情况都是使用 cpu 渲染 -> 显存 -> 显卡适配器 -> vga. 游戏都是 DirectX / OpenGL -> GPU -> 显存… vista 年代 windows: GDI+ -> Direct2D -> GPU Linux: AIGLX(X) -> OpenGL -> GPU 都是可以直接用 GPU,走的以前游戏这条路。 现在 windows: 小改动 win32k.sys, DirectX Linux: Wayland 替代 X, Vulkan 可能替代 OpenGL 参考 Linux 为何不把图形用户界面写入内核? - 12345的回答 - 知乎

<span title='2024-05-03 16:32:00 +0800 CST'>2024-05-03</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;66 words&nbsp;·&nbsp;RamLife

P13 select 模型上

电脑承受进程数量 1核2GB 可以大约 100 多进程或线程 普通服务器大概是 10倍性能,即 1000 多进程或线程。 IO 多路复用能力 1个进程或线程可以使用多个 TCP。 单进程 select 可以 1024 单进程 poll 可以数千 单进程 epoll 可以百万 fdset 本质上是 int[32] 组成的 bitmap, 刚好对应 1024 个文件描述符。 参考 IO 多路复用 select 模型上

<span title='2023-09-24 18:05:00 +0800 CST'>2023-09-24</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;36 words&nbsp;·&nbsp;RamLife

P6 万恶的结构体

客户端和服务端字符串转字节为啥不一样? 客户端 struct hostent* h; // 用于存放服务端IP地址(大端序)的结构体的指针。 if ( (h = gethostbyname(argv[1])) == nullptr ) // 把域名/主机名/字符串格式的IP转换成结构体。 { cout << "gethostbyname failed.\n" << endl; close(sockfd); return -1; } memcpy(&servaddr.sin_addr,h->h_addr,h->h_length); // ③指定服务端的IP(大端序)。 服务端 servaddr.sin_addr.s_addr=inet_addr(argv[1]); // ③指定服务端的IP,只能用IP,不能用域名和主机名。 原因 inet_addr 这个只能转换 ip 地址 gethostbyname 可以支持 IP,域名等等。 对于服务端来说,给他 ip 地址就够了。但是对于客户端来说,他需要连接的更多的可能是域名,而不是 IP。 服务端为什么也要设置 IP 如果服务端是运行于多网卡的服务器上面,那么必须要明确当前这个服务端是服务于那一个网段的,通过设置 servaddr.sin_addr.s_addr 就可以确定服务的网段了。 参考 万恶的结构体

<span title='2023-09-24 18:05:00 +0800 CST'>2023-09-24</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;54 words&nbsp;·&nbsp;RamLife

P12 TCP 缓存

getsockopt 作用 可以获取 socket 缓冲区大小。 int bufsize = 0; socklen_t optlen = sizeof(bufsize); getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &bufsize, &optlen); // 获取发送缓冲区的大小。 cout << "send bufsize=" << bufsize << endl; getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &bufsize, &optlen); // 获取接收缓冲区的大小。 cout << "recv bufsize=" << bufsize << endl; send 会阻塞吗? 如果发送太快,接受太慢,send 也会被阻塞。 send 之后,立即关闭,能接收到吗? 可以的,因为 send 是把数据写入到内核中的发送缓冲区,就算立即关闭,也能接收到。 nagle 算法 在发送一个小于 MSS 长度的包之后,必须收到回复,才能发下一个小包。保证了网络中小包数量得到控制。一般 ACK 大概 40ms. 接收延迟:在接受到一个包之后,会等待 40ms,才会发送 ACK, 这样可以尽量和应用层的回复数据合一个包。 在联机游戏,证券交易等应用场景,时效性要求高,一般会禁用 Nagle 算法。开启 TCP_NODELAY 选项。 #include <netinet/tcp....

<span title='2023-09-23 18:05:00 +0800 CST'>2023-09-23</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;82 words&nbsp;·&nbsp;RamLife

P11 三握四挥

netstat 使用 netstat 可以用来查看 socket 状态。 安装 如果系统里面没有,那么 yum install net-tools -y 可以安装。 使用 使用 netstat -a | less 或者 netstat -a | more 来查看。 上半部分的信息是 TCP 相关,下半部分是进程间的 socket 通信。 可以观察右边的 listen, established 等状态。 客户端的 port 是客户端系统随机选择的,不要去太过于关注。 port 使用限制 普通权限只能使用 1024 以上端口 root 可以使用 1024 以下的端口。 close 状态是假想状态,不存在的。 listen 的第二个参数作用 第二个参数 + 1 是 established 队列的大小,超过队列的客户端连接状态为 SYN_RCV. 三次握手 客户端申请向服务端的通道 服务端接受了,并且向客户端申请通道 客户端接受了,并给出回应 这样经过三次握手,双方建立了双向通道 四次挥手 A 请求关闭 B 同意关闭单向通道 B 把剩余的数据全部发送。 B 向 A 发送关闭请求 A 发送回应 主动端开的 A 在最后的回应后有个 TIME_WAIT 状态,时间为 2MSL,一个 MSL 在 30秒到1分钟。 服务端主动关闭 会导致 socket 释放,并且 2MSL 后端口才能重用。否则会有 bind 错误提示,并且在 netstat 中可以看到处于 TIME_WAIT 状态。 可以使用 setsockopt 函数,在 bind 之前,可以防止 bind 错误。 客户端主动关闭 没有危害,因为客户端的端口是随机分配端口号的,并且一般用的不多,够用了。...

<span title='2023-09-22 18:05:00 +0800 CST'>2023-09-22</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;107 words&nbsp;·&nbsp;RamLife

P10 多进程服务端

signal(i, SIG_IGN) 作用 // 忽略全部的信号,不希望被打扰。顺便解决了僵尸进程的问题。 for (int ii=1;ii<=64;ii++) signal(ii,SIG_IGN); kill(0, SIGTERM) 作用 kill(0,SIGTERM); // 向全部的子进程发送15的信号,通知它们退出。 因为在子进程中 SIGTERM 是退出信号。 父进程关掉 clientsocket, 子进程关掉 listensocket int pid=fork(); if (pid==-1) { perror("fork()"); return -1; } // 系统资源不足。 if (pid> 0) { // 父进程。 tcpserver.closeclient(); // 父进程关闭客户端连接的socket。 continue; // 父进程返回到循环开始的位置,继续受理客户端的连接。 } tcpserver.closelisten(); // 子进程关闭监听的socket。 在 /proc/xxx 下面的是进程相关资源,里面的 fd 是根据当前最小可用来递增的。 如果父进程不关 clientsocket, 那么每次 accept 之后,fd 都需要增加一个,然后在后面的 fork 中,这些递增的 fd 也都会被复制到子进程中。对于子进程来说,它不需要其他子进程相关的 =clientsocket=,所以完全是浪费资源。 子进程只需要自己对应的 clientsocket, 不需要 listensocket. listensocket 是专门给父进程用来监听的。 子进程结束需要 return return 0; // 子进程一定要退出,否则又会回到accept()函数的位置。 如果子进程结束没有 return=,让进程退出,那么会在 =while 中重新回到 accept 这个地方,进行了监听,然后 fork 了。...

<span title='2023-09-21 18:05:00 +0800 CST'>2023-09-21</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;88 words&nbsp;·&nbsp;RamLife

P9 文件传输

为什么 TCP 是可靠的通信,服务端每一步都要有回复。 因为服务端可能没有 accept 或者可能忙于其他事情,bug 掉线等等。所以虽然 TCP 本身是可靠的,但是服务器可能是不可靠的。所以为了业务是正常的,就必须在服务端正常应答的情况下,才能继续。 读取文件使用 ifstream 操作 字符串拼接报错? 一般情况都是只有 char * 和 char * 拼接,才会报错。只要语句中有一个 string, 拼接就不会报错。 参考 实现文件传输功能

<span title='2023-09-20 18:05:00 +0800 CST'>2023-09-20</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;24 words&nbsp;·&nbsp;RamLife

P7 封装 socket 客户端

封装时 send 函数为啥使用 const string & buf 作为参数类型 bool send(const string &buffer) // buffer不要用const char * const string & buf 既可以接收 string 也可以接受 char *. 估计是对 char * 进行了隐式转换成了 string. send 函数的参数为啥是 buf.data() 和 buf.size(), 而不是 buf.c_str() 和 buf.length if ((::send(m_clientfd,buffer.data(),buffer.size(),0))<=0) return false; buf.data() 和 buf.c_str() 都指向的是内容的指针,但是语义不一样。 data 表示的就是原始数据,而 c_str 表示的是转化为 char *. buf.size() 的语义是原始内容的大小,而 length 表示的是字符串的长度。 所以都是因为语义不合适。虽然都能用,但是确实不合适。 recv 函数的参数为啥是 & buf[0] 而不是 buf.c_str() 或者 buf.data() int readn=::recv(m_clientfd,&buffer[0],buffer.size(),0); // 直接操作buffer的内存。 因为后面两种返回的都是带有 const, 只有 &buf[0] 才没有 const, 适合对内容进行修改。...

<span title='2023-09-19 18:05:00 +0800 CST'>2023-09-19</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;125 words&nbsp;·&nbsp;RamLife

删除消息队列

需求 编程调试的时候,如果用到了消息队列,难免会消息队列中有残余信息的情况,并且如果希望在服务程序结束前就清除这些消息队列,那就需要在 shell 中使用命令进行删除。 解决 消息队列属于 IPC 的一部分,使用的命令也是 IPC 的系列命令中的 ipcrm. 查看消息队列情况 ipcs -q 删除指定 key 的消息队列,一般我们经常用这个,因为 key 一般是我们自己设定的。 ipcrm -Q 1234 删除指定 id 的消息队列 ipcrm -q 1234 如果程序是使用 sudo 来启动的,那么删除的时候,也需要 sudo, 否则没有权限. 参考 ipcs, ipcrm 命令 linux下消息队列的查看与删除(ipcs&ipcrm的使用) 请问Linux下如何清除消息队列queue中的内容??

<span title='2023-04-04 11:55:00 +0800 CST'>2023-04-04</span>&nbsp;·&nbsp;1 min&nbsp;·&nbsp;39 words&nbsp;·&nbsp;RamLife