IOCP网络包重组问题

来源:互联网 发布:淘宝裙子桑蚕丝 编辑:程序博客网 时间:2024/05/23 05:09

     目前,IOCP已经广泛用于网络程序设计了,由于IOCP基本多线程对网络数据进行接收,因为数据包的重组往往成功程序员处理IOCP最难做的事情, 近来在做相交的项目,也颇费了一番心思,现把我的处理方法写下来。

     由于TCP连接传输数据会把数据包是流的方式进行,因为,我们在客户端接收数据时,每次recv函数结束得到的并不一定是我们以前每次调用send函数所发送的完整数据,但TCP传输数据的顺序是不会变的。根据这两个性质,我们需要做以下事情,

  一、因为TCP不是分包传输,所以我们需要自己构造数据包头来标识数据的起始位置和数据包的大小;

  二、由于数据传输的顺序是不变的,因此,只要我们保证接收时接收数据的顺序不变,再根据数据包头中的标志和数据数据包的大小就肯定能确定一个完整的数据包。

  因此,我们需要先设计自己的数据包头,这个没有什么说的,第二件事,保证数据接收的顺序不变比较麻烦,因为有多个线程进行数据的接收,要保证顺序性,我们就要对多个线程进行互斥操作,保证某一连接不能同时有多个线程进行数据的接收,为了兼顾效率,我们也应保证在数据接收操作完成后,应立刻允许其它线程对此连接进行数据的接收操作。

  保证一个连接同时只有一个线程接收,我们可以只对一个连接投递一个接收请求,当有数据到来时,启动一个线程进行接收数据,此时,此连接已经没有别的接收请求了,所以就是有数据到达时,也不会启动别的线程在此连接上接收数据,当接收数据的线程完成操作时,再投递接收数据的请求,就可以允许别的线程在连此连接上接收数据了,这样我们就保证了一个连接上接收数据操作的互斥性。

  为了尽快让其它线程对此连接进行数据,我对每个连接都建立一个临时数据的缓冲区和一个变量,指向此缓冲区中数据的长度,当有数据接收后,先放入此缓冲区中数据的后面,然后判断是否有一个完整的数据包(根据数据包头和数据包的长度),如果是完整的数据包,则所有完整的数据从此缓冲区移出,同时调整变量为移后数据的长度,这时便可以投递接收请求,让别的线程进行数据的接收工作,而当前线程可以根据需要处理移出来的数据包。

  由于一个线程从接收数据到投递接收请求这段时间,所处理的操作比较少(就接收数据,移去完整的数据包),所以效率上是可以保证的。而且其中不会有可能使线程挂起或睡眠的操作,所以一般情况下不会产出线程的切换,不会产生额外的开销。下面是数据接收流程图,这个流程图中画的比较多,还把线程移走完整数据后所做的别的操作都画了出来。

 

  

原创粉丝点击