linux comet模型下的连接数统计
comet模型的主机维持长连接,单台连接接数可以达到百万(现网目前用的最高单台可达到60万左右),在统计网络连接状态时会netstat会长期不响应,而SS命令统计相对较快,不过输出不够美观 。本篇主要总结下comet模型下的连接数常见统计方法。tcp连接主机是通过读取/proc/net/tcp文件进行的统计。具体每项值的意思见下图(点击可查看大图)
一、C++ 代码实现连接数统计
1[root@361way netstat]# cat ss++.cc
2// code from www.361way.com
3#include<iostream>
4#include<fstream>
5#include<cstdlib>
6#include<sstream>
7using namespace std;
8//struct: Property of a tcp connection
9struct ConnectionProperty
10{
11 string local_addr;
12 string remote_addr;
13 string state;
14};
15//Change hexadecimal number to decimal number
16int HexToInt(char h)
17{
18 if(h >= '0' && h <= '9')
19 {
20 return h - '0';
21 }
22 else if(h >= 'A' && h <= 'F')
23 {
24 return h - 'A' + 10;
25 }
26 else
27 {
28 cerr << "Error: Illegal Hex Number!" << endl;
29 return -1;
30 }
31}
32//Get Ip address and port number from string XXXXXXXX:XXXX
33string GetIpAddress(char* str)
34{
35 int a, b, c, d, e;
36 a = HexToInt(str[0]) * 16 + HexToInt(str[1]);
37 b = HexToInt(str[2]) * 16 + HexToInt(str[3]);
38 c = HexToInt(str[4]) * 16 + HexToInt(str[5]);
39 d = HexToInt(str[6]) * 16 + HexToInt(str[7]);
40 e = HexToInt(str[9]) * 16 * 16 * 16 +
41 HexToInt(str[10]) * 16 * 16 +
42 HexToInt(str[11]) * 16 +
43 HexToInt(str[12]);
44 //change int to string
45 string sa, sb, sc, sd, se;
46 ostringstream oss;
47 oss << a;
48 sa = oss.str();
49 oss.str(""); //clear the content in oss
50 oss << b;
51 sb = oss.str();
52 oss.str("");
53 oss << c;
54 sc = oss.str();
55 oss.str("");
56 oss << d;
57 sd = oss.str();
58 oss.str("");
59 oss << e;
60 se = oss.str();
61 oss.str("");
62 //return by order: d.c.b.a:e
63 return sd + '.' + sc + '.' + sb + '.' + sa + ':' + se;
64}
65//Get tcp connection state
66string GetConnectionState(char* str)
67{
68 if(str[0] == '0' && str[1] == '0') return "ERROR_STATUS";
69 if(str[0] == '0' && str[1] == '1') return "TCP_ESTABLISHED";
70 if(str[0] == '0' && str[1] == '2') return "TCP_SYN_SENT";
71 if(str[0] == '0' && str[1] == '3') return "TCP_SYN_RECV";
72 if(str[0] == '0' && str[1] == '4') return "TCP_FIN_WAIT1";
73 if(str[0] == '0' && str[1] == '5') return "TCP_FIN_WAIT2";
74 if(str[0] == '0' && str[1] == '6') return "TCP_TIME_WAIT";
75 if(str[0] == '0' && str[1] == '7') return "TCP_CLOSE";
76 if(str[0] == '0' && str[1] == '8') return "TCP_CLOSE_WAIT";
77 if(str[0] == '0' && str[1] == '9') return "TCP_LAST_ACK";
78 if(str[0] == '0' && str[1] == 'A') return "TCP_LISTEN";
79 if(str[0] == '0' && str[1] == 'B') return "TCP_CLOSING";
80 return "UNKNOWN_STATE";
81}
82int main()
83{
84 //read from file /proc/net/tcp
85 ifstream infile("/proc/net/tcp", ios :: in);
86 if(!infile)
87 {
88 cerr << "open error!" << endl;
89 exit(1);
90 }
91 string s;
92 char s_local_addr[20], s_remote_addr[20], s_state[20];
93 getline(infile, s); //title: every column's name
94 while(getline(infile, s))
95 {
96 sscanf(s.c_str(), "%*s%s%s%s", s_local_addr, s_remote_addr, s_state);
97 //printf("%s\t%s\t%s\n", s_local_addr, s_remote_addr, s_state);
98 string ip_local = GetIpAddress(s_local_addr);
99 string ip_remote = GetIpAddress(s_remote_addr);
100 string conn_state = GetConnectionState(s_state);
101 cout << ip_local << "\t" << ip_remote << "\t" << conn_state << endl;
102 }
103 return 0;
104}
通过如下代码编译生成可执行文件: g++ -o netinfo ss++.cc
,执行输出如下:
1[root@comethost ~]# ./netinfo
2115.28.174.118:5224 121.31.251.8:13351 TCP_ESTABLISHED
3115.28.174.118:5229 223.104.23.84:62815 TCP_ESTABLISHED
4115.28.174.118:5225 117.136.79.70:45116 TCP_ESTABLISHED
5115.28.174.118:5224 112.17.243.208:33236 TCP_ESTABLISHED
6115.28.174.118:5224 27.204.14.135:44976 TCP_ESTABLISHED
7115.28.174.118:5228 58.18.233.29:60135 TCP_ESTABLISHED
8115.28.174.118:5226 112.17.246.84:26055 TCP_ESTABLISHED
二、python实现tcp连接统计
1#!/usr/bin/env python
2# code from www.361way.com
3# coding=utf-8
4import pwd
5import os
6import re
7import glob
8PROC_TCP = "/proc/net/tcp"
9STATE = {
10 '01':'ESTABLISHED',
11 '02':'SYN_SENT',
12 '03':'SYN_RECV',
13 '04':'FIN_WAIT1',
14 '05':'FIN_WAIT2',
15 '06':'TIME_WAIT',
16 '07':'CLOSE',
17 '08':'CLOSE_WAIT',
18 '09':'LAST_ACK',
19 '0A':'LISTEN',
20 '0B':'CLOSING'
21 }
22def _load():
23 ''' Read the table of tcp connections & remove header '''
24 with open(PROC_TCP,'r') as f:
25 content = f.readlines()
26 content.pop(0)
27 return content
28def _hex2dec(s):
29 return str(int(s,16))
30def _ip(s):
31 ip = [(_hex2dec(s[6:8])),(_hex2dec(s[4:6])),(_hex2dec(s[2:4])),(_hex2dec(s[0:2]))]
32 return '.'.join(ip)
33def _remove_empty(array):
34 return [x for x in array if x !='']
35def _convert_ip_port(array):
36 host,port = array.split(':')
37 return _ip(host),_hex2dec(port)
38def netstat():
39 '''
40 Function to return a list with status of tcp connections at linux systems
41 To get pid of all network process running on system, you must run this script
42 as superuser
43 '''
44 content=_load()
45 result = []
46 for line in content:
47 line_array = _remove_empty(line.split(' ')) # Split lines and remove empty spaces.
48 l_host,l_port = _convert_ip_port(line_array[1]) # Convert ipaddress and port from hex to decimal.
49 r_host,r_port = _convert_ip_port(line_array[2])
50 state = STATE[line_array[3]]
51 nline = [ l_host+':'+l_port, r_host+':'+r_port, state ]
52 result.append(nline)
53 return result
54if __name__ == '__main__':
55 for conn in netstat():
56 print conn
三、ss统计
默认安装完iproute2包后,里面包含有ss工具,不过想要查看ss的源码可以到https://github.com/shemminger/iproute2/blob/master/misc/ss.c 查看 。
四、统计速率统计
这里只找了一台连接数在20多万的comet服务器进行的测试,从执行效果来看:
- ss -nt执行速度最快
- c++版的netinfo与ss接近(稍慢于c语言版的ss)
- python版的比ss与netinfo慢五到六倍
- netstat没做测试,根据之前的了解,估计与python版的接近或者差于python版的
所以后续现网有简单的连接数统计需求,会优先选择c++版的ss(输出美观),而且可以在此基础上简单定制 。
参考页面:
python版的ss参考 voorloopnul
相关代码已上传至我的github :https://github.com/361way/python/tree/master/netstat
捐赠本站(Donate)
如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))
- Author: shisekong
- Link: https://blog.361way.com/comet-ss/5257.html
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.