2012-04-14 4 views
0

Also ich bin eine Multithread-Socket-Bibliothek in Windows erstellen und ich bekomme den Fehler WSA nicht gestartet, wenn ich recv aufrufen, obwohl ich erfolgreich einen Client zum Herstellen einer Verbindung zum Server. Ich hatte es auch funktioniert, bevor ich es eingefädelt habe, aber ich weiß nicht, was seitdem passiert ist. Jede Hilfe wäre willkommen.WinSock2 Fehler 10093 auf recv

Spocket.hpp

#include <iostream> 
    #include <string> 
    #include <Windows.h> 
    #pragma comment (lib,"ws2_32.lib") 

    static bool initialized_ = false; 

    class Spocket 
    { 
    protected: 
     WSADATA   wsaData_; 
     SOCKET   hSocket_; 
     sockaddr_in  service_; 
     std::string  addr_; 
     USHORT   port_; 
     int    exitCode_; 

    public: 
     Spocket() { 
      initialize(); 
      create_socket(); 
     } 
     Spocket(std::string addr, USHORT port) 
      : addr_(addr), port_(port) { 
       initialize(); 
       create_socket(); 
     } 
     Spocket(Spocket spock, SOCKET sock) 
      : hSocket_(sock), 
      wsaData_(spock.wsaData_), 
      service_(spock.service_), 
      addr_(spock.addr_), 
      port_(spock.port_) 
     { 
      initialize(); 
     } 
     virtual ~Spocket() { close(); } 

     void initialize(); 
     void create_socket(); 
     void close(); 

     template<typename T> 
     int recv_data(T* i) { 
      int ret = recv(hSocket_, reinterpret_cast<char*>(i), 32, 0); 
      if(ret == SOCKET_ERROR) 
       cerr << WSAGetLastError() << endl; 
      return ret; 
     } 

     template<typename T> 
     int send_data(T* i) { 
      int ret = send(hSocket_, reinterpret_cast<char*>(i), sizeof(i), 0); 
      if(ret == SOCKET_ERROR) 
       cerr << WSAGetLastError() << endl; 
      return ret; 
     } 
    }; 

class ServerSpocket : public Spocket 
{ 
public: 
    ServerSpocket(std::string addr, USHORT port); 
    Spocket* accept_clients(); 
}; 


class ClientSpocket : public Spocket 
{ 
public: 
    ClientSpocket(std::string addr, USHORT port); 
}; 

Spocket.cpp

#include <iostream> 
using namespace std; 
#include "../include/spocket.hpp" 

void Spocket::initialize() { 
    if(!initialized_) 
    { 
     cout << "Initializing socket..." << endl; 

     exitCode_ = EXIT_SUCCESS; 
     int iResult = WSAStartup(MAKEWORD(2,2), &wsaData_); 
     if(iResult != NO_ERROR) { 
      cerr << "WSAStartup failed" << endl; 
      exitCode_ = EXIT_FAILURE; 
      close(); 
     } 
     initialized_ = true; 
    } 
} 

void Spocket::create_socket() { 
    hSocket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if(hSocket_ == INVALID_SOCKET) 
    { 
     cerr << "Error at socket(): " << WSAGetLastError() << endl; 
     exitCode_ = EXIT_FAILURE; 
     close(); 
    } 

    service_.sin_family = AF_INET; 
    service_.sin_addr.s_addr = inet_addr(addr_.c_str()); 
    service_.sin_port = htons(port_); 
} 

void Spocket::close() { 
    closesocket(hSocket_); 
    WSACleanup(); 
} 

ServerSpocket::ServerSpocket(std::string addr, USHORT port) : Spocket(addr, port) { 
    if(bind(hSocket_, (SOCKADDR*)&service_, sizeof(service_)) == SOCKET_ERROR) 
    { 
     cerr << "Failed to bind" << endl; 
     exitCode_ = EXIT_FAILURE; 
     close(); 
    } 

    if(listen(hSocket_, 1) == SOCKET_ERROR) 
    { 
     cerr << "Error listening on socket" << endl; 
     exitCode_ = EXIT_FAILURE; 
     close(); 
    } 
} 

Spocket* ServerSpocket::accept_clients() { 
    cout << "Waiting for connection...\n"; 
    SOCKET hAccepted = INVALID_SOCKET; 
    while(hAccepted == INVALID_SOCKET) 
     hAccepted = accept(hSocket_, NULL, NULL); 
    return new Spocket(*this, hAccepted); 
} 

ClientSpocket::ClientSpocket(std::string addr, USHORT port) : Spocket(addr, port) { 
    if(connect(hSocket_, (SOCKADDR*)&service_, sizeof(service_)) == SOCKET_ERROR) 
    { 
     cerr << "Failed to connect" << endl; 
     exitCode_ = EXIT_FAILURE; 
     close(); 
    } 
} 

Server_main.cpp

#include <iostream> 
#include <fstream> 
#include <vector> 
#include <spocket.hpp> 
using namespace std; 

vector<HANDLE> hThreads; 
vector<DWORD> dwThreadIds; 

struct ConnectionInfo 
{ 
    string ip; 
    unsigned int port; 
    ConnectionInfo(string ip_, unsigned int port_) : ip(ip_), port(port_){} 
}; 
static ConnectionInfo ci("127.0.0.1", 27015); 

DWORD WINAPI clientSession(LPVOID lpParam) 
{ 
    // create new socket to listen for connection attempts 
    ConnectionInfo arg = *reinterpret_cast<ConnectionInfo*>(lpParam); 
    ServerSpocket listenSock(arg.ip, arg.port); 

    // spawn a duplicate thread when a connection is made, and close the current listening socket 
    Spocket* sessionSock = listenSock.accept_clients(); 
    listenSock.close(); 
    cout << "client connected..." << endl; 
    /* 
    hThreads.push_back(CreateThread(NULL, 0, clientSession, &ci, 0, NULL)); 
    */ 

    // service the connected client 
    string msg; 
    while(sessionSock->recv_data(&msg) != SOCKET_ERROR && msg != "goodbye!") 
    { 
     cout << msg << endl; 
     msg.clear(); 
    } 

    cout << "finished with client..." << endl; 

    // wait quietly for server shutdown 
    while(true) 
     Sleep(200); 
    return 0; 
} 

int main() { 
    cout << "[Server]" << endl; 
    cout << "starting up..." << endl; 

    hThreads.push_back(CreateThread(NULL, 0, clientSession, &ci, 0, NULL)); 

    string input = ""; 
    do 
     cin >> input; 
    while(input != "exit"); 

    // close all thread handles here 
    cout << "shutting down..." << endl; 
    return 0; 
} 
+0

Das ist eine gute Menge Code für SO. Können Sie bestätigen, dass WSAStartup im serverseitigen Code aufgerufen wurde? Es sollte 'Initializing socket ... 'erscheinen und nicht von einem Fehler gefolgt sein. – ixe013

+0

Ja, tut es. Der Server erstellt das Objekt, bindet, hört und akzeptiert eine Verbindung vom Client und dann die recv-Schleifenfehler mit 10093 und beendet die Verbindung. Sorry über den ganzen Code btw, wusste nicht, wie man um Hilfe mit einem Codeabschnitt bittet, da ich nicht weiß, was die Quelle des WSA-Fehlers ist. – bitwiser

Antwort

1

Ich glaube, Sie müssen das "Original" Buchse am Leben zu halten. Verschieben Sie listenSock.close(); nach der sessionSock->recv_data() Schleife.

+0

BTW, 'clientSession()' wird nie zurückkehren. War das Absicht? – ixe013

+0

Das hat den Fehler behoben, vielen Dank! Wenn ich Ihnen ein Bier kaufen könnte, würde ich :) – bitwiser

+0

Akzeptieren Sie die Antwort, und ich werde ein Bier hier öffnen. Du wirst es verstehen, wenn du lange genug hier rumhängst ... – ixe013