2012-04-14 2 views
0

私はWindowsでマルチスレッドソケットライブラリを構築していますが、サーバに接続するクライアントを正常に取得しても、recvを呼び出すとWSA Not Startedエラーが発生します。私はそれをスレッド化する前にそれも働いていましたが、その後何が起こったのかわかりません。どんな助けもありがとう。WinSock2エラー10093 on 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

これは、SOのコードの量が多いです。 WSAStartupがサーバーサイドコードで呼び出されたことを確認できますか? 'Initializing socket ... 'と表示され、エラーの後には表示されません。 – ixe013

+0

はい、あります。サーバーは、オブジェクトを作成し、クライアントからの接続をバインド、リッスン、受け入れ、そしてrecvループエラーを10093で返し、接続を終了します。すべてのコードbtwについて申し訳ありませんが、私はWSAのソースが何であるか分からないので、コードのセクションで助けを求める方法を知らなかった。 – bitwiser

答えて

1

私はあなたが生きている "オリジナル" のソケットを維持する必要があります信じ。 sessionSock->recv_data()ループの後にlistenSock.close();を移動します。

+0

ところで、 'clientSession()'は決して返りません。それが意図されたのだろうか? – ixe013

+0

それはエラーを修正しました、ありがとうございます!私はあなたにビールを買うことができたら私は:) – bitwiser

+0

答えを受け入れると、私はここでビールを開くでしょう。あなたがここで長い間ぶらぶらしている間にあなたは理解するでしょう... – ixe013