【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

【linux】linux 内核参数的实际作用的疑惑?

"将它们设置成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

【linux】linux 内核参数的实际作用的疑惑?

"这四个内核项,没有影响到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

回到顶部