私は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;
}
これは、SOのコードの量が多いです。 WSAStartupがサーバーサイドコードで呼び出されたことを確認できますか? 'Initializing socket ... 'と表示され、エラーの後には表示されません。 – ixe013
はい、あります。サーバーは、オブジェクトを作成し、クライアントからの接続をバインド、リッスン、受け入れ、そしてrecvループエラーを10093で返し、接続を終了します。すべてのコードbtwについて申し訳ありませんが、私はWSAのソースが何であるか分からないので、コードのセクションで助けを求める方法を知らなかった。 – bitwiser