2012-06-26 2 views
5

소켓에서 read()를 사용하여 데이터를 읽고받는 버퍼를 파일 (ofstream) 또는 이와 유사한 자체 확장 객체로 만드는 C/C++ 방법이 있습니까? (벡터 예)?소켓에서 오브 스트림으로 C++ 읽기() -

EDIT : 내가 10000 바이트 파일의 내용을 수신 할 수있는 스트림 소켓을 읽는 방법을 생각하면서 질문이 제기되었습니다. 난 단지 20000 또는 50000 바이트 (지금은 충분히 큰)를 파일에 임시 보관할 수있을 때까지 파일을 임시로 저장할 수있는 버퍼로 둡니다. 그냥 파일로 직접 스트리밍하지 않고 별표를 표시하는 것이 좋습니다.

많은 당신이 표준 내부의 문자 *에서 얻을 수 있습니다와 같은 : 문자열, 나는 그런

read(int fd, outFile.front(), std::npos); // npos = INT_MAX 

이나 뭐 같은 것을 생각했다.

최종 편집

감사합니다.

+1

예. 꽤 많은 사람들이 소켓에 연결하는 스트림 버퍼를 작성했습니다. 처음에는 시원하게 보였지만 적어도 실제로는 잘 작동하지 않았습니다. 제대로 작동하려면 일종의 비동기 작업 (예 : ASIO처럼)을 추가해야합니다. http://socketstream.sourceforge.net/, http://www.pcs.cnu.edu/~dgame/sockets/socketsC++//sockets.html 등 –

답변

4

이 단순하고, 내 손가락의 맨 위에 떨어져 있지만, 나는이 라인을 따라 뭔가가 해결 것이라고 생각 : 코멘트에

template <unsigned BUF_SIZE> 
struct Buffer { 
    char buf_[BUF_SIZE]; 
    int len_; 
    Buffer() : buf_(), len_(0) {} 
    int read (int fd) { 
     int r = read(fd, buf_ + len_, BUF_SIZE - len_); 
     if (r > 0) len_ += r; 
     return r; 
    } 
    int capacity() const { return BUF_SIZE - len_; } 
} 

template <unsigned BUF_SIZE> 
struct BufferStream { 
    typedef std::unique_ptr< Buffer<BUF_SIZE> > BufferPtr; 
    std::vector<BufferPtr> stream_; 
    BufferStream() : stream_(1, BufferPtr(new Buffer<BUF_SIZE>)) {} 
    int read (int fd) { 
     if ((*stream_.rbegin())->capacity() == 0) 
      stream_.push_back(BufferPtr(new Buffer<BUF_SIZE>)); 
     return (*stream_.rbegin())->read(fd); 
    } 
}; 

, 당신은 당신이 큰 문자 버퍼를 만들지 않도록하고 싶었다 언급했다. read 시스템 호출을 사용할 때 일반적으로 많은 작은 읽기 대신 몇 개의 큰 읽기를 수행하는 것이 더 효율적입니다. 따라서 대부분의 구현은 효율성을 높이기 위해 대형 입력 버퍼를 선택합니다.

std::vector<char> input; 
char in; 
int r; 
while ((r = read(fd, &in, 1)) == 1) input.push_back(in); 

그러나 시스템 호출과 입력의 모든 바이트에 대해 적어도 하나의 바이트가 복사됩니다. 대조적으로, 내가 추가 한 코드는 여분의 데이터 복사본을 피한다.

나는 당신이 채택 할 해결책이 될 코드를 정말로 기대하지 않습니다. 방금 공간과 시간면에서 효율적이었던 자체 확장 객체를 만드는 방법을 보여주는 그림을 제공하려고했습니다. 귀하의 목적에 따라, 그것을 확장하거나 자신의 글을 쓸 수도 있습니다. 내 머리 위로 떨어져, 일부 개선 될 수있다 :

  • 사용 std::list 대신,
  • 이 API를 항상 적어도 수 있도록
  • 사용 readv을 읽는 방법 바이트 지정하는 매개 변수를 허용 크기를 조정 벡터를 피하기 위해 BUF_SIZE 바이트 (또는 BUF_SIZE 바이트 이상)를 한 번에 읽을 수 있습니다.
+0

흥미 롭습니다. 내가 실제로했던 것은 큰 문자 버퍼를 선언 할 필요가없는 방법이었습니다. 그러나 struct Buffer {char buf_ [BUF_SIZE]; ... char 버퍼를 선언하고 있습니다. –

+1

@WesMiller :'read'는 버퍼를 넘겨 줄 필요가 있습니다. 그리고 여러분은 데이터를 self-extending 데이터 구조로 수집하기를 원합니다. 이것은'read'가 반환 된 후에 버퍼를 저장하는 것을 의미합니다. 사용자 공간 코드에서 버퍼를 실제로 만들지 않으려면 0 복사 의미 (커널에서 사용하는 네트워크 버퍼에 직접 액세스)로 사용자 고유의 네트워크 I/O 장치 드라이버를 만드는 것이 좋습니다. – jxh

+0

OK, 그렇게 멀리 가지 마십시오. 수신 된 데이터 스트림 (스트림 소켓)이 알려지지 않은 크기의 경우 자체 확장 객체를 고려했습니다. 위의 원래 게시물에서 편집 한 것처럼 알 수없는 크기의 파일을 받게 될 것이고 char 버퍼 [50000]가 "충분히 커"였으면 좋겠지 않기를 바랬습니다. 조만간에 보장되지 않습니다. –

0

boost::asio에서 스트림 지원을 살펴보십시오.

+2

"Thou shalt not Boost"- 관리. –