首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我的c++中的http服务器没有正确地发回所有文件。

我的c++中的http服务器没有正确地发回所有文件。
EN

Stack Overflow用户
提问于 2009-11-28 03:09:46
回答 4查看 614关注 0票数 2

我在c++的一个超文本传输协议服务器上工作,现在它可以处理文本文件的请求,但当尝试获取jpeg或其他文件时,只发送了文件的一部分。问题似乎是,当我使用fgets( buffer,2000,returned_file)时,它似乎增加了文件位置指示器,而不是实际放入缓冲区。为什么会发生这种情况?我把我所有的代码放在下面。当响应码是200时,这个问题出现在while(true)循环中。感谢所有回复的人。

代码语言:javascript
复制
// Interpret the command line arguments
unsigned short port = 8080;

if ( (argc != 1) && (argc != 3) && (argc != 5) ) {
  cerr << "Usage: " << argv[0];
  cerr << " -p <port number> -d <base directory>" << endl;
  return 1;
}
else {
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "-p") == 0)
      port = (unsigned short) atoi(argv[++i]);
    else if (strcmp(argv[i], "-d") == 0)
      base_directory = argv[++i];
  }
}
// if base_directory was not given, set it to current working directory
if ( !base_directory ) {
  base_directory = getcwd(base_directory, 100);
}

// Create TCP socket
int tcp_sock = socket(AF_INET, SOCK_STREAM, 0);
if (tcp_sock < 0) {
  cerr << "Unable to create TCP socket." << endl;
  return 2;
}

// Create server socket
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons( port );
server.sin_addr.s_addr = INADDR_ANY;

// Bind the socket
if (bind(tcp_sock, (sockaddr*)&server, sizeof(server)) < 0) {
  cerr << "Unable to bind TCP socket." << endl;
  return 3;
}

// Listen for a connection request on TCP port
listen(tcp_sock, 5);

// Create HTTP_Request object and start a while loop of accepting connections
char buffer[2000];
int bytes_recv = 0;
int recv_len = 0;
string error_reply;

HTTP_Response* response;

while (true) {
  int acc_tcp_sock = accept(tcp_sock, NULL, NULL);
  if (acc_tcp_sock == -1) {
    cerr << "Unable to open TCP connection with client." << endl;
  }
  do {
    // may want to do just one recv
    recv_len = recv( acc_tcp_sock, buffer + bytes_recv,
      2000 - bytes_recv, 0 );
    bytes_recv += recv_len;
  } while (false);
  bytes_recv = 0;
  // may want to see if this causes a memory leak
  HTTP_Request* request = HTTP_Request::Parse(buffer, 2000);

  response = handle_request(request); // function to handle the request

  // Put response header into buffer
  response->Print( buffer, 2000 );

  // if 200 and GET then send header with file
  if ( response->Get_code() == 200 ) {
    // send response header
    if ( send( acc_tcp_sock, buffer, strlen(buffer), 0 ) < 0 ) {
      cerr << "Unable to send response header to client." << endl;
    }
    if ( method == "GET" ) {
      // send file
      while ( true ) {
        fgets( buffer, 2000, returned_file );
        if ( feof( returned_file ) ) break;
        if ( send( acc_tcp_sock, buffer, strlen(buffer), 0 ) < 0 ) {
          cerr << "Unable to send file in response to client." << endl;
        }
      }
    }
    fclose( returned_file ); // close file
  }
  else {
    if ( method == "GET" ) {
      error_reply = buffer + error_page;
      if ( send( acc_tcp_sock, error_reply.c_str(), error_reply.length(), 0 ) < 0 ) {
        cerr << "Unable to send response to client." << endl;
      }
    }
    else {
      if ( send( acc_tcp_sock, buffer, strlen(buffer), 0 ) < 0 ) {
        cerr << "Unable to send respone header to client." << endl;
      }
    }
  }

  close( acc_tcp_sock ); // close the connection
}

return 0;
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-11-28 03:16:16

不要使用fgets()来读取需要逐位保存的二进制数据。您不需要记录分隔符转换,如果您以这种方式阅读,某些系统可能会假设它是文本。在这个问题上,换行符和记录分隔符是完全没有意义的,所以fgets()的扫描它们的函数充其量是一个令人困惑的低效,在最坏的情况下根本就不是二进制的。

使用fread(3),或者更好的方法是使用原始系统调用(Posix API,在非Unix上) read(2)。这将读取一定数量的逐位数据,并告诉您它读取了多少。(关于使用哪种二进制能力的API :通常,建议我们缓冲数据,因为我们通常以行等小单元来处理数据。然而,当把整个文件从一个地方移到另一个地方时,缓冲只会减慢你的速度。在这种情况下,只使用read()会更简单、更快。)

你也不能strlen()二进制数据。您只需使用API调用中的字节计数。

票数 6
EN

Stack Overflow用户

发布于 2009-11-28 03:15:36

不会在二进制文件上使用strlen break吗?

代码语言:javascript
复制
send( acc_tcp_sock, buffer, strlen(buffer), 0 )
票数 5
EN

Stack Overflow用户

发布于 2009-11-28 03:17:35

您的二进制文件很可能包含空字节('\0')。当您使用fgets读取数据时,数据可能会被放入缓冲区,但是当您传输数据时,\0丢失之后的所有内容都会丢失(您的strlen调用可以确保这一点)。

因此,您需要使用fread读取数据。它返回实际读取的字节数,所以根本不需要使用strlen。别忘了以二进制模式打开文件!

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1810277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档