code // 只有上帝和我知道这行代码什么意思 1970.01.01
code // 现在只有上帝知道了 1970.01.07
记录一下Python socket.py 中各接口的作用。
ssl : pass
_socketmethods=(
'bind','connect','connect_ex','fileno','listen',
'getpeername','getsockname','getsockopt','setsockopt',
'sendall','setblocking',
'settimeout','gettimeout','shutdown')
模块被导入时给socket绑定上的方法名列表。
def meth(name,self,*args):
return getattr(self._sock,name)(*args)
从socket属性中获取对应名字的方法。
for _m in _socketmethods:
p = partial(meth,_m)
p.__name__ = _m
p.__doc__ = getattr(_realsocket,_m).__doc__
m = MethodType(p,None,_socketobject)
setattr(_socketobject,_m,m)
将_socket.py中的方法设置到_socketobject对象中,模块被引用时调用,具体为_socketmethods元祖中的方法名。
socket = SocketType = _socketobject # 对_socketobject类的引用,方便构造socket对象。
class _closedsocket:
关闭了的socket类对象,将自身的_dummy方法覆盖了其它的基本方法
class _socketobject:
socket基本实体,初始化时绑定 _delegate_methods = ("recv", "recvfrom", "recv_into", "recvfrom_into","send", "sendto")等方法。
初始化函数接收family, type, protocol参数,接收对象为socket.py 模块中的 SocketType类
close(self):
生成closedsocket类实例。干毛用未知。
accept(self):
调用自身的_socket对象进行接收链接的操作,接收操作返回sock链路实体对象与addr地址信息。将socket链路实体传入_socketobject后就获得了新的用来通讯的链路对象。
dup(self):
生成一个拥有相同资源的链路(未理解)。
makefile(self):
返回一个与socket一致的标准文件对象??
family: property 返回family信息
type: property 返回type信息
proto: property 返回proto信息
总结: 导入时绑定socket基本方法,实例化时绑定接收,发送等方法。底层好像调用的都还是sendall方法,只不过是根据缓存区大小决定发不发送数据。
class _fileobject(object):
default_bufsize = 8192
name = "<socket>"
def __init__(self, sock, mode='rb', bufsize=-1, close=False):
初始化函数接收参数等。如果传入的bufsize参数乱七八糟的话,self.bufsize, self._rbufsize, self.wbufsize都默认为8192。
self._rbuf = StringIO() 读缓存区用StringIO对象来记录数据?
self._wbuf = [] 写入缓存区为字符串组成的列表,为毛?
self._wbuf_len = 0 初始化的写缓存列表长度为0
self.close = close 初始化时为False
def _getclosed:
返回布尔值,判断self._socket值是否为None
def close:
如果self._sock存在,将写缓存区的数据全部发出去。如果self._close属性为True,调用_socketobject的close方法。之后将self._socket置为None。
def __del__(self):
try:
self.close()
def flush(self):
将写缓存区列表里的元素组成一个字符串整体后,清空写缓存区列表,然后将数据一齐发出去。如果出现异常,未发送出去的数据slice之后添加回写缓存区。
def fileno(self):
获取文件描述符
def write(self, data):
将data字符串化后,将字符串添加到写缓存区,记录其长度。如果写缓存区超过默认大小的话,就flush发出去。
def writelines(self, list):
具体原理同write
def read(self, size=-1):
rbufsize度缓存区默认大小8192。buf为 StringIO()对象,调用read方法时,定位读取位置为结尾。然后根据read的参数size决定读取细节。
1. 未指定size时默认接收到无数据可读为止。(收数据,写到缓存区,全部获取。
2. 指定size参数时,记录当前读取位置,判断读取缓存区的数据大小是否超过size大小。
2.1 超过的话就先读取size大小的数据出来,多出的数据存到读缓存区。(从缓存区读取数据)。
2.2 未超过的话持续接收……没数据时停止。啊好累,一种读缓存区没数据的情况,直接返回数据。一种获取到同样大小数据后,写入读缓存区。
def readline, readlines: // to do
def __iter__(self):
return self
def next(self):
line = self.readline()
if not line:
raise StopIteration
return line
总结: 通过类实现一个 file对象,并有相应的缓存区机制,实现读写操作,实现for 语句的操作等。只有read无指定size参数时会清空读缓存区。