2009-10-17 9 views

Antwort

2

Pseudocode:

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

So ähnlich.

+0

Das ist normalerweise gut genug, aber manchmal bekomme ich wirklich lange Zeilen, und das Lesen von einem Zeichen zu einer Zeit ist zu langsam. –

3

Ich lese gerade von einem TCP-Socket, von dem man nicht ausgehen kann, wenn das Ende der Zeile erreicht wird. Therfore werden Sie so etwas brauchen:

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; 

Sie verwenden "\ n \ n" als Begrenzer Unter der Annahme. (Ich habe das Code-Snippet nicht getestet ;-))

Auf einem UDP-Socket ist das eine andere Geschichte. Der Emiter kann ein Paquet senden, das eine ganze Zeile enthält. Der Empfänger wird garantiert, um das Paket als eine einzelne Einheit zu empfangen. Wenn es es empfängt, als UDP ist natürlich nicht so zuverlässig wie TCP.

+0

Es geht um TCP, ja. Das Problem ist, dass der Socket interaktiv ist. Ich muss eine Zeile senden, dann bekomme ich ein paar Zeilen. Ich kann das Ende mit doppelter Zeilenumbruch "\ n \ n" erkennen. –

+0

... also kann ich 1024 Zeichen nicht vorauslesen, weil es vielleicht nicht so viele gibt. man 2 lesen zeigt, dass POSIX gelesen haben 3 Argumente, so dass ich nicht weiß, was lesen Sie beziehen sich auf. –

+0

wie ich dir sagte, ich habe es nicht getestet. Ich schreibe nur 'bei der Fliege'. Der Code ist leicht zu verstehen und anzupassen. Übrigens habe ich es aktualisiert, um Ihre Zeilentrennzeichen zu berücksichtigen: "\ n \ n" –

0

Verwendung von C++ Sockets Bibliothek:

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

und unter Verwendung der oben Klasse:

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

Die Bibliothek kümmert sich um alle Fehlerbehandlung.

Finden Sie die Bibliothek google nutzen oder diesen Link verwenden: http://www.alhem.net/Sockets/

2

hier ein getestet wird, sehr effizient Code:

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

Es ist auch Aufbausignal SIGPIPE beim Lesen nützlich zu ignorieren und Schreiben (und handle Fehler wie oben gezeigt):

signal (SIGPIPE, SIG_IGN);