char tmp[1024];
AMS_WARN(" --clear socket buff...");
while(1) {
ret = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
if(ret == 0) {
break;
}
if (recv(client_fd, tmp, 1024, 0 ) != 1024) {
break;
}
}
建议将tmp
大小设置为65535,业务代码逻辑可能需要修改。
可以在程序中动态地修改(通过setsockopt系统调用)持有的有效Socket的读写缓冲区大小。
参考代码:
int ret, sock, sock_buf_size;
sock = socket( AF_INET, SOCK_STREAM, 0 );
sock_buf_size = BDP;
ret = setsockopt( sock, SOL_SOCKET, SO_SNDBUF,
(char *)&sock_buf_size, sizeof(sock_buf_size) );
ret = setsockopt( sock, SOL_SOCKET, SO_RCVBUF,
(char *)&sock_buf_size, sizeof(sock_buf_size) );
参考文章:Socket缓冲区大小修改与系统设置
端口复用reuseport原因:单线程listener,在处理高速率海量连接时,会成为瓶颈;
参考文章:Linux3.9中 SO_REUSEPORT 对高并发服务器的改进
配置修改参考: c/c++:端口复用(setsockopt)、io多路转接(select、 poll、epoll)
调用setsockopt函数:
#include
#include
// 设置套接字属性
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
参数:
- sockfd: 要操作的文件描述符
- level: 级别 -> SOL_SOCKET (端口复用的级别)
- optname: 端口复用的级别(二选一,随便选,对于端口复用都可以)
- SO_REUSEADDR
- SO_REUSEPORT
- optval: 端口复用-> 对应的是整形数
- 1: 可以复用
- 0: 不能复用
- optlen: optval参数对应的内存大小
// 设置端口复用, 设置的时机: 服务器绑定端口之前, 设置端口复用。例如:
setsockopt();
bind();
具体参数含义参考文章:Linux内核 TCP/IP、Socket参数调优
修改linux系统文件句柄限制
执行echo -e "* soft nofile 40960 \n* hard nofile 65536" >> /etc/security/limits.conf
修改linux系统文件句柄限制
cat /etc/security/limits.conf
将在limits.conf中添加以下参数
* soft nofile 40960
* hard nofile 65536
参数
* 代表所有用户有效
soft:软限制,超过会报warn
hard:实际限制
nofile:文件句柄参数
number:最大文件句柄数
使用ulimit -n
查看open files 参数是否改变。
TCP/IP内核参数优化,建议参数如下:
/etc/sysctl.conf添加以下代码,重启后永久生效
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_default = 8388608
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 2000
net.core.somaxconn = 2048
net.core.optmem_max = 81920
net.ipv4.tcp_mem = 131072 262144 524288
net.ipv4.tcp_rmem = 8760 8388608 16777216
net.ipv4.tcp_wmem = 8760 8388608 16777216
net.ipv4.tcp_keepalive_time = 60
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 20
vm.overcommit_memory=1
TCPNoDelay和TCPkeepalive都是常用的TCP选项,前者的作用是禁用Nagle 算法6,避免连续发包出现延迟,这对编写低延迟网络服务很重要。后者的作用是定期探查TCP连接是否还存在。一般来说如果有应用层心跳的话,TCPkeepalive不是必需的。
TCPNoDelay设置参考代码:
int sock, flag, ret;
/* Create new stream socket */
sock = socket( AF_INET, SOCK_STREAM, 0 );
/* Disable the Nagle (TCP No Delay) algorithm */
flag = 1;
ret = setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) );
if (ret == -1) {
printf("Couldn't setsockopt(TCP_NODELAY)\n");
exit(-1);
}
TCPkeepalive内核中设置参考上面第4点,应用程序中设置参考如下:
int keepAlive = 1; // 开启keepalive属性
int keepIdle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测
int keepInterval = 5; // 探测时发包的时间间隔为5 秒
int keepCount = 3; // 探测尝试的次数.如果第1次探测包就收到响应了,则后2次的不再发.
setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepIdle, sizeof(keepIdle));
setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepInterval, sizeof(keepInterval));
setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepCount, sizeof(keepCount));
见《Linux多线程服务编程》8.9节
6、使用std::vector作为数据缓冲区,具体请参考https://gitee.com/liudegui/finger_server/blob/master/common/Buffer.cpp