2009-10-17 16 views

risposta

2

Pseudocodice:

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

Qualcosa del genere.

+0

Questo è in genere abbastanza buono, ma a volte ottengo linee veramente lunghe e la lettura di un carattere alla volta è troppo lenta. –

3

Si sta leggendo da un socket TCP che non si può assumere quando verrà raggiunta la fine della linea. Therfore avrete bisogno di qualcosa di simile:

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; 

Supponendo che si sta utilizzando "\ n \ n" come delimitatore. (Non ho provato quello snippet di codice ;-))

Su una presa UDP, questa è un'altra storia. L'emettitore può inviare un paquet contenente un'intera riga. Il ricevitore è garantito per ricevere il paquet come singola unità. Se lo riceve, come UDP non è affidabile come TCP, naturalmente.

+0

Riguarda il TCP, sì. Il problema è che il socket è interattivo. Devo inviare una riga, poi ottengo poche righe. Posso riconoscere la fine con double newline "\ n \ n". –

+0

... quindi non posso leggere avanti 1024 caratteri perché potrebbero non essercene così tanti. man 2 read mostra che POSIX read ha 3 argomenti, quindi non so a cosa si riferisca. –

+0

come ti ho detto non l'ho provato. Scrivo solo "al volo". Il codice è facile da capire e adattare. A proposito, l'ho aggiornato per tenere conto dei delimitatori di linea: "\ n \ n" –

0

con C++ Sockets Library:

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

E utilizzando la classe di cui sopra:

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 biblioteca si occupa di tutti la gestione degli errori.

Trova la libreria usando Google o utilizzare questo link diretto: http://www.alhem.net/Sockets/

2

Qui è un collaudato con il codice abbastanza efficiente:

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

E 'anche utile per segnale di impostazione SIGPIPE ignorando in lettura e scrittura (e gestire gli errori come mostrato sopra):

signal (SIGPIPE, SIG_IGN); 
Problemi correlati