您的位置:首页 > 其它

开个帖子随时记录下进度什么什么的吧,很无聊的一个随笔

2013-12-16 23:24 302 查看
今晚大致搞通了recv函数的原理了,反正目前为止就知道它默认的话,其实应该是socket里面设置的默认值,最大可以一次接受32k的数据,然后最后那个flag参数不会影响大文件分段读取的性质,反正我这里用了一个1G的文件作为测试,当然这个文件是我自己生成的,每1k数据都是不同的,然后我就接受个4次,看了下,ok的,表明用一个循环来接受就可以,虽然这个不是什么长久之计,但是好歹我也是搞明白了它的返回值和函数性质了,返回值就是这一次recv的过程读取了多少个字符,用个if来判断吧,跟缓冲区的大小作比较,就知道发送端是否还有需要接受的数据了:

const int big_size = 1024;
char* for_recv = new char[big_size];

int per_receive = 0;
int tmp_count = 0;
for(;;)
{
per_receive = recv(socket.native_handle(), for_recv, big_size, 0);
if (per_receive < big_size)
{
cout << "Time to finish!\nper_receive:" << per_receive << endl;
output_for_trans.write(for_recv, per_receive);
break;
}

output_for_trans.write(for_recv, big_size);
output_for_trans.flush();
cout << "\nNow turn to next time's receive!\n";

tmp_count++;
if (tmp_count == 4)
break;
}

output_for_trans.close();

delete []for_recv;


对了,这里记得delete掉自己new出来的指针,也就是堆空间。

Over,12.16

这里是12。20号的晚上的八点钟,哎,我不能这么懒了

好吧,正题,今天下午终于搞懂了transmit file的和recv函数的有关事情,呵呵,其实没那么难发现的,虽然现在原理我也不是很懂,但是如果几天前测试的时候多测几步详细点,我就会早早知道答案了,其实也不需要弄懂什么,现在知道是这样工作的了,就可以根据我自己的需求来设定缓冲区的大小了,至少能根据机器的表现来调整吧!

是这样的,首先贴代码片段:

//Size per line is : 64B
const int big_size = 65536 + 65536/2;
char* for_recv = new char[big_size];

int per_receive = 0;
int tmp_count = 0;
for(;;)
{

per_receive = recv(boost_socket.native_handle(), for_recv, big_size, 0);
//                 if (per_receive < big_size)
//                 {
//                     cout << "Time to finish!\nper_receive: " << per_receive << endl;
//                     output_for_trans.write(for_recv, per_receive);
//                     break;
//                 }

output_for_trans.write(for_recv, big_size);
output_for_trans.flush();

cout << "Time to finish!\nper_receive: " << per_receive << endl;
cout << "Identify the first letter of the buffer: " << for_recv[0] << endl;
cout << "Now turn to next time's receive!\n\n";

int for_pause = 0;
cin >> for_pause;

tmp_count++;
if (tmp_count == 4)

break;
}

output_for_trans.close();

delete []for_recv;

cout << "\nIt's done just check it out!\n";
cin >> forcin;


发送端就没什么好说的了,直接一个transmit_file函数,

transmit_file(socket_, file_,
boost::bind(&connection::handle_write, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));

然后这里上面的代码,我就是想知道它每次到底是发送了多少我可以每次接受多少是不是socket的buffer是可以设置的而且是不是要调用native handler来设置之类的,然后首先要说明一样东西:第一次总会只接收到32k的数据,我这里说的是最大,很奇怪的,比如我这里把接收的buffer的size也就是代码里面的big size调成了各种比较大的数字,因为实验的文本一行是64B。然后奇妙的事情发生了,比如我buffer调整成64k,那么它第一次接收32k,第二次第三次第四次就会开始正常接收64k了,再次调大缓冲区也是如此,然后缓冲区的工作原理我也通过改文本的每行内容来观测了,反正就是每一次调用recv的时候,就重新把缓冲区重写一遍,所以在第一次的时候,比如缓冲区是64k,那么第一次写到文本里面的内容其实就是32k的有效内容加上32k的“屯屯屯。。。。。”,额……

然后下一次再条用的时候,就会接着从上次从发送发的全部内容读到哪里了就接着从哪里取64k出来填充满整个缓冲区,比如我的文本呢是32k的a b两段交替的,那么第二次读入缓冲区的就会是b,a,所以有必要先获取每次要写入的内容的总大小是多少的,然后再一段段写入,然后再累加,直到刚好等于原本发送方想要写入的文件的原始大小为止。

以上写于12月20日晚

----------------------------------------------------------

好吧,昨天开年会偷了两个号码到最后就连中了两个杯子我真是悲剧王然后特等奖被身后的一个声音很嗲但是很明显嗲的效果跟我的志玲姐姐差了十万八千里的一个女生给领走了,哎算了吧回来就继续调了下代码结果又发现了些好搞笑的事情,其实也就是上面那一段说到的缓冲区的问题,我在把测试的代码片段写到正式的工程里面的时候把在另一篇文章提到的限定socket的buffer大小的那两行给删掉了,结果就很神奇的东西出现了,这家伙第一次接收的时候还是32k的很正常,然后到后面就完全随机了,有时是21k,有时是22k,有时就64k,总之要把那两行代码给加上它就老老实实地每次接受64k了,反正就这样吧。

不过到底哪种方式更快我还是不得而知,应该是说,内存的占用大小跟最终的提速到底成不成正比,现在我自己还不得而知。

以上写于12.21日晚

-------------------------------------------------------------------

12.22 5pm

现在差不多了,在服务端已经完全写好了handle post 和get请求的所有流程和代码,然后处理post请求的话,server这边的话获取了客户端的请求之后先写一个faked reply,反正这个也没什么用的唯一的用处就是给客户端一个ack吧,然后客户端收到了个response之后也就收到了不会拿这个东西干嘛的,然后就开始用transmitfile,这些都是正常的但是不知道为什么我总是不够专心所以今天搞了那么久,反正好像比昨天的效率又好了点就继续努力吧,哎

好了,现在就想想怎么改改客户端,不应该说改,应该说规范下客户端的时候吧,因为刚才在跑一趟测试的时候就发现问题了,只有第一次发送的32k是能能够被接受到的,后面的就没了,为什么呢?用屁股想想就知道了,transmitfile里面用到的socket和random access file handler都是临时对象,我应该要规范下客户端的代码使得像server端那样,有个connection的类然后这些对象就能一直存活了。好吧先吃饭了。

左思右想,想偷懒在原本的代码基础上来增加个client类然后再把关键的东西弄成智能指针防止对象生命周期结束什么的,然后发现这样偷懒一时的话可能会给我将来的拓展带来巨大的麻烦,想想还是不能偷懒了,而且现在客户端的代码还是无端端地搞了个io_service_pool在里面本来这就很不符合常理啊,最直观也是最容易修改的代码结构就是用boost的智能指针管理的多线程,每个线程开启后就会生成一个client的对象这个对象会执行它的读写任务,这样吧,改吧,哎。挫逼的人啊。

--------------------------------------------------------------------------

哎,下午刚刚把整理好的client测试通过后,添加下多线程来测试,然后怎么又是那个很恶心的说不能实例化什么私有变量的问题其实这个问题就是io_service的传递出现了非法的情况好吧我是不太掌握得好为什么例程可以我就不可以但是我现在是真的不想再测试了打算明天早上再搞了现在连符号都懒得再打更何况一行行的代码一次次的调试呢哎半夜还是起来赚个几十块吧人穷就是这个吊样的了

希望明天可以多点进度,把那个问题给搞定吧,看在我这行字回复了符号。

晚安。

以上写于12.23晚上23:12

---------------------------------------------------------------------------

睡醒了一觉之后突然果然忽然不出奇然地恍然大悟,原来是这里除了问题啊,是vector啊!不是因为传用io_service的引用当参数啊!因为vector把对象push back进去的时候在内部做了一个复制啊,管他是深还是浅,反正io service就是noncopyable的,所以才会报错!

//Creat some io_service
for (int i = 0; i < THREAD_POOL_SIZE; i++)
{
io_service_ptr io_ptr(new boost::asio::io_service);
io_service_pool.push_back(io_ptr);
}

//Creat some different clients
client new_client_1(get_next_io_service(), next_io_service);
client new_client_2(get_next_io_service(), next_io_service);

client new_client_3(get_next_io_service(), next_io_service);
client new_client_4(get_next_io_service(), next_io_service);

vector<client> clients;
//     clients.push_back(new_client_1);
//     clients.push_back(new_client_2);
//     clients.push_back(new_client_3);
//     clients.push_back(new_client_4);


解决方法当然就是用boost的智能指针来包装一下,就可以了,当然要记得先在client.h里面,在client的类声明之后,添加一个:

typedef boost::shared_ptr<client> client_ptr 来告诉系统,我有这么一个client类型的智能指针

//Creat some io_service
for (int i = 0; i < THREAD_POOL_SIZE; i++)
{
io_service_ptr io_ptr(new boost::asio::io_service);
io_service_pool.push_back(io_ptr);
}

//Creat some different clients

vector<client_ptr> clients;
for (int i = 0; i < CLIENT_POOL_SIZE; i++)
{
client_ptr new_client(new client(get_next_io_service(), next_io_service));
clients.push_back(new_client);
}

//Launch the request method of client
for (int thread_id = 0; thread_id < CLIENT_POOL_SIZE; thread_id ++)
{
cout << "Now Thread:" << thread_id << "is about to be executed...\n";
if (thread_id%2 == 0)
{
boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&client::launch_client, clients[thread_id], GET_REQUEST, thread_id)));
thread_pool.push_back(thread);
}

else
{
boost::shared_ptr<boost::thread> thread(new boost::thread(boost::bind(&client::launch_client, clients[thread_id], POST_REQUEST, thread_id)));
thread_pool.push_back(thread);
}
}


以上这样就妥妥的ok了,,记得在bind函数里面要改一下,因为现在是指针,所以直接传指针就可以了,之前传的是对象的引用,其实一个意思,因为引用就是那个对象的地址,现在指针指向的就是那个地址,所以就去掉引用符号就可以了。嗯嗯,还要注意一下shared ptr的声明方式,老是忘记。

好吧,这个小问题算解决了,这篇太长了,另外开一篇吧,刚刚用四个客户端来跑了一篇,发现读写文件的时候有点问题,我是故意让两个client分别执行两个一样的操作针对同一个文件的,其实post request的两个client都妥妥的没问题,因为就是这两个client同时打开同一个文件然后transmit给server端这个是没有问题的生成的文件很正常,anyway,新开一篇吧

平安夜快乐,@ Lab
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐