您的位置:首页 > 理论基础 > 计算机网络

TCP网络程序的基本框架

2005-12-25 16:13 351 查看
这段时间看了不少网络程序的代码,也动手写了几个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会替你管理这块内存.
------------------------------------------------------------------------------------------------------------
题外话:dudu能不能修改一下编辑器,支持wiki类似的语法,这样编辑,排版简单有效,现在这个不太好用,经常要去手工改html标签.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: