欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

然后没理 昆山软件开发 客户端

点击: 次  来源:劳务派遣管理系统 时间:2017-12-20

原文出处: 王爵

处事端的系统配置中常常会和底层协议打交道,我们有须要重温一下曾经那些“听过”却不熟悉的名词。 本日聊的话题是 KeepAlive,在实际应用中又是怎么利用的?

为什么有Keepalive?

各人都做过电梯吧,假设电梯来了你先进去,劳务派遣管理系统,你伴侣还没进来,过一段时间电梯门就会自动封锁, 你应该没碰着过哪个电梯会一直等你伴侣来了才关门的。假如然是那样,那此外楼层的小姐姐们会炸了~

我们举个编程中的例子来表明下,我编写了一个处事端措施S和一个客户端措施C,客户端向处事端发送 一个动静:

然后没理 昆山软件开拓 客户端

处事端收到动静后一看,劳务派遣管理系统,瞧给你牛*的,然后没理客户端,傻狗客户端一直在期待,可是不知道是不是处事器挂掉了? 这时候TCP协议提出一个步伐,当客户端端期待高出一按时间后自动给处事端发送一个空的报文, 假如对方回覆了这个报文证明毗连还存在世,假如对方没有报文返回且举办了多次实验都是一样,昆山软件开发, 那么就认为毗连已经丢失,客户端就没须要继承保持毗连了。 假如没有这种机制就会有许多空闲的毗连占用着系统资源。

KeepAlive并不是TCP协议类型的一部门,但在险些所有的TCP/IP协议栈(不管是Linux照旧Windows)中,都实现了KeepAlive成果

RFC1122#TCP Keep-Alives

如何配置它?

在配置之前我们先来看看KeepAlive都支持哪些配置项

  1. KeepAlive默认环境下是封锁的,可以被上层应用开启和封锁
  2. tcp_keepalive_time: KeepAlive的空闲时长,可能说每次正常发送心跳的周期,默认值为7200s(2小时)
  3. tcp_keepalive_intvl: KeepAlive探测包的发送隔断,默认值为75s
  4. tcp_keepalive_probes: 在tcp_keepalive_time之后,没有吸收到对方确认,继承发送保活探测包次数,默认值为9(次)

我们讲讲在Linux操纵系统和利用Java、C语言和Nginx中如何配置

在Linux内核配置

KeepAlive默认不是开启的,假如想利用KeepAlive,需要在你的应用中配置SO_KEEPALIVE才可以生效。

查察当前的设置:

cat /proc/sys/net/ipv4/tcp_keepalive_time
cat /proc/sys/net/ipv4/tcp_keepalive_intvl
cat /proc/sys/net/ipv4/tcp_keepalive_probes

在Linux中我们可以通过修改 /etc/sysctl.conf 的全局设置:

net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_keepalive_intvl=75
net.ipv4.tcp_keepalive_probes=9

添加上面的设置后输入 sysctl -p 使其生效,你可以利用 sysctl -a | grep keepalive 呼吁来查察当前的默认设置

假如应用中已经配置SO_KEEPALIVE,措施不消重启,内核直接生效

利用Netty4配置

这里我们利用常用的Java网络框架Netty来配置,只需要在处事端配置即可:

EventLoopGroup bossGroup   = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
    ServerBootstrap b = new ServerBootstrap();
    b.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel.class)
            .option(ChannelOption.SO_BACKLOG, 100)
            .childOption(ChannelOption.SO_KEEPALIVE, true)
            .handler(new LoggingHandler(LogLevel.INFO));

    // Start the server.
    ChannelFuture f = b.bind(8088).sync();
    // Wait until the server socket is closed.
    f.channel().closeFuture().sync();
} finally {
    // Shut down all event loops to terminate all threads.
    bossGroup.shutdownGracefully();
    workerGroup.shutdownGracefully();
}

这段代码来自经典的echo处事器,我们在childOption中开启了SO_KEEPALIVE。 Java措施只能做到配置SO_KEEPALIVE选项,其他设置项只能依赖于sysctl设置,系统举办读取。

C语言配置

函数原型:

#include <sys/socket.h>

int setsockopt(int socket, int level, int option_name,
      const void *option_value, socklen_t option_len);

我们在需要使能Keepalive的socket上面挪用setsockopt函数便可以打开该socket上面的keepalive。

  1. 第一个参数是要配置的套接字
  2. 第二个参数是SOL_SOCKET
  3. 第三个参数必需是SO_KEEPALIVE
  4. 第四个参数必需是一个布尔整型值,0暗示封锁,1暗示打开
  5. 最后一个参数是第四个参数值的巨细。

挪用例子:

int socket(int domain, int type, int protocol)
{
  int (*libc_socket)(int, int, int);
  int s, optval;
  char *env;

  *(void **)(&libc_socket) = dlsym(RTLD_NEXT, "socket");
  if(dlerror()) {
    errno = EACCES;
    return -1;
  }

  if((s = (*libc_socket)(domain, type, protocol)) != -1) {
    if((domain == PF_INET) && (type == SOCK_STREAM)) {
      if(!(env = getenv("KEEPALIVE")) || strcasecmp(env, "off")) {
        optval = 1;
      } else {
        optval = 0;
      }
      if(!(env = getenv("KEEPALIVE")) || strcasecmp(env, "skip")) {
        setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
      }
#ifdef TCP_KEEPCNT
      if((env = getenv("KEEPCNT")) && ((optval = atoi(env)) >= 0)) {
        setsockopt(s, SOL_TCP, TCP_KEEPCNT, &optval, sizeof(optval));
      }
#endif
#ifdef TCP_KEEPIDLE
      if((env = getenv("KEEPIDLE")) && ((optval = atoi(env)) >= 0)) {
        setsockopt(s, SOL_TCP, TCP_KEEPIDLE, &optval, sizeof(optval));
      }
#endif
#ifdef TCP_KEEPINTVL
      if((env = getenv("KEEPINTVL")) && ((optval = atoi(env)) >= 0)) {
        setsockopt(s, SOL_TCP, TCP_KEEPINTVL, &optval, sizeof(optval));
      }
#endif
    }
  }

   return s;
}

代码摘取自libkeepalive源码,C语言可以配置更为具体的TCP内核参数

在Nginx中设置