2012-05-10 5 views
1

Как вы читаете петли для C++-сокетов.Как вы читаете петли для C++-сокетов?

stringstream ss; 
while (1) { 
    char buf [2]; 
    ssize_t e = read(fd, buf, 2); 

    ss << buf[0]; 
    ss << buf[1]; 



    cout << e << endl; 
    cout << buf[0] << endl; 
    cout << buf[1] << endl; 

    if (e <= 0) { 
     break; 
    } 
} 
string msg = ""; 
ss >> msg; 

Когда я телнет и типа привет, а затем ввести, чтобы проверить это, я получаю

2 
h 
e 
2 
l 
l 
2 
o 

1 

И он просто ждет там, не зацикливание. Что происходит, и как я читаю сокеты?

Как я Signify EOF с помощью

  1. телнет

  2. БУФ в контексте записи (FD, ЬиЕ, BUFSIZE);

+0

Да, он ждет на 'read()', что является блокирующим вызовом. – delicateLatticeworkFever

+0

Как я могу узнать, что это eof? – Derek

+0

Соединение сломается. 'read()' будет возвращать либо -1 (затем проверить 'errno'), либо 0. 0 указывает, что другой конец отключен. – delicateLatticeworkFever

ответ

1

Что вы имеете в виду, не зацикливание? Напечатайте еще немного, нажмите enter, и вы увидите еще несколько результатов.

Если вы закончили, вы должны нажать Ctrl + D, чтобы сигнализировать о конце ввода (EOF).

+0

И после EOF в этом цикле будет запущена проверка 'read()' ... – delicateLatticeworkFever

+0

Ctrl + D не дает мне EOF на telnet – Derek

+0

В окнах я думаю, что это Ctrl-Z, * nix - это Ctrl- D. – delicateLatticeworkFever

1

Как я Signify EOF с помощью

1) телнет

2) ЬиЕ в контексте записи (FD, ЬиЕ, BUFSIZE);

Во-первых, это не EOF, который вы хотите сигнализировать. Это «конец сообщения» или «данные, которые вы только что получили, являются полным блоком данных протокола, и вы должны его обработать». И ответ: , однако вы хотите, если обе стороны согласны.

Например, вы можете зарезервировать персонаж ~ специально для того, чтобы пометить конец сообщения. Чтобы указать конец сообщения, одна сторона отправляет номер ~. Другая сторона знает, что когда она получает ~, все, что до этого, является единственным сообщением, и все после него является новым сообщением.

Вы также можете отправить длину сообщения до отправки фактического сообщения. Вы можете сделать это в тексте, за которым следует нулевой байт или фид строки. Или вы можете сделать каждое сообщение строкой.

Вы можете сделать это, однако, имеет наибольший смысл в своем конкретном приложении, но вам действительно нужно это сделать.

Есть два случая, когда TCP делает это сделать для вас:

1) Когда сторона полностью осуществляется отправка и знает, с другой стороны не будет посылать больше данных в любом случае, он может использовать close на сокете. Другая сторона прочтет оставшуюся часть уже отправленных данных, а затем read вернется 0.

2) Когда сторона не собирается отправлять больше данных, но другая сторона может отправить больше данных, она может shutdown своей стороной соединения. Однако он больше не может отправлять данные. Другая сторона узнает об этом завершении работы, и, если это будет специально закодировано, может продолжать отправлять данные до тех пор, пока она не отключит свою половину. Тогда другая сторона read вернет ноль.(Обратите внимание, что если вы сделаете это с программой, которая не была предназначена для ее принятия, она, вероятно, запутается и не поймет, что она все равно может отправлять вам данные.)

В противном случае все зависит от вас.

+0

Клиент: 1.connect, 2.write, 4.close, 6.read | Сервер: 3.read, 5.write, 7.close, Могу ли я запустить код в этом порядке с помощью sockfd из 2. и 6. то же самое? – Derek

+0

После закрытия вы не можете прочитать. Тем не менее, клиент может отключить свою сторону записи сокета, и если сервер правильно закодирован, он может интерпретировать частичное завершение работы как конец сообщения, отправляемого клиентом. Я не рекомендую это делать. –

1

TCP-пакеты - это поток, а не файл. Это зависит от вас, как читается поток.

В общем случае, если вы напишете 20 байт на одном конце, вы получите 20 байт на другом конце в одном чтении, запретив использование некоторых общих параметров tcp/ip.

Ниже приведены допущения. Некоторые из этих предположений:

Предположим, что все строительные леса есть.

Предположим, я допустил ошибки и отлаживал их самостоятельно.

Предположим, что все вопросы по порядку байтов обрабатываются.

Предположим, вы достаточно умны, чтобы не отправлять типы с плавающей точкой в ​​виде двоичных файлов.

  • Некоторые программисты предпочитают использовать длину префикса пакета и читать байт длины (2), а затем прочитать столько байтов, что длина представляет собой, например, так.

    unsigned char buffer[MAX_CHAR] = ""; 
    unsigned char length = 0; 
    int bytesRead = 0; 
    
    read(fd, sizeof(length), &length); 
    // Handle failure from read 
    while(bytesRead < length) 
    { 
        int readRv = read(fd, &buffer[bytesRead], length - bytesRead); 
        if(readRv <= 0) // 0 usually means socket was closed. -1 is an erro 
        { 
         // Handle socket error/closed socket 
        } 
        else if(readRv < length) 
        { 
         bytesRead += readRv; 
        } 
        else if(readRv == length) 
        { 
         bytesRead = readRv; 
         break; 
        } 
    } 
    
  • Некоторые программисты читать то, что доступно и искать конец пакета маркера

    unsigned char buffer[MAX_CHAR] = ""; 
    unsigned char length = 0; 
    int bytesRead = 0; 
    int readRv = read(fd, buffer, sizeof(buffer)); 
    int eopFound = 0; 
    
    
    if((eopFound = findEndOfPacketMarker(buffer)) > 0) 
    { 
        // Less than 0 = error. 
    } 
    else if(eopFound == 0) 
    { 
        // No end of packet, must read more bytes here 
    } 
    else 
    { 
        // Found an end of packet marker 
    } 
    
    // Here you deal with bytes that are "over read" 
    // Either the 
    // 1) packet was bigger than buffer, 
    // 2) there were bytes left over after the EOP marker 
    // 3) Martians crapped in your code and screwed it all up. :) 
    
  • Некоторые программисты используют фиксированный размерный набор пакетов и тип пакета идентификатор

    int packetType; 
    
    unsigned char buffer[MAX_CHAR] = ""; 
    unsigned char length = 0; 
    int bytesRead = 0; 
    
    read(fd, sizeof(packetType), &packetType); 
    read(fd, getLengthFromPacketType(packetType), buffer); 
    

Это должно охватывать большинство вещей ... Если у вас есть еще несколько пожалуйста, спросите в комментариях с помощью статьи @ JimR, чтобы она отображалась как сообщение для меня для чтения.

Смежные вопросы