2009-10-17 31 views

Respuesta

2

Pseudocódigo:

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

Algo por el estilo.

+0

Esto suele ser suficiente, pero a veces obtengo líneas realmente largas, y leer un carácter a la vez es demasiado lento. –

3

I está leyendo desde un socket TCP que no puede asumir cuando se llegue al final de la línea. Los antecedentes demuestran que necesitaré algo así:

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; 

Suponiendo que está usando "\ n \ n" como delimitador. (No probé ese fragmento de código ;-))

En un socket UDP, esa es otra historia. El emisor puede enviar un paquete que contenga una línea completa. El receptor está garantizado para recibir el paquet como una sola unidad. Si lo recibe, como UDP, por supuesto, no es tan confiable como TCP.

+0

Se trata de TCP, sí. El problema es que el socket es interactivo. Tengo que enviar una línea, luego obtengo algunas líneas. Puedo reconocer el final con double newline "\ n \ n". –

+0

... así que no puedo leer 1024 caracteres por adelantado porque puede que no haya tantos. man 2 read muestra que POSIX read tiene 3 argumentos, por lo que no sé a qué lectura te refieres. –

+0

como te dije que no lo probé. Solo escribo 'al vuelo'. El código es fácil de entender y adaptar. Por cierto, lo he actualizado para tener en cuenta los delimitadores de línea: "\ n \ n" –

0

Usando C++ biblioteca de sockets:

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

Y el uso de la clase anterior:

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

La librería se encarga de toda la gestión de errores.

Encuentra la biblioteca a través de Google o utilizar este enlace directo: http://www.alhem.net/Sockets/

2

que aquí hay una prueba, código muy eficiente:

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

También es útil para SIGPIPE señal de ajuste haciendo caso omiso de la lectura y la escritura (y manejar errores como se muestra arriba):

signal (SIGPIPE, SIG_IGN); 
Cuestiones relacionadas