当前位置: 首页 > news >正文

上海网站建设 销售网络推广好做吗多少钱

上海网站建设 销售,网络推广好做吗多少钱,宜昌网站推广优化技巧,网站建设需要哪些常用技术写在前面#xff1a; 版本信息#xff1a; Linux内核2.6.24#xff08;大部分centos、ubuntu应该都在3.1。但是2.6的版本比较稳定#xff0c;后续版本本质变化也不是很大#xff09; ipv4 协议 https://blog.csdn.net/ComplexMaze/article/details/124201088 本文使用案例…写在前面 版本信息 Linux内核2.6.24大部分centos、ubuntu应该都在3.1。但是2.6的版本比较稳定后续版本本质变化也不是很大 ipv4 协议 https://blog.csdn.net/ComplexMaze/article/details/124201088 本文使用案例如上地址感谢案例的分享本篇文章核心部分还是在Linux内核源码分析 为什么写下这篇文章因为在实际项目中是无法避免TCP通讯对于这点可能大部分Java程序员感受不到底层的网络通讯正因为无法避免TCP通讯恰好TCP通讯存在三次握手和四次挥手的过程如果建立一次连接就三次握手和四次挥手而我们清楚的知道三次握手和四次挥手是同步的过程此过程也会带来不少的时间浪费和资源的浪费。所以Linux内核TCP网络协议栈就出现了KeepAlive机制此机制减少三次握手和四次挥手次数第一次建立连接后保持长连接后续通讯就可以只考虑发送数据报文即可。往往出现一个机制解决某个问题其他问题又出现如果所有连接都建立长连接保活机制而连接数又有限制此时该如何解决呢如下代码Linux使用心跳机制去检测连接是否存活 #define TCP_KEEPALIVE_TIME (120*60*HZ) // 首次2小时 #define TCP_KEEPALIVE_PROBES 9 // 重试9次 #define TCP_KEEPALIVE_INTVL (75*HZ) // 后续每75秒一次 在Linux内核中默认关闭KeepAlive开启KeepAlive后默认2小时后往对端发送心跳包检查是否还活着默认后续每75秒往对端发送心跳包检查是否还活着默认当对端9次都没有响应报文就发送RST报文断开TCP连接释放资源当然这一切参数都可以配置通过sys_setsockopt系统调用当然setsockopt函数库就行啦 回到上述描述的话题往往出现一个机制解决某个问题其他问题又出现。解决了频繁握手和挥手的时间但是连接数量不够的问题又出现了可能很多连接建立在那里完全不通讯了或者对端已经断网或者宕机等等原因占用连接不释放而Linux默认一个连接存活检测需要2个小时 才去检测对端是否活着如果说服务器的负荷比较大2小时才检测一次会导致正常请求无法进行所以此参数需要通过setsockopt函数库重新设置参数当然如果是Java等等虚拟机语言本身也有自身的封装函数去操作setsockopt函数库或者直接调用sys_setsockopt系统调用这个需要看语言手册话又说回来如果设置的阈值大小、时间太短的问题也会很明显一直都在发心跳包检测甚至性能损耗大于了握手和挥手的时间所以需要根据业务环境、服务器的硬件从性能损耗和空闲连接数量做折中考虑 案例 下面是C语言的服务端的案例源码此案例是借用的但是我们重点关心机制 /*server.c*/ #includestdio.h #includestdlib.h #includeerrno.h #includestring.h #includesys/types.h #includenetinet/in.h #includesys/socket.h #includesys/wait.h #include netinet/tcp.h ​ #define PORT 4000//端口号 #define BACKLOG 5/*最大监听数*/ #define MAX_DATA 100//接收到的数据最大程度 ​ int main(){int sockfd,new_fd;/*socket句柄和建立连接后的句柄*/struct sockaddr_in my_addr;/*本方地址信息结构体下面有具体的属性赋值*/struct sockaddr_in their_addr;/*对方地址信息*/int sin_size;char buf[MAX_DATA];//储存接收数据 ​sockfdsocket(AF_INET,SOCK_STREAM,0);//建立socket if(sockfd-1){printf(socket failed:%d,errno);return -1;}my_addr.sin_familyAF_INET;/*该属性表示接收本机或其他机器传输*/my_addr.sin_porthtons(PORT);/*端口号*/my_addr.sin_addr.s_addrhtonl(INADDR_ANY);/*IP括号内容表示本机IP*/bzero((my_addr.sin_zero),8);/*将其他属性置0*/if(bind(sockfd,(struct sockaddr*)my_addr,sizeof(struct sockaddr))0){//绑定地址结构体和socketprintf(bind error);return -1;}listen(sockfd,BACKLOG);//开启监听 第二个参数是最大监听数 while(1){sin_sizesizeof(struct sockaddr_in);new_fdaccept(sockfd,(struct sockaddr*)their_addr,sin_size);//在这里阻塞知道接收到消息参数分别是socket句柄接收到的地址信息以及大小 // 开启保活1分钟内探测不到断开连接int keep_alive 1;int keep_idle 3;int keep_interval 1;int keep_count 57;if (setsockopt(new_fd, SOL_SOCKET, SO_KEEPALIVE, keep_alive, sizeof(keep_alive))) {perror(Error setsockopt(SO_KEEPALIVE) failed);exit(1);}if (setsockopt(new_fd, IPPROTO_TCP, TCP_KEEPIDLE, keep_idle, sizeof(keep_idle))) {perror(Error setsockopt(TCP_KEEPIDLE) failed);exit(1);}if (setsockopt(new_fd, SOL_TCP, TCP_KEEPINTVL, (void *)keep_interval, sizeof(keep_interval))) {perror(Error setsockopt(TCP_KEEPINTVL) failed);exit(1);}if (setsockopt(new_fd, SOL_TCP, TCP_KEEPCNT, (void *)keep_count, sizeof(keep_count))) {perror(Error setsockopt(TCP_KEEPCNT) failed);exit(1);}while(new_fd ! -1) {recv(new_fd,buf,MAX_DATA,0);//将接收数据打入buf参数分别是句柄储存处最大长度其他信息设为0即可。 printf(%s,buf);}}return 0; } 此服务端案例非常的简单当客户端与服务端建立连接后修改KeepAlive的机制参数使用setsockopt库函数修改。 SO_KEEPALIVE开启KeepAlive机制 TCP_KEEPIDLE首次检测的时长 TCP_KEEPINTVL下次检测的间隔时长 TCP_KEEPCNT重试阈值次数 源码分析 首先看到TCP_KEEPIDLE、TCP_KEEPINTVL、TCP_KEEPCNT这三个参数的设置源码在net/ipv4/tcp.c 文件do_tcp_setsockopt方法此方法由sys_setsockopt系统调用方法调用。 static int do_tcp_setsockopt(struct sock *sk, int level,int optname, char __user *optval, int optlen) {struct tcp_sock *tp tcp_sk(sk);struct inet_connection_sock *icsk inet_csk(sk);int val;int err 0;switch (optname) {…………case TCP_KEEPIDLE: // 设置第一次触发的时间if (val 1 || val MAX_TCP_KEEPIDLE)err -EINVAL;else {// 算出设置的时间tp-keepalive_time val * HZ;// 如果KeepAlive机制已开启并且当前不是关闭状态和监听状态。if (sock_flag(sk, SOCK_KEEPOPEN) !((1 sk-sk_state) (TCPF_CLOSE | TCPF_LISTEN))) {// 当前时间 - 上次ACK的时候 相对时间__u32 elapsed tcp_time_stamp - tp-rcv_tstamp;if (tp-keepalive_time elapsed)// 如果上次ACK同步的时间小于设置的时间那就把剩余的时间算出来elapsed tp-keepalive_time - elapsed;else// 如果上次ACK同步的时间大于设置的时间那就立马检测elapsed 0;// 设置内核的定时器inet_csk_reset_keepalive_timer(sk, elapsed);}}break;case TCP_KEEPINTVL: // 设置每次的间隔时间if (val 1 || val MAX_TCP_KEEPINTVL)err -EINVAL;elsetp-keepalive_intvl val * HZ;break;case TCP_KEEPCNT: // 设置阈值次数if (val 1 || val MAX_TCP_KEEPCNT)err -EINVAL;elsetp-keepalive_probes val;break;release_sock(sk);return err; } 这里非常的简单通过switch case的形式把参数添加到结构体中并且设置了首次触发的时间 接下来我们看到定时器何时设置的。在net/ipv4/tcp_ipv4.c 文件中tcp_v4_init_sock方法。 static int tcp_v4_init_sock(struct sock *sk) {…………tcp_init_xmit_timers(sk);…………return 0; }void tcp_init_xmit_timers(struct sock *sk) {inet_csk_init_xmit_timers(sk, tcp_write_timer, tcp_delack_timer,tcp_keepalive_timer); }void inet_csk_init_xmit_timers(struct sock *sk,void (*retransmit_handler)(unsigned long),void (*delack_handler)(unsigned long),void (*keepalive_handler)(unsigned long)) {struct inet_connection_sock *icsk inet_csk(sk);…………// 初始化sk-sk_timer也即初始化timer_list// timer_list在内核是一个定时器的结构体init_timer(sk-sk_timer);// 设置定时器的回调函数sk-sk_timer.function keepalive_handler;………… } 把大部分无关的代码省略掉以后源码看起来非常的简单这里初始化了定时器并且把定时器的回调函数设置成tcp_keepalive_timer所以接下来我们直接分析tcp_keepalive_timer方法即可。在net/ipv4/tcp_timer.c 文件中 tcp_keepalive_timer方法。 // 当达到keepalive设置的值以后回掉此方法。 static void tcp_keepalive_timer (unsigned long data) {struct sock *sk (struct sock *) data;struct inet_connection_sock *icsk inet_csk(sk);struct tcp_sock *tp tcp_sk(sk);__u32 elapsed;/* Only process if socket is not in use. */bh_lock_sock(sk);if (sock_owned_by_user(sk)) {// 这里很简单因为锁的原因所以需要重试。inet_csk_reset_keepalive_timer (sk, HZ/20);goto out;}// 4次挥手阶段而此时达到了保活的检测此时发送RST报文给对端表示我要断开了然后释放资源即可。if (sk-sk_state TCP_FIN_WAIT2 sock_flag(sk, SOCK_DEAD)) {if (tp-linger2 0) {const int tmo tcp_fin_time(sk) - TCP_TIMEWAIT_LEN;if (tmo 0) {tcp_time_wait(sk, TCP_FIN_WAIT2, tmo);goto out;}}tcp_send_active_reset(sk, GFP_ATOMIC);goto death;}// 如果KeepAlive没有开启或者当前已经是关闭状态if (!sock_flag(sk, SOCK_KEEPOPEN) || sk-sk_state TCP_CLOSE)goto out;// 算出下次检测的时间elapsed keepalive_time_when(tp);// 此时正在发送报文所以无须检测直接重置下次检测的时间if (tp-packets_out || tcp_send_head(sk))goto resched;// 算出距离上一次ACK的相对时间elapsed tcp_time_stamp - tp-rcv_tstamp;// 如果上一次ACK的相对时间 大于等于 设置的时间那么就代表达到一次阈值if (elapsed keepalive_time_when(tp)) {// 查看是否达到次数阈值达到阈值后直接发送RST报文给对方然后关闭连接。if ((!tp-keepalive_probes icsk-icsk_probes_out sysctl_tcp_keepalive_probes) ||(tp-keepalive_probes icsk-icsk_probes_out tp-keepalive_probes)) {tcp_send_active_reset(sk, GFP_ATOMIC);tcp_write_err(sk);goto out;}// 没达到阈值的情况// 尝试发送报文给对方看是否还活着if (tcp_write_wakeup(sk) 0) {// 如果回复了那就把下次检测的时间设置好icsk-icsk_probes_out;elapsed keepalive_intvl_when(tp);} else { // 对端没有回复不知道是因为丢失还是怎么了所以加快速度尝试下一次。elapsed TCP_RESOURCE_PROBE_INTERVAL;}} else {// 没有达到上次ACK的相对时间所以算出差值设置到定时器中。elapsed keepalive_time_when(tp) - elapsed;}TCP_CHECK_TIMER(sk);sk_stream_mem_reclaim(sk);resched:// 把最新值设置到定时器中。inet_csk_reset_keepalive_timer (sk, elapsed);goto out;death:// 关闭连接释放资源。tcp_done(sk);out:bh_unlock_sock(sk);sock_put(sk); } 此方法是当定时器结束后回调执行检测是否达到了我们设置或者默认的阈值如果没有达到再设置下一次定时器的时间如果达到了就发送RST报文关闭连接释放资源
http://www.huolong8.cn/news/320011/

相关文章:

  • 番禺制作网站技术美业网站建设
  • 俄罗斯做货代的网站政务公开和网站建设工作问题
  • 网站建设公司及网络安全法大专学历怎么自考
  • 上饶建设银行网站长沙网约车驾驶员资格证网上报名
  • 网站建设公司 云智互联网站建设心得感想
  • asp.net mvc做网站难吗教育网站设计欣赏
  • 成都网站设计师网络推广途径和推广要点
  • 保定的网站建设网络推广方案有哪些
  • 那些网站可以做h5wordpress扒站工具
  • 汽车报价大全官网惠州网站关键字优化
  • 网站的建设费用分为南宁网约车资格证网上报名
  • 备案成功的网站网站域名301设置
  • 网站架构图用什么做哈尔滨营销网站建设公司哪家好
  • 海尔商城网站建设维护网站再就业技能培训班
  • 宿州市建设局网站网页封装app
  • 网站怎么做301吉林平台网站建设哪里有
  • 网站做接口排线方法做转运网站
  • 网站嵌套代码做网站用花瓣上的图片会侵权吗
  • seo网站设计网页单页设计将自己做的网站发布到
  • html5做网站链接网站怎么更改关键词
  • p2p平台网站开发坪山手机网站建设
  • 买房网站排名手机商城网站
  • 网站首页收录专业购物网站
  • 张家口市建设局网站网页显示站点不安全
  • 做片头网站电商网站建设需求分析引言
  • 不关闭网站 备案深圳网站建设要多少钱
  • php做网站怎么布局哪个网站做宣传比较好
  • 免费网站哪个好做手机网站要注意
  • ktv网站建设方案专做负面的网站
  • 社区网站如何做flash 网站制作