文件传输服务器(43)

来源:互联网 发布:淘宝一百多的狩猎者 编辑:程序博客网 时间:2024/06/10 02:55

文件传输(MuduoManual.pdf P57)
examples/filetransfer/download.cc
examples/filetransfer/download2.cc
examples/filetransfer/download3.cc

tests/Filetransfer_test.cc





单线程模式之一次性发完一个文件

#include <muduo/base/Logging.h>#include <muduo/net/EventLoop.h>#include <muduo/net/TcpServer.h>#include <stdio.h>using namespace muduo;using namespace muduo::net;const char* g_file = NULL;// FIXME: use FileUtil::readFile()string readFile(const char* filename){  string content;  FILE* fp = ::fopen(filename, "rb");  if (fp)  {    // inefficient!!!    const int kBufSize = 1024*1024;    char iobuf[kBufSize];    ::setbuffer(fp, iobuf, sizeof iobuf);    char buf[kBufSize];    size_t nread = 0;    while ( (nread = ::fread(buf, 1, sizeof buf, fp)) > 0)    {      content.append(buf, nread);    }    ::fclose(fp);  }  return content;}void onHighWaterMark(const TcpConnectionPtr& conn, size_t len){  LOG_INFO << "HighWaterMark " << len;}void onConnection(const TcpConnectionPtr& conn){  LOG_INFO << "FileServer - " << conn->peerAddress().toIpPort() << " -> "           << conn->localAddress().toIpPort() << " is "           << (conn->connected() ? "UP" : "DOWN");  if (conn->connected())  {    LOG_INFO << "FileServer - Sending file " << g_file             << " to " << conn->peerAddress().toIpPort();    conn->setHighWaterMarkCallback(onHighWaterMark, 64*1024);    string fileContent = readFile(g_file);    conn->send(fileContent);    conn->shutdown();    LOG_INFO << "FileServer - done";  }}int main(int argc, char* argv[]){  LOG_INFO << "pid = " << getpid();  if (argc > 1)  {    g_file = argv[1];    EventLoop loop;    InetAddress listenAddr(2021);    TcpServer server(&loop, listenAddr, "FileServer");    server.setConnectionCallback(onConnection);    server.start();    loop.loop();  }  else  {    fprintf(stderr, "Usage: %s file_for_downloading\n", argv[0]);  }}


单线程模型之分块发送文件

#include <muduo/base/Logging.h>#include <muduo/net/EventLoop.h>#include <muduo/net/TcpServer.h>#include <stdio.h>using namespace muduo;using namespace muduo::net;void onHighWaterMark(const TcpConnectionPtr& conn, size_t len){  LOG_INFO << "HighWaterMark " << len;}const int kBufSize = 64*1024;const char* g_file = NULL;void onConnection(const TcpConnectionPtr& conn){  LOG_INFO << "FileServer - " << conn->peerAddress().toIpPort() << " -> "           << conn->localAddress().toIpPort() << " is "           << (conn->connected() ? "UP" : "DOWN");  if (conn->connected())  {    LOG_INFO << "FileServer - Sending file " << g_file             << " to " << conn->peerAddress().toIpPort();    /*高水位标志的回调函数*/    conn->setHighWaterMarkCallback(onHighWaterMark, kBufSize+1);    FILE* fp = ::fopen(g_file, "rb");    if (fp)    {    /*设置conn 的上下文*/      conn->setContext(fp);      char buf[kBufSize];      size_t nread = ::fread(buf, 1, sizeof buf, fp);      conn->send(buf, nread);    }    /*发送完毕就shutdown connection*/    else    {      conn->shutdown();      LOG_INFO << "FileServer - no such file";    }  }  /*如果连接关闭,那么就关闭文件指针*/  else  {    if (!conn->getContext().empty())    {      FILE* fp = boost::any_cast<FILE*>(conn->getContext());      if (fp)      {        ::fclose(fp);      }    }  }}/*如果发完一块,还有其他块,那么接着发送,这只fp是保存在connection的上下文中,所以是同一个文件指针*/void onWriteComplete(const TcpConnectionPtr& conn){  FILE* fp = boost::any_cast<FILE*>(conn->getContext());  char buf[kBufSize];  size_t nread = ::fread(buf, 1, sizeof buf, fp);  if (nread > 0)  {    conn->send(buf, nread);  }  /*如果发完也关闭掉*/  else  {    ::fclose(fp);    fp = NULL;    conn->setContext(fp);    conn->shutdown();    LOG_INFO << "FileServer - done";  }}int main(int argc, char* argv[]){  LOG_INFO << "pid = " << getpid();  if (argc > 1)  {    g_file = argv[1];    EventLoop loop;    InetAddress listenAddr(2021);    TcpServer server(&loop, listenAddr, "FileServer");    server.setConnectionCallback(onConnection);    server.setWriteCompleteCallback(onWriteComplete);    server.start();    loop.loop();  }  else  {    fprintf(stderr, "Usage: %s file_for_downloading\n", argv[0]);  }}


单线程模型之分块发送(智能指针)

#include <muduo/base/Logging.h>#include <muduo/net/EventLoop.h>#include <muduo/net/TcpServer.h>#include <boost/shared_ptr.hpp>#include <stdio.h>using namespace muduo;using namespace muduo::net;/*这个程序和第二个是一样,只是这里的文件指针是智能共享的,不用我们手动关闭*/void onHighWaterMark(const TcpConnectionPtr& conn, size_t len){  LOG_INFO << "HighWaterMark " << len;}const int kBufSize = 64*1024;const char* g_file = NULL;typedef boost::shared_ptr<FILE> FilePtr;void onConnection(const TcpConnectionPtr& conn){  LOG_INFO << "FileServer - " << conn->peerAddress().toIpPort() << " -> "           << conn->localAddress().toIpPort() << " is "           << (conn->connected() ? "UP" : "DOWN");  if (conn->connected())  {    LOG_INFO << "FileServer - Sending file " << g_file             << " to " << conn->peerAddress().toIpPort();    conn->setHighWaterMarkCallback(onHighWaterMark, kBufSize+1);    FILE* fp = ::fopen(g_file, "rb");    if (fp)    {    /*这里ctx接受两个参数,因为ctx不是类的指针,所以他不是调用delete    来消费ctx指针,而是调用fclose这个函数来消费这个ctx指针*/      FilePtr ctx(fp, ::fclose);      conn->setContext(ctx);      char buf[kBufSize];      size_t nread = ::fread(buf, 1, sizeof buf, fp);      conn->send(buf, nread);    }    else    {      conn->shutdown();      LOG_INFO << "FileServer - no such file";    }  }}void onWriteComplete(const TcpConnectionPtr& conn){  const FilePtr& fp = boost::any_cast<const FilePtr&>(conn->getContext());  char buf[kBufSize];  size_t nread = ::fread(buf, 1, sizeof buf, get_pointer(fp));  if (nread > 0)  {    conn->send(buf, nread);  }  else  {    conn->shutdown();    LOG_INFO << "FileServer - done";  }}int main(int argc, char* argv[]){  LOG_INFO << "pid = " << getpid();  if (argc > 1)  {    g_file = argv[1];    EventLoop loop;    InetAddress listenAddr(2021);    TcpServer server(&loop, listenAddr, "FileServer");    server.setConnectionCallback(onConnection);    server.setWriteCompleteCallback(onWriteComplete);    server.start();    loop.loop();  }  else  {    fprintf(stderr, "Usage: %s file_for_downloading\n", argv[0]);  }}



原创粉丝点击