所以我在windows中构建了一个多线程套接字库,当我调用recv时我得到了WSA Not Started错误,即使我成功地让一个客户端连接到服务器。我在穿线之前也让它工作,但我不知道从那以后发生了什么。任何帮助,将不胜感激。
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;
}