【linux】linux 内核参数的实际作用的疑惑?
"tcp 内核接收和发送缓冲区"sysctl -x net.ipv4.tcp_mem -> net.ipv4.tcp_rmem = 4096 87380 6291456
sysctl -x net.ipv4.tcp_rmem -> net.ipv4.tcp_wmem = 4096 16384 4194304
--------------------------------------------------------------
"本地测试"
--------------------------------------------------------------
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void print_buffer(const int &fd) {
int buffer_size = 0;
socklen_t opt_len = sizeof(buffer_size);
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size, &opt_len) == 0) {
std::cout << "send buffer = " << buffer_size << std::endl;
}
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size, &opt_len) == 0) {
std::cout << "recv buffer = " << buffer_size << std::endl;
}
}
int main(int argc, char* argv[]) {
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
print_buffer(fd);
return 0;
}
"运行结果 与 内核参数一致"
-------------------------------------------------------------
send buffer = 16384
recv buffer = 87380
--------------------------------------------------------------
"远程测试"
--------------------------------------------------------------
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
void print_buffer(const int &fd) {
int buffer_size = 0;
socklen_t opt_len = sizeof(buffer_size);
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size, &opt_len) == 0) {
std::cout << "send buffer = " << buffer_size << std::endl;
}
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size, &opt_len) == 0) {
std::cout << "recv buffer = " << buffer_size << std::endl;
}
}
int main(int argc, char* argv[]) {
int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in socket_address = {};
socket_address.sin_family = AF_INET;
socket_address.sin_port = htons(9501);
socket_address.sin_addr.s_addr = inet_addr("0.0.0.0");
if(-1 == ::bind(fd, (sockaddr*)&socket_address, sizeof(sockaddr))) {::close(fd);return -1;}
if(-1 == ::listen(fd, 123)) { ::close(fd);return -1;}
sockaddr_in connection_info = {};
socklen_t sock_addr_len = sizeof(sockaddr_in);
int client_fd = ::accept(fd, (sockaddr*)&connection_info, &sock_addr_len);
print_buffer(client_fd);
::close(fd);
::close(client_fd);
return 0;
}
"运行结果 与 内核参数不一致 局域网内"
-------------------------------------------------------------
send buffer = 2626560
recv buffer = 1062000
--------------------------------------------------------------
tcp缓冲区的疑惑
-----------------------------------------------------------------------------------------
1."为什么本地与远程的得出的内核发送缓冲是不同的?"
2."远程的这个内核的发送缓冲区的值是如何计算得出的?"
3."按我的理解本地内核的socket缓冲区的参数,只会影响本地的socket,对于远程的socket是无效的?"
-----------------------------------------------------------------------------------------
udp
"在网上查了很多资料,都说这4个参数影响tcp滑动窗口的大小"sysctl -x net.core.wmem_default
sysctl -x net.core.rmem_default
sysctl -x net.core.wmem_max
sysctl -x net.core.rmem_max
"将它们设置成10W时,我的滑动窗口为28960"sysctl -x net.core.wmem_default -> net.core.wmem_default = 100000
sysctl -x net.core.rmem_default -> net.core.rmem_default = 100000
sysctl -x net.core.wmem_max -> net.core.wmem_max = 100000
sysctl -x net.core.rmem_max -> net.core.rmem_max = 100000
"将它们设置成8192时,我的滑动窗口还是28960"sysctl -x net.core.wmem_default -> net.core.wmem_default = 8192
sysctl -x net.core.rmem_default -> net.core.rmem_default = 8192
sysctl -x net.core.wmem_max -> net.core.wmem_max = 8192
sysctl -x net.core.rmem_max -> net.core.rmem_max = 8192
"这四个内核项,没有影响到tcp,反倒是影响了udp的发送缓冲区与接收缓冲区。"
"本地测试"--------------------------------------------------------------
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void print_buffer(const int &fd) {
int buffer_size = 0;
socklen_t opt_len = sizeof(buffer_size);
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size, &opt_len) == 0) {
std::cout << "send buffer = " << buffer_size << std::endl;
}
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size, &opt_len) == 0) {
std::cout << "recv buffer = " << buffer_size << std::endl;
}
}
int main(int argc, char* argv[]) {
int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
print_buffer(fd);
return 0;
}
"运行结果 与 内核参数一致"
-------------------------------------------------------------
send buffer = 8192
recv buffer = 8192
这4个内核参数的疑惑-----------------------------------------------------------------------------------------
1."为什么在网上查看的资料都很统一的指向tcp滑动窗口大小?可是我测试的结果却不对呢?"
2."tcp滑动窗口的大小,我方的窗口大小,到底是根据什么参数,来告之对方的呢?"
回答
问题里若干不明,只能边猜边答。
见 linux.die.net/man/7/tcp" rel="nofollow noreferrer">tccp :tcp_rmem 跟 tcp_wmem 后面的三个数字是 最小值、默认值、最大值。实际使用的值是动态变化的。你所有看到的结果都在最小值与最大值之间,所以都没有什么问题。
所谓“远程”,你是不是想说一个已经建立连接的 socket?建立连接的时候也是有若干 TCP 包的交换了,buffer 大小在此过程中发生变化也不奇怪。具体逻辑,也许要看代码,或者找其它资料了。
net.core.wmem_default, net.core.rmem_default, net.core.wmem_max, net.core.rmem_max 设置的都是缓冲区的大小。他们适用于所有协议。所以你可以看到 UDP 的缓冲区大小的变化。
而且,由于还有 tcp_wmem 在,在 TCP 里,究竟哪个最大值生效貌似可能于 man page 里写得都不太一样。参见https://stackoverflow.com/q/3...。根据这个问题的答案,tcp_rmem 里的最大值于 rmem_max 里更大的那个生效。于是,rmem_max 对 TCP 基本没有什么作用。rmem_default 自然也会被 tcp_rmem 覆盖掉。(注意 tcp_rmem 同时指定的最小值、默认值、最大值)
TCP 传输过程中,窗口的大小也是可以浮动的。TCP 头里传输的 window size,指这个 package 的发送方,当前还可以接收多少数据(receive window)。这个值当然会随着接受缓存的总大小,以及接受缓存中已经存储的数据量的变化,而不断地发生变化,不会是一个恒定地值。在接收缓冲为空的时候,它通常就是接收缓冲的大小。可能因此才有这些参数可以“控制”窗口大小的说法,因为它们在一定程度上,控制了接收缓冲区的大小。实际情况,可能还要改 tcp_rmem 跟 tcp_wmem 才成。
都是先查的,有错欢迎指出。
以上是 【linux】linux 内核参数的实际作用的疑惑? 的全部内容, 来源链接: utcz.com/a/82832.html