iTePub电子图书论坛 » 程序开发设计经验交流 » 转:TCP网络程序的基本框架

页: [1]

hawkguo05-12-25 10:58
转:TCP网络程序的基本框架

TCP网络程序的基本框架
这段时间看了不少网络程序的代码,也动手写了几个server/client.总结一下,大部分网络程序使用的是tcp,用udp只有3个理由,
1.允许一定的包丢失
2.需要做nat穿透
3.节省资源,如socket句柄.
   
     而大多数应用层通讯协议,特别是数据量传输比较大的,为了效率和可靠性都会采用tcp.而TCP是流结构,应此要考虑2种情况:
1.发送数据被阻塞
2.接受包不完整或者多余.
    虽然tcp是stream,但是为了解析网络数据都是基于二进制封包或者基于文本的token形式存在. 对二进制的封包来说,一般结构如下:
struct Pack
{
char magic_num;
char pack_type;
int size;
char *data;
};
因为这样的结构,网络程序想要防止抓包,破解基本上很难.网游外挂光靠技术手段是没有什么用的.
下面用python写了段伪码,无论是阻塞还是非阻塞,单线程还是多线程,基本上都应该采用如下的框架.  
class CSocket:
    BUF_SIZE=(1024*16)
    def __init__(self):
        self.revbuf=[]
        self.sedbuf=[]
        self.handle=0
     
    def handleError(self,e):
        print e
     
    def handleClose(self):
        pass
     
    def handleSend(self):
        try:
            send_bytes=self.handle.send(self.sedbuf)
            self.sedbuf=self.sedbuf[send_bytes:]
            #从buffer 中删除发送过的数据
        except Exception,e:
            self.handleError(e)
   

  def handleRecv(self):
        try:
            data = self.handle.recv(BUF_SIZE)
            if len(data)==0:
                self.handleClose()
                return
            else:
                self.revbuf.append(data)
            while self.revbuf:
                read_bytes,need_more = self.processPacket()
                 
                if need_more:
                    break #当前buffer中的数据不是一个完整的数据包
                else:
                    sef.revbuf=self.revbuf[read_bytes:]#从buffer中删掉解析过的数据
                     
        except  Exception,e:
            self.handleError(e)
     
    def processPacket(self):
        #解析封包,假设封包的魔法数是ox3a
        if self.revbuf[0]!=0x3a:
            return len(self.revbuf),True
            #错误的数据,丢弃整个buffer
        #advanced process.
        pass
         
    def Send(self,data):
        self.sedbuf.append(data)
        self.handleSend()
     
         需要说明的是:
1.Send可以显示的调用,但是recv则不行,你不能确定在什么时候能够收到,如果用轮询的方式,
        while RecvData():
                        sleep(100)
会把整个线程给"锁"住,除非你使用单独的线程来处理,比较合理的方法是使用non-blocking io,用select或者poll来管理socket句柄.当数据到来的时候,系统会发出通知.

2.在windows平台,如果你使用重叠IO,就不需要sendbuf,这样可以减少一次内存copy,
可以直接在栈里面定义一个buffer,扔给WSARecv,windows会替你管理这块内存.

sunmarcus06-6-30 07:15
你的题目也起的太大了点吧...

brucelut06-7-5 08:32
同一楼上的,呵呵,看了一下,原来是这样的。


查看完整版本: 转:TCP网络程序的基本框架


Powered by Discuz! Archiver 4.1.0  © 2001-2006 Comsenz Inc.
Processed in 0.036591 second(s), 2 queries