2012-06-26 37 views
5

Có cách C/C++ để đọc dữ liệu từ một socket bằng cách sử dụng read() và có bộ đệm nhận là một tệp (ofstream) hoặc một đối tượng tự mở rộng tương tự (ví dụ vectơ)?C++ đọc() - ing từ một socket đến một dòng

EDIT: Câu hỏi nảy sinh trong khi tôi dự tính cách đọc ổ cắm luồng có thể nhận nội dung của tệp 10000+ byte. Tôi chỉ không bao giờ làm như đặt 20000 hoặc 50000 byte (đủ lớn cho bây giờ) trên stack như một bộ đệm, nơi tập tin có thể được lưu trữ tạm thời cho đến khi tôi có thể dính vào một tập tin. Tại sao không chỉ truyền trực tiếp tệp đó vào tệp để gắn dấu sao.

Giống như bạn có thể có được ở các char * bên trong một std: string, tôi nghĩ đến một cái gì đó giống như

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

hoặc một cái gì đó như thế.

cuối chỉnh sửa

Cảm ơn.

+1

Có. Khá nhiều người đã viết bộ đệm luồng kết nối với ổ cắm. Trong khi ban đầu họ có vẻ mát mẻ, ít nhất là từ những gì tôi đã nhìn thấy, họ hiếm khi làm việc tốt trong thực tế. Bạn (gần như) cần phải thêm một số loại hoạt động không đồng bộ (ví dụ, như ASIO) để làm cho nó hoạt động tốt. http://socketstream.sourceforge.net/, http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.html, v.v. –

Trả lời

4

Đây là đơn giản, và ra khỏi đỉnh ngón tay của tôi, nhưng tôi nghĩ rằng một cái gì đó dọc theo những dòng sẽ làm việc ra:

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); 
    } 
}; 

Trong một bình luận, bạn nói bạn muốn tránh tạo ra một bộ đệm char lớn. Khi sử dụng cuộc gọi hệ thống read, thông thường sẽ hiệu quả hơn khi thực hiện một số lần đọc lớn thay vì nhiều lần đọc nhỏ. Vì vậy, hầu hết các triển khai sẽ lựa chọn không cho bộ đệm đầu vào lớn để đạt được hiệu quả đó. Bạn có thể triển khai một cái gì đó như:

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

Nhưng điều đó sẽ liên quan đến cuộc gọi hệ thống và ít nhất một byte được sao chép cho mỗi byte đầu vào. Ngược lại, mã tôi đưa ra tránh các bản sao dữ liệu thừa.

Tôi thực sự không mong đợi mã mà tôi đưa ra là giải pháp bạn sẽ áp dụng. Tôi chỉ muốn cung cấp cho bạn một minh họa về cách tạo ra một đối tượng tự mở rộng là khá không gian và thời gian hiệu quả. Tùy thuộc vào mục đích của bạn, bạn có thể muốn mở rộng nó hoặc viết của riêng bạn. Off đỉnh đầu của tôi, một số cải tiến có thể là:

  • sử dụng std::list thay vào đó, để tránh vector thay đổi kích thước
  • phép API một tham số để xác định có bao nhiêu byte để đọc
  • sử dụng readv luôn luôn cho phép ít nhất BUF_SIZE bytes (hoặc hơn BUF_SIZE bytes) để đọc tại một thời điểm
+0

Thú vị. Những gì tôi thực sự là sau khi một cách không phải tuyên bố một bộ đệm char lớn. Nhưng trong struct Buffer {char buf_ [BUF_SIZE]; ... bạn đang khai báo một bộ đệm char. –

+1

@WesMiller: 'read' cần được chuyển qua bộ đệm và bạn muốn dữ liệu được thu thập trong cấu trúc dữ liệu tự mở rộng, có nghĩa là lưu trữ bộ đệm sau khi' đọc' trả về. Nếu bạn thực sự muốn không có bộ đệm nào được tạo trong mã vùng người dùng, bạn đang xem xét việc tạo trình điều khiển thiết bị I/O mạng của riêng mình với ngữ nghĩa 0 bản sao (truy cập trực tiếp vào bộ đệm mạng được sử dụng bởi hạt nhân). – jxh

+0

OK, không đi xa đến vậy. Tôi dự tính đối tượng tự mở rộng cho các trường hợp mà luồng dữ liệu nhận được (đó là một ổ cắm luồng) có kích thước không xác định. Như đã chỉnh sửa trong bài đăng gốc ở trên, tôi sẽ nhận được một tệp có kích thước không xác định và hy vọng không phải hy vọng bộ đệm char [50000] là "đủ lớn". Đảm bảo không sớm hay muộn. –

0

Hãy xem hỗ trợ luồng trong boost::asio.

+2

"Thou shalt not Boost" - quản lý. –

Các vấn đề liên quan