2015-05-04 2 views
1

В настоящее время я пытаюсь реализовать класс для создания и использования TCP-соединений. (я совершенно новый в C++, поэтому возможно, что я забыл что-то очевидное, хотя я серьезно проверял свой код)10038 wsa socket error recv

Обратите внимание, что позже я буду внедрять второй класс для обработки новых подключений, чтобы там некоторые части кода, которые являются неполными/упорядоченными, и я надеюсь, что это не потревожит вас, пытаясь понять это.

Вот моя проблема:

сервер и клиент, как представляется, отлично работает (я всегда проверять на моем слушать, связывать, не подключать функции: нет ошибок), и я, видимо, способен передавать данные с клиент, но когда я пытаюсь прочитать его с сервера, я получаю WSA-ошибку 10038 (это означает, что я выполняю recv() в недопустимом сокете). Я искал его в течение нескольких дней и не могу найти свою ошибку. Помимо тестов в коде, я использовал «netstat -an -p tcp», чтобы проверить состояние соединения, и все выглядит нормально, но сервер просто не получит данные.

NB: Я использую Visual Studio 6 (да, это старый, но это обязательно так ...) и winsock, а не winsock2.

Если я забыл что-то просто спросить, я стараюсь быть как можно более полным, но что-то не забывать.

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

CmTcpTransport.cpp

/** 
Initializes the TCP connexion (socket) in CLIENT or SERVER mode. 
It does not connect yet. 

@param strIPAddress: IP Adress to reach 
     nPort: Port to connect to 
     hSocket: client Socket if SERVER mode 
     nTcpMode: mode for this connexion SERVER(1) or CLIENT(2)  

@return an int to get the exit point of the function 
*/ 
int CmTcpTransport::initialize(std::string strIPAddress, unsigned int nPort,   SOCKET hSocket, int nTcpMode) 
{ 
m_nTcpMode = nTcpMode; 

cout << "Creating TCP connexion..." << endl << endl; 

if (nTcpMode == 1) // SERVER 
{ 

    serveraddr.sin_family = AF_INET; // address family Internet 
    serveraddr.sin_port = htons (nPort); // Port to connect on 
    serveraddr.sin_addr.s_addr = inet_addr (strIPAddress.c_str()); // Target IP 

    cout << "SERVER: Retreaving socket information..." << endl; 

    if (hSocket == INVALID_SOCKET) 
    { 
     return 102; // The received socket is invalid 
     cout << "SERVER: Socket creation failed" << endl; 
    } 

    serverSocket = hSocket; 

    cout << "SERVER: Listening socket received" << endl; 

    if (bind(serverSocket, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) == SOCKET_ERROR) 
    { 
     return 103; // Couldn't bind 
     cout << "SERVER: Socket binding failed" << endl; 
    } 
    else { 
     cout << "SERVER: Binding successful" << endl; 
    } 

    if (listen(serverSocket, 1) == SOCKET_ERROR) 
    { 
     return 103; // Couldn't listen 
     cout << "SERVER: Socket listening failed" << endl; 
    } 
    else { 
     cout << "SERVER: Listening to socket" << endl; 
    } 

} 
else // CLIENT 
{ 
    serveraddr.sin_family = AF_INET; // address family Internet 
    serveraddr.sin_port = htons (nPort); // Port to connect on 
    serveraddr.sin_addr.s_addr = inet_addr (strIPAddress.c_str()); // Target IP 

    cout << "CLIENT: Creating client socket..." << endl; 

    clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // CREATE CLIENT SOCKET 

    if (clientSocket == INVALID_SOCKET) 
    { 
     return 104; // Couldn't create the socket 
     cout << "CLIENT: Socket creation failed" << endl; 
    } 

    cout << "CLIENT: Client socket created" << endl; 


} 

cout << "Initialization succeeded." << endl << endl << endl; 
return 105; 
} 

/** 
Creates the connexion to TCP 

@param none   
@return an int to get the exit point of the function 
*/ 
int CmTcpTransport::connectTcp() 
{ 


if (m_nTcpMode == 1) // SERVER 
{ 
    cout << "Waiting for connexion..." << endl; 
    int clientLen(0); 
    clientLen = sizeof(clientaddr); 


    if ((clientSocket = accept(serverSocket, (SOCKADDR *)&clientaddr, &clientLen) == INVALID_SOCKET)) 
    { 
     cout << "SERVER: Connexion failed." << endl; 
     return 202;; // Couldn't listen 
    } 
    else { 
     cout << "SERVER: Connexion established." << endl << endl << endl; 
     if (clientSocket == SOCKET_ERROR) 
     { 
      printf("socket became invalid after connexion:: %d\n", WSAGetLastError()); 
     } 
     else { 
       cout << "SOCKET STILL VALID AND WORKING AFTER CONNEXION" << endl; 
     } 
     return 201; 
    } 


} 
else // CLIENT 
{ 
    cout << "Connecting..." << endl; 
    if (connect(clientSocket, (SOCKADDR *)&serveraddr, sizeof(serveraddr)) == SOCKET_ERROR) 
    { 
     cout << "CLIENT: Connexion failed." << endl << endl << endl; 
     return 202;; // Couldn't connect 
    } 
    else 
    { 
     cout << "CLIENT: Connexion to server succeeded." << endl << endl <<   endl; 
    } 
    return 203; 
} 
} 

/** 
Receives a buffer of bytes from the TCP 

@param buffer: buffer to store the data 
     bufLen: size of the buffer 

@return nbChar: the result of the recv function 
if no error occurs, recv returns the number of bytes received 
else, it returns a value of SOCKET_ERROR 
*/ 
int CmTcpTransport::recvTcp(char *buffer, int bufLen) 
{ 
if (clientSocket == SOCKET_ERROR) 
     { 
      printf("socket became invalid before receive:: %d\n", WSAGetLastError()); 
     } 
     else { 
       cout << "SOCKET STILL VALID AND WORKING BEFORE RECEIVE" <<   endl; 
     } 

int nbChar = recv(clientSocket, buffer, bufLen, 0); 
if (nbChar == SOCKET_ERROR) 
{ 
    printf("recv failed: %d\n", WSAGetLastError()); 
    cout << "No data received." << endl << endl << endl; 
    return nbChar; 
} 
else { 
    buffer[nbChar]=0; // Gestion de la taille du buffer 
    cout << "Data received: " << buffer << endl << endl << endl; 
    return nbChar; 
} 
} 
/** 
Sends a buffer of bytes to the TCP 

@param buffer: buffer containing the data 
     bufLen: size of the buffer 

@return nbChar: the result of the send function 
if no error occurs, recv returns the number of bytes sent 
else, it returns a value of SOCKET_ERROR 
*/ 
int CmTcpTransport::sendTcp(char *buffer, int bufLen) 
{ 

int nbChar = send(clientSocket, buffer, bufLen,0); 
if (nbChar == SOCKET_ERROR) 
{ 

    cout << "No data sent." << endl << endl << endl; 
    return nbChar; 
} 
else { 
    cout << "Data sent: " << buffer << endl << endl << endl; 
    return nbChar; 
} 
} 

сервер main.cpp

int main(int argc, char* argv[]) 
{ 
// ----------------------- WINSOCK ---------------------------- 

cout << "Initializing winsock library..." << endl; 

// Start up Winsock 
WSADATA wsadata; 

int error = WSAStartup(0x101, &wsadata); 

// Error ? 
if (error) 0; 

// Try Winsock Version ? 
if (wsadata.wVersion != 0x101) 
{ 
    WSACleanup(); // Clean up Winsock 
    return 101; 
} 

cout << "Initialization successful" << endl << endl << endl; 


// ----------------------- SERVER --------------------------- 

char buffer[3000]; 

int testRecv; // return of the recv function 

cout << "SERVER" << endl << endl << endl; 

// Simulate the activity of the TcpListener transfering a listening Socket for the client connexion 
SOCKET testSocket; 
testSocket = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP); 

// Creating a new TCP transport 
CmTcpTransport server; 

// Initialize and connect the TCP transport 
server.initialize("127.0.0.1", 10000, testSocket, TTCP_MODE_SERVER); 

server.connectTcp(); 

// Try to receive data 
testRecv = server.recvTcp(buffer, sizeof(buffer)); 

cout << testRecv << endl; 

// Disconnect 
server.disconnectTcp(); 


return 0; 
} 

клиент main.c С.

int main(int argc, char* argv[]) 
{ 

// ----------------------- WINSOCK ---------------------------- 

cout << "Initializing winsock library..." << endl; 

// Start up Winsock 
WSADATA wsadata; 

int error = WSAStartup(0x0202, &wsadata); 

// Error ? 
if (error) 0; 

// Try Winsock Version ? 
if (wsadata.wVersion != 0x0202) 
{ 
    WSACleanup(); // Clean up Winsock 
    return 101; 
} 

cout << "Initialization successful" << endl << endl << endl; 


// ----------------------- CLIENT --------------------------- 

char buffer[10000]; 

cout << "CLIENT" << endl << endl << endl; 

// this Socket won't be used as the TCP transport is in client mode 
SOCKET test; 
test = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP); 

// Create, initialize and connect the client TCP transport 
CmTcpTransport client; 

client.initialize("127.0.0.1", 10000, test, TTCP_MODE_CLIENT); 

client.connectTcp(); 

// Copy the data in the buffer and send it 
strcpy(buffer, "Test donnees"); 

client.sendTcp(buffer, sizeof(buffer)); 

client.disconnectTcp(); 

return 0; 
} 

А вот скриншоты моих консолей, когда я запускаю обе сети:

http://www.hostingpics.net/viewer.php?id=892752Consoles.jpg

Благодарим Вас за вашу помощь, я понимаю, что это много, чтобы читать/процесс, и я ценю усилие !

+1

Это, как правило, что отладчик для, не вопрос о SO. –

+0

Smal EDIT: Я уже исправил тот факт, что мои «возвращения» в случае ошибки были до моей «ошибки cout ...», это была старая, но работающая версия моего кода. И, работая, я имею в виду, что я получаю ошибку 10038 на recv(). –

ответ

2

Я думаю, вы недействительность нового носка идентификатора на accept с неправильными скобками:

if ((clientSocket = accept(serverSocket, (SOCKADDR *)&clientaddr, &clientLen) == INVALID_SOCKET))

Попробуйте изменить его:

if ((clientSocket = accept(serverSocket, (SOCKADDR *)&clientaddr, &clientLen)) == INVALID_SOCKET)

+0

Спасибо! Это сработало. Я был уверен, что это было что-то смешное, я думаю, это хороший урок для изучения. –

+0

Спасибо, Прабху, я срывал волосы с той же проблемой! –