2010-10-11 6 views
0

У меня возникли проблемы с простым TCP-сокетом с функцией connect() и read(). Эта программа работает, если я запускаю сервер сначала, а клиент второй. Однако, когда я сначала запускаю клиент, он продолжает пытаться подключиться к серверу, а затем, когда я запускаю сервер, он соединяется, но последующее чтение возвращает 0 байтов. Это говорит о том, что сервер закрыл сокет, но операторы отладки не поддерживают это.Ошибка TCP-соединения

Я пытаюсь, чтобы клиент постоянно пытался подключиться к серверу на порту 6380, а затем читать данные. Если соединение потеряно, клиент попытается снова подключиться. У меня SO_REUSEADDR установлен для сокетов. Есть ли что-то еще, что мне не хватает?

Исходный код для сервера

//***** SERVER ***** 
#include <iostream> 
#include "SocketAdapter.h" 
#include "SocketServer.h" 
#include <errno.h> 
#include <string.h> 

unsigned char buffer[] = "123123123"; 

int main() 
{ 
    SocketAdapter socket; 
    SocketServer server(6380); 

    server.Start(); 
    std::cout << "Wait for Connection" << std::endl; 
    server.WaitForConnection(socket); 
    std::cout << "Start to Send Data" << std::endl; 

    while(1) 
    { 
     std::cout << "Sending Data "; 
     int bytesSent = socket.Send(buffer, 10); 
     std::cout << "byteSent = " << bytesSent << std::endl; 
     if (bytesSent == -1) 
     { 
     std::cout << "Errno (" << errno << ") - " << strerror(errno) << std::endl; 
     } 

     sleep(1); 
    }//end while 

    std::cout << "Ending Server" << std::endl; 
    socket.Close(); 

    return 0; 
} 

Исходный код для клиента

// ***** SIMPLE CLIENT ****** 
#include <iostream> 
#include "SocketAdapter.h" 
#include "SocketClient.h" 
#include <string.h> 
#include <errno.h> 

int main() 
{ 
    SocketAdapter socket; 
    SocketClient client(6380, "127.0.0.1"); 

    unsigned char buffer[1024]; 


    while(1) 
    { 
     client.Start(); 

     //Loop till we connect to Server 
     while(!client.Connect(socket)) 
     { 
     std::cout << "Trying to connect to server." << std::endl; 
     sleep(1); 
     } 

     std::cout << "Connected to Server" << std::endl; 

     //Read till we get a timeout 
     while(1) 
     { 
     int bytesRead = socket.Recv(buffer, 10,2000); 
     if (bytesRead != 10) 
     { 
      std::cout << " Failed to Read" << std::endl; 
      std::cout << " bytesRead = " << bytesRead << std::endl; 
      std::cout << " Errno (" << errno << ") - " 
         << strerror(errno) << std::endl; 
      break; 
     } 

     std::cout << "buffer = " << buffer << std::endl; 
     usleep(250000); 
     } 

     std::cout << "Something went wrong, restart" << std::endl; 
    } 

    return 0; 
} 

ВЫВОД Серверной

./Server 
Wait for Connection 
Start to Send Data 
Sending Data byteSent = 10 

ВЫВОД КЛИЕНТА

./Client 
Trying to connect to server. 
Trying to connect to server. 
Connected to Server 
    Failed to Read 
    bytesRead = 0 
    Errno (107) - Transport endpoint is not connected 
Something went wrong, restart 
Close Socket 
Close Socket File Descriptor 
Connected to Server 
Trying to Recv on a closed socket 
Return Value = -1 
Errno  = Connection reset by peer 

    Failed to Read 
    bytesRead = -3 
    Errno (104) - Connection reset by peer 
Something went wrong, restart 
Close Socket 
Close Socket File Descriptor 
Socket cannot shutdown! 
Return Value = -1 
Errno  = Transport endpoint is not connected 

Trying to connect to server. 
Close Socket 
Close Socket File Descriptor 
Socket cannot shutdown! 
Return Value = -1 
Errno  = Transport endpoint is not connected 
+4

Что такое SocketAdapter.h и SocketServer.h? Доморощенные? – dgnorton

+1

Я удивлен, что вывод сервера не извергает «Отправка данных byteSent = 10» снова и снова. Почему буфер 123 МБ на сервере? Клиент предполагает, что всегда будет читать 10 байт ... вероятно, будет даже без гарантии даже при нормальной работе. – dgnorton

+2

, вы можете рассмотреть [Boost.Asio] (http://www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/overview/rationale.html) вместо своих родных оболочек. –

ответ

1

Возврат 0 считанных байтов из сокета является совершенно законным. Это означает, что вам нужно подождать и повторить попытку.

Например, посмотрите на это read_data() function. Он проверяет, является ли количество прочитанных байтов > 0, затем оно хранит их. Он проверяет, является ли количество прочитанных байтов < 0, то это ошибка.

0 случай, конечно, не очень большой успех, но не провал. Попробуйте еще раз. Я не анализировал ваш код очень подробно, так что может быть что-то еще, но это часто возникающая ошибка. (Кроме того, что в этих классах не показано?)

Что вы можете задумать - это неблокирующие сокеты. Также см. FAQ for how to tell if a socket is closed on the other end. И, возможно, рассмотрите detecting transfer completion explicitly by sending and end-of-file or marker.

+0

Спасибо. Вот и все. Я предполагал, что 0 означает отказ и что другая сторона фактически закрыла сокет. Однако, когда я модифицировал код для продолжения и повторил попытку с чтением, он работает отлично. –

+0

Это действительно решило мою проблему, но теперь я не могу понять, закрыла ли другая сторона гнездо. Я думал, что получение 0 байтов из чтения означает, что другая сторона закрыла сокет. Как http://stackoverflow.com/questions/2416944/can-read-function-on-a-connected-socket-return-zero-bytes –

+2

Возвращаемое значение 0 из прочитанного обычно означает, что сокет был отключен (в зависимости от на том, какую раму сокета вы используете поверх сокета). То, что вы должны делать, особенно если используете неблокирующие сокеты, ожидает, пока отчеты сокета будут считаны, прежде чем вы действительно сделаете чтение. В случае подключения сокет будет сообщать себя как записываемый, когда соединение будет успешным. –

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