免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: yestreenstars
打印 上一主题 下一主题

作为一名Python爱好者,你懂网络编程吗? [复制链接]

论坛徽章:
0
11 [报告]
发表于 2015-01-12 12:43 |只看该作者
1.说说你对TCP/IP协议的了解有多少。
TCP/IP协议属于网络通信协议,由网络层的IP协议和传输层的TCP协议组成,定义电子设备怎么连入互联网,以及相互间如何通信。
TCP/ip协议是HTTP的底层协议,在采用socket通讯时,会使用TCP或者UDP。TCP属于有连接传输;UDP属于无连接传输,也叫广播传送,它可以由开发人员管理状态。
网络编程一般采用http协议或者https协议的session,cookie等元素来进行管理。

2.说说你对Python基础知识的了解有多少。
python主要了解他的基本语法和应用,有丰富的库,可以做系统维护方面的工作,也有很强的网络功能,目前主要在以对象的方式进行网络和数据库开发,涉及线程、CGI、数据库、xml、html等库。


3.说说你读完本章节后的感谢。(图书链接在下方)
章节写的浅显易懂,实战内容很贴切,适合做网络应用开发,最近正在写一个爬虫小程序,抓取特定的数据整合,希望能够有这本书给予帮助。

4.请给出一段跟网络编程相关的Python代码并简单说明一下它的功能。
  1. import urllib   
  2. import urllib2   
  3.   
  4. url = '....testserver.com/register.do'  
  5.   
  6. user_agent = 'Mozilla/4.0 (compatible; MSIE 6; Windows NT)'   
  7. values = {'name' : 'xfzhi888',   
  8.           'location' : 'shenzhen',   
  9.           'language' : 'Python' }   
  10.   
  11. headers = { 'User-Agent' : user_agent }   
  12. data = urllib.urlencode(values)   
  13. req = urllib2.Request(url, data, headers)   
  14. response = urllib2.urlopen(req)   
  15. the_page = response.read()  
复制代码
功能:使用python写的爬虫中的一小段,模拟IE浏览器访问网站并获取页面信息。

论坛徽章:
93
2015年辞旧岁徽章
日期:2019-10-10 10:51:15CU大牛徽章
日期:2014-02-21 14:21:56CU十二周年纪念徽章
日期:2020-10-15 16:55:55CU大牛徽章
日期:2014-02-21 14:22:07羊年新春福章
日期:2019-10-10 10:51:39CU大牛徽章
日期:2019-10-10 10:55:38季节之章:春
日期:2020-10-15 16:57:40ChinaUnix元老
日期:2019-10-10 10:54:42季节之章:冬
日期:2019-10-10 10:57:17CU大牛徽章
日期:2014-02-21 14:22:52CU大牛徽章
日期:2014-03-13 10:40:30CU大牛徽章
日期:2014-02-21 14:23:15
12 [报告]
发表于 2015-01-12 17:37 |只看该作者
不懂python可以来捧场吗~~

论坛徽章:
32
处女座
日期:2013-11-20 23:41:20双子座
日期:2014-06-11 17:20:43戌狗
日期:2014-06-16 11:05:00处女座
日期:2014-07-22 17:30:47狮子座
日期:2014-07-28 15:38:17金牛座
日期:2014-08-05 16:34:01亥猪
日期:2014-08-18 13:34:25白羊座
日期:2014-09-02 15:03:55金牛座
日期:2014-11-10 10:23:58处女座
日期:2014-12-02 09:17:52程序设计版块每日发帖之星
日期:2015-06-16 22:20:002015亚冠之塔什干火车头
日期:2015-06-20 23:28:22
13 [报告]
发表于 2015-01-12 17:51 |只看该作者
回复 14# seesea2517

of course!
   

论坛徽章:
93
2015年辞旧岁徽章
日期:2019-10-10 10:51:15CU大牛徽章
日期:2014-02-21 14:21:56CU十二周年纪念徽章
日期:2020-10-15 16:55:55CU大牛徽章
日期:2014-02-21 14:22:07羊年新春福章
日期:2019-10-10 10:51:39CU大牛徽章
日期:2019-10-10 10:55:38季节之章:春
日期:2020-10-15 16:57:40ChinaUnix元老
日期:2019-10-10 10:54:42季节之章:冬
日期:2019-10-10 10:57:17CU大牛徽章
日期:2014-02-21 14:22:52CU大牛徽章
日期:2014-03-13 10:40:30CU大牛徽章
日期:2014-02-21 14:23:15
14 [报告]
发表于 2015-01-13 10:28 |只看该作者
回复 15# yestreenstars


    {:3_189:} ~~

论坛徽章:
18
卯兔
日期:2013-09-27 17:41:0615-16赛季CBA联赛之佛山
日期:2016-07-09 17:34:45操作系统版块每周发帖之星
日期:2015-12-02 15:01:04IT运维版块每日发帖之星
日期:2015-12-02 06:20:00IT运维版块每日发帖之星
日期:2015-10-07 06:20:00IT运维版块每日发帖之星
日期:2015-10-03 06:20:00IT运维版块每日发帖之星
日期:2015-10-01 06:20:00羊年新春福章
日期:2015-04-01 17:56:06拜羊年徽章
日期:2015-04-01 17:56:062015年迎新春徽章
日期:2015-03-04 09:49:452015年辞旧岁徽章
日期:2015-03-03 16:54:15天秤座
日期:2015-01-14 06:39:28
15 [报告]
发表于 2015-01-13 13:14 |只看该作者
好书,先占个位置.........................
从楼上看到各位都是编程的高手啊

求职 : Linux运维
论坛徽章:
19
CU大牛徽章
日期:2013-03-13 15:15:0815-16赛季CBA联赛之山东
日期:2016-10-31 10:40:10综合交流区版块每日发帖之星
日期:2016-07-06 06:20:00IT运维版块每日发帖之星
日期:2016-02-08 06:20:00数据库技术版块每日发帖之星
日期:2016-01-15 06:20:00IT运维版块每日发帖之星
日期:2016-01-15 06:20:00IT运维版块每日发帖之星
日期:2016-01-10 06:20:00黄金圣斗士
日期:2015-11-24 10:45:10IT运维版块每日发帖之星
日期:2015-09-01 06:20:00IT运维版块每日发帖之星
日期:2015-08-13 06:20:00IT运维版块每日发帖之星
日期:2015-07-30 09:40:012015年亚洲杯之巴勒斯坦
日期:2015-05-05 10:19:03
16 [报告]
发表于 2015-01-14 10:13 |只看该作者
使用python最重要的原因是因为她是自由开源软件。这是算法的最直接的描述,未来源代码的封闭将让我们无法知道计算机的行为,那是可怕的

论坛徽章:
1
水瓶座
日期:2013-11-04 13:16:13
17 [报告]
发表于 2015-01-14 13:51 |只看该作者
python网络编程可以看它的twisted框架啊

论坛徽章:
1
天蝎座
日期:2013-10-23 21:11:03
18 [报告]
发表于 2015-01-14 18:16 |只看该作者
支持
Python还是很方便的

论坛徽章:
40
水瓶座
日期:2013-08-15 11:26:422015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之乌兹别克斯坦
日期:2015-03-27 14:01:172015年亚洲杯之约旦
日期:2015-03-31 15:06:442015亚冠之首尔
日期:2015-06-16 23:24:37IT运维版块每日发帖之星
日期:2015-07-01 22:20:002015亚冠之德黑兰石油
日期:2015-07-08 09:32:07IT运维版块每日发帖之星
日期:2015-08-29 06:20:00IT运维版块每日发帖之星
日期:2015-08-29 06:20:00IT运维版块每日发帖之星
日期:2015-10-10 06:20:00IT运维版块每日发帖之星
日期:2015-10-11 06:20:00IT运维版块每日发帖之星
日期:2015-11-10 06:20:00
19 [报告]
发表于 2015-01-14 19:37 |只看该作者
1.说说你对TCP/IP协议的了解有多少。
如果指的是TCP/IP协议族的话不敢说了解太多,因为它们包含好多协议,但是对于TCP/UDP/IP/WebSocket/DNS/DHCP 这几个协议来说还是非常有自信的。以前读过《TCP/IP 卷1》,内容基本能够理解,而且现在从事的工作涉及到linux系统网络的部分开发。
对于TCP还是非常佩服,但是就设计出这么优秀的协议,前段时间在研究WebSocket,发现WebSocket几乎和TCP协议没什么区别,就是略微封装一下TCP协议,对于HTTP协议来说开销小了很多,而且支持双向即时通讯。

2.说说你对Python基础知识的了解有多少。
Python也是当年的备选语言,最终还是系统的学习了lua语言,相对来说lua更适合嵌入式设备中的程序开发,即使这样也学习了一些Python的基础内容。能够使用python构建简单的管理程序,再进一步的内容就无从适应了。对于网络编程来说,各个语言都是非常类似的,都是通过对应的接口函数或者对象、类来发起TCP或者UDP的连接,服务端监听请求并作出处理。

3.说说你读完本章节后的感想
试读章节内容不多,托管在了图灵社区里面,大体看了下第一章节的内容:
这一章节是一个介绍入门性的内容,显示介绍了Python的网络编程用到的核心网络库,也就是socket模块提供的类方法和实例方法,使用python第一步就是使用import导入要使用的库文件,然后建立一个socket连接,这里连接服务器用到了两步,分别是获取主机对应的ip地址,然后是发起真正的TCP请求。
试读章节的内容都是从准备工作、实战演练和原理分析的步骤进行,每一块都是一个实战过程,分块学习比较有成就感,组织方式挺不错。试读完之后感觉就是Python的网络编程和其他语言网络编程类似,而且类库准备了大量的函数,学习和使用起来应该非常方便。

4.请给出一段跟网络编程相关的Python代码并简单说明一下它的功能。
下面是一段rot13的代码,是关于字符串加解密的,这个和网络编程可能有些不相关,但是非常有意思,当年罗马军事通讯就用了这个加密算法,就是字母的位置移动,python没有内置的函数,但是可以通过python的字符串操作函数组合就能快速实现。
  1. python
  2. # rot13, readable
  3. rot13_tbl = string.maketrans("ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz", "NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm")
  4. string.translate("Hello World #123", rot13_tbl)

  5. #
  6. # 这里说的是一个坏的程序员无论用啥语言编程都能写出烂代码
  7. #

  8. # rot13,这是一个好的写法
  9. string.translate("Hello World #123", string.maketrans(string.lowercase+string.uppercase, string.lowercase[13:]+string.lowercase[:13]+string.uppercase[13:]+string.uppercase[:13]))

  10. # rot47, 这是非常好的写法
  11. ''.join([ord(c) in range(33,127) and chr(((ord(c)-33+47)%(127-33))+33) or c for c in "Hello World #123"])

  12. python
  13. "Hello World #123".encode('rot13')
复制代码

论坛徽章:
11
2015年迎新春徽章
日期:2015-03-04 09:55:282017金鸡报晓
日期:2017-02-08 10:39:4215-16赛季CBA联赛之辽宁
日期:2016-12-15 10:24:1715-16赛季CBA联赛之佛山
日期:2016-11-30 09:04:2015-16赛季CBA联赛之江苏
日期:2016-04-29 15:56:1215-16赛季CBA联赛之同曦
日期:2016-04-12 13:21:182016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之山东
日期:2016-02-16 11:37:52每日论坛发贴之星
日期:2016-02-07 06:20:00程序设计版块每日发帖之星
日期:2016-02-07 06:20:0015-16赛季CBA联赛之新疆
日期:2018-01-09 16:25:37
20 [报告]
发表于 2015-01-15 19:18 |只看该作者
回复 1# yestreenstars

1.不多
2.不多
3.没有感觉
4.代码

#工作流程说明:
# .主线程
#    控制配置文件刷新和其它线程的启停
# .socket主线程:
#    接收client连接,放到Context.vClients
# .客户端线程
#   解包client数据,产生dEvent,检验后放到 Context.qIndb去入event表
# .入库线程
#   对Context.qIndb中的数据进行分类处理,对告警事件,如果入库成功
#   添加INSTID,然后放到 Context.qArData
# .告警规则线程
#   对Context.qArData进行压缩和延迟
#   待通知的结果放到 Context.qAlarm
# .告警通知
#   对Context.qAlarm按规则进行mail或sms,发送结果放到Context.qIndb去入send表
#, 并将告警发送关系放到Context.qIndb去入cdr表
# .告警重发
#   根据send表,cdr表和时间设置进行重发
#
# 每个线程起来后不需要停止
#
###############################################################################
import sys,os,time
import select,socket,string,cPickle as pickle
import threading,thread,logging,Queue
import signal,StringIO,traceback

###############################################################################
from rules import engine as _engine
from rules.entity import Utils as _utils, InitUtils

import SocketServerPlus as SocketServer,select

###############################################################################
__version__ = 'Server 2.0'

# Context:上下文
#
class Context:
        pass # 太长省了....


###############################################################################
#主线程
#检测配置文件变化和停止标志.
#控制其它线程
#
class MainThread:
        pass # 太长省了....
###############################################################################
#可控的安全线程(可控,能控并且是必控)
#start,stop
#
class Subroutine(threading.Thread):
      pass # 太长省了....

class MainSock(Subroutine):
        def __init__(self):
                Subroutine.__init__(self)
                return
       
        def _init(self):
                SocketServer.ThreadingTCPServer.allow_reuse_address = True
                if context.sServIP or context.nServPort > 0:
                        sAddress = (context.sServIP,context.nServPort)
                        _INFO('%s Start Server ... [%s]',_cOdepOs(self), str(sAddress))
                        context.server = SocketServer.ThreadingTCPServer(sAddress,RequestHandlerClass)
                        pass
                else:
                        _ERROR('%s Server=[%s] Paramter Error.',_cOdepOs(self), str(sAddress))
                        pass
                return True
        def _refresh(self):
                if not context.server:
                        return
                sAddress = (context.sServIP,context.nServPort)
                if sAddress == context.server.server_address:
                        return
                self._finish()
                self._init()
                return
       
        def _run(self):
                if not context.server:
                        return False
                r, w, e = select.select([context.server], [], [], 0.5)
                if r:
                        context.server._handle_request_noblock()
                        pass
                return True
       
        def _finish(self):
                if context.server:
                        sAddress = (context.sServIP,context.nServPort)
                        _INFO('%s Stop Server ... [%s]',_cOdepOs(self), str(sAddress))
                        context.server.server_close()
                        del context.server
                        pass
                context.server = None
                while len(context.vClients):
                        time.sleep(1)
                        _INFO('%s wait client ... [%d]',_cOdepOs(self), len(context.vClients))
                        continue
                return True

#告警规则的调用流程
class AlarmRuleThread2(Subroutine):
        pass # 太长省了....

class ForwardThread(Subroutine):
        def __init__(self):
                Subroutine.__init__(self)
                self.engine = _engine.RuleEngine(context,_cOdepOs)
                pass
        def _init(self):
                try:
                        service = context.plat.GetServiceByServer()
                        root = service.getElementsByTagName('FORWARD_RULE_SERVICE')[0]
                        self.engine.Load(root)
                        self.engine.init()
                        pass
                except:
                        fp = StringIO.StringIO()
                        traceback.print_exc(file=fp)
                        message = fp.getvalue()
                        _ERROR('%s except=>>>%s<<<', _cOdepOs(self),message)
                        pass
                return True
        #
        def _refresh(self):
                self._finish()
                self._init()
                return
        #
        def _run(self):
                bEmpty = context.qAlarm.empty()
                #_INFO('%s ??????', _cOdepOs(self))

                while not context.qAlarm.empty():
                        item = context.qAlarm.get()
                        _INFO('%s forward disp alarm %s', _cOdepOs(self),_utils.getkey(item))
                        #拿去转发
                        self.engine.rc.vInput.append(item)
                        setattr(self,'输入',getattr(self,'输入',0)+1)
                        continue
                #根据规则转发
                self.engine.run()
               
                #更新发送状态表
                for item in self.engine.rc.vOutput:
                        self.__indbq(item)
                        setattr(self,'输出',getattr(self,'输出',0)+1)
                        pass
                del self.engine.rc.vOutput[:]
               
                if bEmpty:
                        time.sleep(1)
                        pass
                return True
       
        def _hb(self):
                _INFO('Forward process [%d] alarm, and output [%d] alarm',
                getattr(self,'输入',0),getattr(self,'输出',0))

        #告警发送状态数据入库
        def __indbq(self,dEvent):
                #数据正确性,完整性由forward rule保证,这里不做校验
                sDataKey = _utils.getkey(dEvent)
                #先验证一下
                sFuncOld = dEvent['_func']
                assert(sFuncOld in ('InsertAlarmCdr','InsertAlarmSend'))
                _INFO('%s put to indb quequ for [%s], key=(%s)',
                _cOdepOs(self),sFuncOld,sDataKey)
               
                context.qIndb.put(dEvent)
                return
        #
        def _finish(self):
                self.engine.end()
                return True

class ResendThread(Subroutine):
        def __init__(self):
                Subroutine.__init__(self)
                self.hModule = None
                self.hInst = None
                pass
        def _init(self):
                try:
                        self.hModule = __import__(context.sResend, globals(), locals(), ['*'])
                        self.hModule = reload(self.hModule)
                        self.hInst = self.hModule.TReSendMessage()
                        self.hInst.Init(context.db)
                        self.hInst.Run()
                        pass
                except:
                        self.hModule = None
                        self.hInst = None
                        fp = StringIO.StringIO()
                        traceback.print_exc(file=fp)
                        message = fp.getvalue()
                        _ERROR('%s except=>>>%s<<<', _cOdepOs(self),message)
                        pass
                return True
        #
        def _refresh(self):
                self._finish()
                self._init()
                return
        #
        def _run(self):
                time.sleep(1)
                return True
        #
        def _finish(self):
                if self.hInst:
                        del self.hInst
                        self.hInst = None
                return True


#专门入库的线程
class Save2DB(Subroutine):
        pass # 太长省了....


#处理传过来的命令,
#解析出包放到 context.qDB 上
#指定要执行的DB操作
#必要的回包
#注:CER/CEA:心跳消息 CAR/CAA:告警消息 CSR/CSA:统计消息..
class PackageHandler:
        def __init__(self):
                _DEBUG('%s create package handler %d ', _cOdepOs(self), id(self))
                pass

        def __del__(self):
                _DEBUG('%s delete package handler %d.', _cOdepOs(self), id(self))
                pass
       
        def __repr__(self):
                cc = getattr(self,'context for client',None)#here maybe not set
                return '<PackageHandler(%d) for %s>'%(id(self),cc)

        def __ReplyPackage(self,nIndex,sNeId,sCmdCode,BodySize):
                cc = getattr(self,'context for client')
                sData = string.zfill(BodySize,7)
                sBuffer = cc.pkg.GetBodyStringByInfo(nIndex,sNeId,sCmdCode[:2]+'A',sData)
                _DEBUG('%s Send %s Data Package. INDEX=[%d],SIZE=[%d]', _cOdepOs(self), cc, nIndex, len(sData))
                if True:#cc.hSocket:
                        cc.qSend.put(sBuffer)
                        sBuffer = cc.sSend + sBuffer
                        pass
                return

        def __SavePackage(self,PackageVer,CreateTime,NeId,CmdCode,DataList):
                cc = getattr(self,'context for client')
                _DEBUG('%s save package[%s] to indb queue for %s, key=(%s)',_cOdepOs(self), CmdCode, cc,''.join(DataList[:3]))
                Result = 1
                #
                _INFO('put !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
                try:
                        #保存告警数据
                        if CmdCode == 'CAR' and len(DataList) > 6:
                                #AlarmType,NeId,TaskId,AlarmTime,AlarmCode,ResetFlag,DateList
                                #Result = DBInst.InsertAlarmEvent(DataList[0],DataList[1],DataList[2],DataList[3],DataList[4],DataList[5],DataList[6:])
                                context.qIndb.put(['InsertAlarmEvent',(CmdCode,DataList),(DataList[0],DataList[1],DataList[2],DataList[3],DataList[4],DataList[5],DataList[6:])])
                                pass

                        #保存统计数据
                        elif CmdCode == 'CSR' and len(DataList) > 6:
                                #StatType,NeId,TaskId,KpiTabId,StatTime,RowIndex,KpiValues
                                #STAT_FUNCTION|78|12|41|2010-04-11 17:39:52|44|5080|Liu.QiQuan|taskhost|0|10448896|"taskhost.exe"
                                if DataList[0].find('ATTR')>=0: sOpt = 'InsertStatAttrCDR'
                                else: sOpt = 'InsertStatCDR'
                                context.qIndb.put([sOpt,(CmdCode,DataList),(DataList[0],DataList[1],DataList[2],DataList[3],DataList[4],DataList[5],DataList[6:])])
                                pass

                        #保存心跳数据
                        elif CmdCode == 'CHR' and len(DataList) >= 3:
                                #Result = DBInst.UpdateNeHeart(DataList[1],DataList[2],CreateTime)
                                context.qIndb.put(['UpdateNeHeart',(CmdCode,DataList),(DataList[1],DataList[2],CreateTime)])
                                #_INFO('%s %s UpdateNeHeart(%s,%s,%s) =>',_cOdepOs(self), cc, DataList[1],DataList[2],CreateTime)
                                pass
                        else:
                                Result = 0
                                _WARN('%s find %s unkown CmdCode[%s]',_cOdepOs(self), cc, CmdCode)
                                pass
                        return Result
                except:
                        fp = StringIO.StringIO()
                        traceback.print_exc(file=fp)
                        message = fp.getvalue()
                        _ERROR('%s Save %s Database Error! ParamText=%s, Message=[%s]', _cOdepOs(self),cc,str(DataList),message)
                        return 0

        def __ProcessOnePackage(self,BodyIndex,PackageVer,CreateTime,NeID,CmdCode,BodyMsg):
                # #InstId = -1
                # #vData = BodyMsg.split('|')
                # #vData[-1] = vData[-1].replace('#13#10',os.linesep)
                if CmdCode in ['CAR','CSR','CHR','CER']:
                        #完成一次包的入库工作
                        # #nCount = self.__SavePackage(PackageVer,CreateTime,NeID,CmdCode,vData)
                        bOK,dEvent = _utils.set(BodyIndex,PackageVer,CreateTime,NeID,CmdCode,BodyMsg)
                        if bOK:
                                _LDEBUG('%s recv NE[%s] PKG[%s]',_cOdepOs(self),NeID,CmdCode)
                                context.qIndb.put(dEvent)
                                pass
                        else:
                                _WARN('%s error data : %s',_cOdepOs(self), dEvent)
                                pass
                        pass

                if CmdCode in ['CAR','CSR','CHR']:
                        #发送回复包
                        self.__ReplyPackage(BodyIndex,NeID,CmdCode,len(BodyMsg))
                        pass
                return 1

        def process(self):
                cc = getattr(self,'context for client')
                if cc.qRecv.qsize() == 0:
                        return
                sBuffer = cc.qRecv.get()
                cc.nTotal += self.__ProcessPackage(sBuffer)
                if cc.nTotal>=1000:
                        time.sleep(0.01)
                        cc.nTotal = 0
                        pass
                return

        def __ProcessPackage(self, sBuffer):
                cc = getattr(self,'context for client')
                try:
                        nPackage = 0
                        #合并上次的剩余包信息
                        sBuffer = cc.sLeft + sBuffer
                        cc.sLeft = ''

                        #初步判断是否合法
                        nBegin = sBuffer.find(cc.pkg.GetPackageName())
                        if nBegin > 0:
                                _WARN('%s Skip %s Package Head [%d] Char. PACKAGE_SIZE=[%d],PACKAGE_TEXT=[%s]',
                                        _cOdepOs(self),cc,nBegin,len(sBuffer),sBuffer)
                                sBuffer = sBuffer[nBegin:]
                                pass
                        elif nBegin==-1:
                                _WARN('%s Skip %s Package Buffer. PACKAGE_SIZE=[%d],PACKAGE_TEXT=[%s]',
                                        _cOdepOs(self),cc,len(sBuffer),sBuffer)
                                return nPackage

                        #如果不到一个包头,则等下一次的包
                        if cc.pkg.GetPackageHeadSize() >= len(sBuffer):
                                cc.sLeft = sBuffer
                                _DEBUG('%s Skip %s Package. PACKAGE_SIZE=%d,BUFFER_SIZE=%d,PACKAGE_TEXT=[%s]',
                                        _cOdepOs(self),cc,cc.pkg.GetPackageHeadSize(),len(sBuffer),sBuffer)
                                return nPackage

                        #解包信息
                        BodyIndex,BodySize,NeID,CmdCode,PackageVer,CreateTime,BodyMsg = cc.pkg.GetBodyInfoByString(sBuffer)
                        #如果最后一个包是半个包(有可能只有包头)
                        if BodySize > len(BodyMsg):
                                cc.sLeft = sBuffer
                                _DEBUG('%s Skip %s Package. PACKAGE_SIZE=%d,BODY_SIZE=%d,BODY_READ_SIZE=%d,PACKAGE_TEXT=[%s]',
                                        _cOdepOs(self),cc,len(sBuffer),BodySize,len(BodyMsg),cc.sLeft)
                                return nPackage

                        _DEBUG('%s %s PACKAGE RECV: %s',_cOdepOs(self),cc,cc.pkg)
                        #处理一个完整的包
                        if self.__ProcessOnePackage(BodyIndex,PackageVer,CreateTime,NeID,CmdCode,BodyMsg):
                                nPackage += 1
                                pass

                        if len(sBuffer)==cc.pkg.GetPackageHeadSize()+BodySize:
                                return nPackage

                        #计算出下一次包的内容
                        NextPackageBuffer = sBuffer[cc.pkg.GetPackageHeadSize()+BodySize:]
                        _DEBUG('%s %s Next Package. SIZE=%d,TEXT=[%s]',_cOdepOs(self),cc,len(NextPackageBuffer),NextPackageBuffer)

                        #如果下一次的包还可以解一次,则递归调用
                        if len(NextPackageBuffer) > cc.pkg.GetPackageHeadSize():
                                nPackage += self.__ProcessPackage(NextPackageBuffer)
                                pass
                        else:
                                cc.sLeft = NextPackageBuffer
                                pass
                        pass
                except:
                        fp = StringIO.StringIO()
                        traceback.print_exc(file=fp)
                        message = fp.getvalue()
                        _ERROR('%s Parse %s Package Error. Message = %s',_cOdepOs(self),cc,message)
                        pass
                return nPackage


#客户端socket请求收发处理
class RequestHandlerClass(SocketServer.BaseRequestHandler):
        def __init__(self, request, client_address, server):
                SocketServer.BaseRequestHandler.__init__(self, request,        client_address,        server)
                _DEBUG('%s create request handler=[%s:%d]',_cOdepOs(self),client_address[0],client_address[1])
                pass
        def __del__(self):
                _DEBUG('%s delete request handler=%d',_cOdepOs(self),id(self))
                pass
       
        def __repr__(self):
                try:
                        return '<RequestHandlerClass(%d) for (%s:%d>'%(self.client_address[0],self.client_address[1],id(self))
                except:
                        return '<RequestHandlerClass(%d)>'%id(self)
                return

        def __handle(self,cc):
                hSock = self.request
                if not cc.qSend.empty() or cc.sSend:
                        w = [hSock]
                        pass
                else:
                        w = []
                        pass
                ready_to_read, ready_to_write, in_error        = select.select([hSock], w, [hSock], 1)
                if in_error:
                        raise RuntimeError, 'socket error'
               
                if ready_to_read:
                        #读取客户端口的数据包.
                        sBuffer = hSock.recv(8*1024)
                        #没有数据,则客户端退出.
                        if not sBuffer:
                                _INFO('%s %s Is Disconnect.', _cOdepOs(self),cc)
                                return False
                        _DEBUG('%s Read %s Message. SIZE=%d',_cOdepOs(self), cc,len(sBuffer))
                        #发送消息给队列..
                        cc.qRecv.put(sBuffer)
                        setattr(self,'dead time',time.time()+10*60)
                        pass
               
                if ready_to_write:
                        if not cc.qSend.empty():
                                cc.sSend += cc.qSend.get()
                                pass
                        nCount = hSock.send(cc.sSend)
                        cc.sSend = cc.sSend[nCount:]
                        _DEBUG('%s Write %s Message. SIZE=%d',_cOdepOs(self), cc,nCount)
                        pass
                if getattr(self,'dead time',time.time()) < time.time():
                        _INFO('%s check socket dead %s',_cOdepOs(self), self)
                        return False
               
                getattr(self,'package hander').process()
                return True
       
        def setup(self):
                #创建client的上下文,和报文处理工具.
                cc = ClientContext(self.request,self.client_address)
                setattr(self,'context for client',cc)
                ph = PackageHandler()
                setattr(self,'package hander',ph)
                #交叉引用
                setattr(ph,'context for client',cc)
                setattr(cc,'package hander', ph)
                #加到全局上下文
                context.vClients.append(cc)
                _INFO('%s %s Connect. Total %d Clients.', _cOdepOs(self), cc, len(context.vClients))
                setattr(self,'dead time',time.time()+10*60)
                pass
       
        def handle(self):
                cc = getattr(self,'context for client')
                _DEBUG('%s begin request handler %s',_cOdepOs(self),cc)
                try:
                        while True:
                                if context.bStopThread:
                                        break
                                if context.server is None:
                                        _INFO('%s find server quit,so quit %s',_cOdepOs(self),cc)
                                        break
                                if not self.__handle(cc):
                                        break
                                continue
                        pass
                except:
                        fp = StringIO.StringIO()
                        traceback.print_exc(file=fp)
                        message = fp.getvalue()
                        _ERROR('%s Read Message Error. Message=%s',_cOdepOs(self),message)
                        pass
                _DEBUG('%s quit request handler',_cOdepOs(self))
                return

        def finish(self):
                assert(self.request is not None)
                #移除交叉引用列表.
                cc = getattr(self,'context for client')
                ph = getattr(cc,'package hander')
                setattr(cc,'package hander', None)
                setattr(ph,'context for client', None)
                for cc in context.vClients:
                        if cc.hSocket != self.request:
                                continue
                        context.vClients.remove(cc)
                        break
                try:
                        self.request.shutdown(2)
                        pass
                except:
                        pass
                try:
                        self.request.close()
                        pass
                except:
                        pass

                _DEBUG('%s Destory request handler for [%s:%s]', _cOdepOs(self),self.client_address[0],self.client_address[1])
                return

#==============================================================
#Function Name:Main
#
#==============================================================
#唯一的全局的实例
context = Context()

if __name__ == '__main__':
        try:
                AgentServer = MainThread()
                if AgentServer.Init(): AgentServer.Run()
                del AgentServer
        except SystemExit:
                pass
        except:
                fp = StringIO.StringIO()
                traceback.print_exc(file=fp)
                message = fp.getvalue()
                print message
else:
        pass

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP