Как считать точно одну строку?

Если это имеет значение значение, для которого стандарта ++ постепенное увеличение прекращает функционировать, 9,007,199,254,740,992.

6
задан Łukasz Lew 17 October 2009 в 22:15
поделиться

4 ответа

Если вы читаете из TCP-сокета, вы не можете предположить, когда будет достигнут конец строки. Поэтому вам понадобится что-то вроде этого:

std::string line;
char buf[1024];
int n = 0;
while(n = read(fd, buf, 1024))
{
   const int pos = std::find(buf, buf + n, '\n')
   if(pos != std::string::npos)
   {
       if (pos < 1024-1 && buf[pos + 1] == '\n')
          break;
   }
   line += buf;
}

line += buf;

Предполагая, что вы используете "\ n \ n" в качестве разделителя. (Я не тестировал этот фрагмент кода ;-))

С UDP-сокетом это совсем другая история. Эмитент может отправить пакет, содержащий целую строку. Получатель гарантированно получит пакет как единое целое. Если он его получит, UDP, конечно, не так надежен, как TCP.

3
ответ дан 17 December 2019 в 00:11
поделиться

Псевдокод:

char newline = '\n';
file fd;
initialize(fd);
string line;
char c;
while( newline != (c = readchar(fd)) ) {
 line.append(c);
}

Что-то вроде этого.

2
ответ дан 17 December 2019 в 00:11
поделиться

Вот протестированный, довольно эффективный код:

bool ReadLine (int fd, string* line) {
  // We read-ahead, so we store in static buffer 
  // what we already read, but not yet returned by ReadLine.
  static string buffer; 

  // Do the real reading from fd until buffer has '\n'.
  string::iterator pos;
  while ((pos = find (buffer.begin(), buffer.end(), '\n')) == buffer.end ()) {
    char buf [1025];
    int n = read (fd, buf, 1024);
    if (n == -1) {    // handle errors
      *line = buffer;
      buffer = "";
      return false;
    }
    buf [n] = 0;
    buffer += buf;
  }

  // Split the buffer around '\n' found and return first part.
  *line = string (buffer.begin(), pos);
  buffer = string (pos + 1, buffer.end());
  return true;
}

Также полезно настроить игнорирование сигнала SIGPIPE при чтении и записи (и обрабатывать ошибки, как показано выше):

signal (SIGPIPE, SIG_IGN);
2
ответ дан 17 December 2019 в 00:11
поделиться

Использование библиотеки сокетов C ++:

class LineSocket : public TcpSocket
{
public:
  LineSocket(ISocketHandler& h) : TcpSocket(h) {
    SetLineProtocol(); // enable OnLine callback
  }
  void OnLine(const std::string& line) {
    std::cout << "Received line: " << line << std::endl;
    // send reply here
    {
      Send( "Reply\n" );
    }
  }
};

И использование вышеуказанного класса:

int main()
{
  try
  {
    SocketHandler h;
    LineSocket sock(h);
    sock.Open( "remote.host.com", port );
    h.Add(&sock);
    while (h.GetCount())
    {
      h.Select();
    }
  }
  catch (const Exception& e)
  {
    std::cerr << e.ToString() << std::endl;
  }
}

Библиотека берет на себя всю обработку ошибок.

Найдите библиотеку с помощью Google или воспользуйтесь этой прямой ссылкой: http://www.alhem.net/Sockets/

0
ответ дан 17 December 2019 в 00:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: