Chinaunix首页 | 论坛 | 博客
  • 博客访问: 19253
  • 博文数量: 8
  • 博客积分: 190
  • 博客等级: 入伍新兵
  • 技术积分: 90
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-14 12:40
文章分类
文章存档

2012年(8)

我的朋友

分类: LINUX

2012-11-14 14:17:18

2. Download Server

 

这一节我们介绍一个多线程下载服务器.

1.服务器收到一个请求时,将该任务分配到某个线程,由该线程处理对应的请求.

2.某个线程收到RequestSize,返回协议指定file_name返回文件的大小给客户端(回复RespondSize协议).

3.某个线程收到RequestData请求时,按协议指定的数据偏移start_pos请求file_namesize大小的数据块返回给客户端(回复RespondData协议).

 

一、Download 线程及线程池

1. 用enetlib生成框架代码:

enetlib -m DownloadServer -main

生成了3个文件:

DownloadServer.cpp

DownloadServer.h

DownloadServerMain.cpp

ok, 我们的下载服务器完成了, 收工....开玩笑的, 还需要添加业务逻辑层代码呢:

 

二、 DownloadServer 线程

1. 实现创建协议族方法:

ProtocolFamily* DownloadServer::create_protocol_family()

{

       return new DownloadProtocolFamily;

}

void DownloadServer::delete_protocol_family(ProtocolFamily* protocol_family)

{

       delete protocol_family;

}

接下来当然是处理请求协议,来看看我们是如何做到的:当然是实现on_recv_protocol接口了.

2. 处理请求协议:

bool DownloadServer::on_recv_protocol(SocketHandle socket_handle, Protocol *protocol, bool &detach_protocol)

{

       DownloadProtocolFamily* protocol_family = (DownloadProtocolFamily*)get_protocol_family();

       DefaultProtocolHeader *header = (DefaultProtocolHeader *)protocol->get_protocol_header();

       switch(header->get_protocol_type())

       {

       case PROTOCOL_REQUEST_SIZE:

       {

              RequestSize *temp_protocol = (RequestSize*)protocol;

              const string file_name = temp_protocol->get_file_name();

              SLOG_INFO("receive ", file_name.c_str());

 

              string path="/data/";

              path += file_name;

 

              //get file size

              unsigned long long file_size=0;

              FILE *fp = fopen(path.c_str(), "r");

              if(fp != NULL)

              {

                     fseek(fp, 0, SEEK_END);

                     file_size = ftell(fp);

                     fseek(fp, 0, SEEK_SET);

                     fclose(fp);

              }

 

              RespondSize* resp_protocol = (RespondSize*)protocol_family->create_protocol(PROTOCOL_RESPOND_SIZE);

              if(resp_protocol)

              {

                     resp_protocol->assign(file_name, file_size);

                     send_protocol(socket_handle, resp_protocol);

              }

              else

                     SLOG_ERROR("create RespondSize protocol failed.");

 

              break;

       }

       case PROTOCOL_REQUEST_DATA:

       {

              RequestData *temp_protocol = (RequestData*)protocol;

              const string file_name = temp_protocol->get_file_name();

              unsigned long long start_pos = temp_protocol->get_start_pos();

              unsigned int size = temp_protocol->get_size();

              SLOG_INFO("receive ld, size=%d>", file_name.c_str(), start_pos, size);

 

              string path="/data/";

              path += file_name;

              FILE *fp = fopen(path.c_str(), "r");

              if(fp != NULL)

              {

                     RespondData* resp_protocol = (RespondData*)protocol_family->create_protocol(PROTOCOL_RESPOND_DATA);

                     resp_protocol->assign(file_name, start_pos, size);

 

                     DefaultProtocolHeader *header = (DefaultProtocolHeader *)resp_protocol->get_protocol_header();

                     int header_length = header->get_header_length();

                     ByteBuffer *byte_buffer = new ByteBuffer;

                     //1. 预留协议头空间

                     byte_buffer->get_append_buffer(header_length);

                     byte_buffer->set_append_size(header_length);

                     //2. 编码协议体数据

                     resp_protocol->encode_body(byte_buffer);

                     //3. 添加数据

                     char *data_buffer = byte_buffer->get_append_buffer(size);

                     fseek(fp, start_pos, SEEK_SET);

                     fread(data_buffer, 1, size, fp);

                     fclose(fp);

                     byte_buffer->set_append_size(size);

                     //4. 编码协议头

                     int body_length = byte_buffer->size()-header_length;

                     char *header_buffer = byte_buffer->get_data(0, header_length);

                     header->encode(header_buffer, body_length);

                     //5. 发送协议

                     resp_protocol->attach_raw_data(byte_buffer);

                     send_protocol(socket_handle, resp_protocol);

              }

              else

              {

                     SLOG_ERROR("can't open file=%s", file_name.c_str());

              }

              break;

       }

       default:

              SLOG_WARN("receive undefine protocol. ignore it.");

              return false;

       }

 

       return true;

}

 

 

,到现在我们的下载服务器完成了.收工,洗洗睡了... ,忘记还有客户端的代码,顺便提供一下,嘿嘿...

阅读(320) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~