#!/usr/bin/python
# -*- coding: utf-8 -*
# #############################################################################
#
# Copyright (c) 2014 Baidu.com, Inc. All Rights Reserved
#
# #############################################################################
"""
:author:
Guannan Ma
:create_date:
2014
:last_date:
2014
:descrition:
network related module
"""
import socket
import struct
import warnings
try:
import fcntl
except ImportError as error:
# 'Seems run on non-linux machine'
pass
from cup.net import async
from cup import platforms
__all__ = [
'get_local_hostname',
'get_hostip',
'getip_byinterface',
'set_sock_keepalive_linux',
'set_sock_reusable',
'set_sock_linger',
'set_sock_quickack',
'async'
]
if platforms.is_linux():
_SOCK = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
_SOCKFD = _SOCK.fileno()
_SIOCGIFADDR = 0x8915
[docs]def getip_byinterface(iface='eth0'):
"""
@platform:
Linux/Unix
获得某个网卡的ip地址
E.g.
::
import cup
print cup.net.getip_byinterface('eth0')
print cup.net.getip_byinterface('eth1')
print cup.net.getip_byinterface('xgbe0') # 万兆网卡
"""
if platforms.is_linux():
ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00' * 14)
try:
res = fcntl.ioctl(_SOCKFD, _SIOCGIFADDR, ifreq)
except Exception as error: # pylint: disable=W0703,W0612
return None
ipaddr = struct.unpack('16sH2x4s8x', res)[2]
return socket.inet_ntoa(ipaddr)
else:
raise NotImplementedError('Not implemented on this platform')
[docs]def get_local_hostname():
"""
获得当前机器的hostname
"""
return str(socket.gethostname())
[docs]def get_hostip(hostname=None):
"""
拿到某hostname的ip地址.
:param hostname:
机器的hostname, 默认为None代表不传值, 函数将自动获取当前机器的ip
"""
if hostname is None:
hostname = get_local_hostname()
return str(socket.gethostbyname(hostname))
[docs]def set_sock_keepalive_linux(
sock, after_idle_sec=1, interval_sec=3, max_fails=5
):
"""
Set TCP keepalive on an open socket.
It activates after 1 second (after_idle_sec) of idleness,
then sends a keepalive ping once every 3 seconds (interval_sec),
and closes the connection after 5 failed ping (max_fails), or 15 seconds
:param sock:
socket
:param after_idle_sec:
for TCP_KEEPIDLE
:param interval_sec:
for TCP_KEEPINTVL
:param max_fails:
for TCP_KEEPCNT
"""
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, after_idle_sec)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails)
# pylint: disable=W0613
def set_keepalive_osx(sock, after_idle_sec=1, interval_sec=3, max_fails=5):
"""
Set TCP keepalive on an open socket.
Sends a keepalive ping once every 3 seconds (interval_sec)
"""
# scraped from /usr/include, not exported by python's socket module
# pylint: disable=C0103
TCP_KEEPALIVE = 0x10
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
sock.setsockopt(socket.IPPROTO_TCP, TCP_KEEPALIVE, interval_sec)
[docs]def set_sock_reusable(sock, resuable=True):
"""
设置socket的端口是否可被重复使用, 默认resuable==True
"""
if resuable:
value = 1
else:
value = 0
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, value)
[docs]def set_sock_linger(sock):
"""
关闭socket的linger参数。
实际产生的效果如下:
I.g.
::
sock.setsockopt(
socket.SOL_SOCKET, socket.SO_LINGER,
struct.pack('ii', 0, 0)
)
"""
l_onoff = 0
l_linger = 0
sock.setsockopt(
socket.SOL_SOCKET, socket.SO_LINGER, struct.pack(
'ii', l_onoff, l_linger
)
)
[docs]def set_sock_quickack(sock):
"""
打开socket的quickack功能:
I.g.
::
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_QUICKACK, 1)
"""
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_QUICKACK, 1)
# vi:set tw=0 ts=4 sw=4 nowrap fdm=indent