class socketClient
{
private:
SOCKET ConnectSocket;
int numBlock;
public:
socketClient()
{
WSADATA wsaData;
numBlock = countObj;
++countObj;
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
ssPrintf("WSAStartup failed: %d\n", iResult);
//return 1;
}
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
{
ssPrintf("Error at socket(): %ld\n", WSAGetLastError());
//freeaddrinfo(result);
WSACleanup();
//return 1;
}
}
void sConnect(char* myHost, int myPort)
{
int iResult;
char port[5];
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
_itoa_s(myPort,port,5,10);
iResult = getaddrinfo(myHost, porgt, &hints, &result);
if ( iResult != 0 )
{
ssPrintf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
//return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
}
~socketClient()
{
int iResult;
--countObj;
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
//return 1;
}
closesocket(ConnectSocket);
WSACleanup();
}
int getNumBlock()
{
return numBlock;
}
int sWrite(std::string str)
{
int iResult;
// Send an string
iResult = send( ConnectSocket, str.c_str(), str.size(), 256 );
if (iResult == SOCKET_ERROR)
{
ssPrintf("send failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
//return 1;
}
return iResult; //pocet odeslanych bytu
}
};
我正在尝试将字符串发送到客户端模型,但在运行模型时,我收到错误:
请让我知道我可以在此代码中更改哪些内容。
答案 0 :(得分:1)
套接字错误10093(WSANOTINITIALIZED
)表示:
WSAStartup()
尚未被调用,或者失败
WSACleanup()
被调用了太多次。
在这种情况下,您的代码在不属于的地方调用WSACleanup()
:
sConnect()
失败,则 WSACleanup()
来电getaddrinfo()
sWrite()
失败,则 WSACleanup()
调用send()
。
~socketClient()
失败, WSACleanup()
会额外拨打shutdown()
。
WSAStartup()
和WSACleanup()
。对于WSAStartup()
的每次成功来电,您必须只调用WSACleanup()
一次。在这种情况下,只有析构函数应该调用WSACleanup()
,并且只有WSAStartup()
在构造函数中成功。
您的代码中也包含其他错误。
尝试更像这样的东西:
class socketClient
{
private:
SOCKET ConnectSocket;
int numBlock;
bool WSAInitialized;
// private to prevent copies
socketClient(const socketClient&)
: ConnectSocket(INVALID_SOCKET), WSAInitialized(false)
{
numBlock = countObj++;
}
socketClient& operator=(const socketClient&)
{
return *this;
}
public:
socketClient()
: ConnectSocket(INVALID_SOCKET), WSAInitialized(false)
{
numBlock = countObj++;
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
ssPrintf("WSAStartup() failed: %d\n", iResult);
return;
}
WSAInitialized = true;
// Create a SOCKET for connecting to server
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
{
ssPrintf("socket() failed: %d\n", WSAGetLastError());
return;
}
}
~socketClient()
{
--countObj;
if (ConnectSocket != INVALID_SOCKET)
{
shutdown(ConnectSocket, SD_SEND);
closesocket(ConnectSocket);
}
if (WSAInitialized)
WSACleanup();
}
bool sConnect(char* myHost, int myPort)
{
char port[6];
struct addrinfo *result = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
_itoa_s(myPort, port, 6, 10);
int iResult = getaddrinfo(myHost, port, &hints, &result);
if (iResult != 0)
{
ssPrintf("getaddrinfo() failed: %d\n", iResult);
return false;
}
// Connect to server.
if (connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR)
{
ssPrintf("connect() failed: %d\n", WSAGetLastError());
freeaddrinfo(result);
return false;
}
freeaddrinfo(result);
return true;
}
int getNumBlock()
{
return numBlock;
}
bool sWrite(const std::string &str)
{
int iResult;
const char *ptr = str.c_str();
int len = str.size();
// Send an string
while (len > 0)
{
iResult = send( ConnectSocket, ptr, len, 0 );
if (iResult == SOCKET_ERROR)
{
ssPrintf("send() failed: %d\n", WSAGetLastError());
return false;
}
ptr += iResult;
len -= iResult;
}
return true;
}
};
由于您使用C ++进行编码,因此您应该考虑使用异常和RAII技术,例如:
#include <stdexcept>
#include <memory>
class winsock_error : public std::runtime_error
{
public:
int errorCode;
winsock_error(const std::string &msg, int error)
: std::runtime_error(msg), errorCode(error)
{
}
};
class wsaInit
{
private:
void init()
{
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
throw winsock_error("WSAStartup() failed", iResult);
}
public:
wsaInit()
{
init();
}
wsaInit(const wsaInit &)
{
init();
}
~wsaInit()
{
WSACleanup();
}
};
struct socketDeleter
{
typedef SOCKET pointer;
void operator()(SOCKET s)
{
if (s != INVALID_SOCKET)
{
shutdown(s, SD_BOTH);
closesocket(s);
}
}
};
typedef std::unique_ptr<SOCKET, socketDeleter> socket_ptr;
typedef std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> addrinfo_ptr;
class socketClient
{
private:
wsaInit wsa;
socket_ptr ConnectSocket;
int numBlock;
public:
socketClient()
: ConnectSocket(INVALID_SOCKET)
{
numBlock = countObj++;
}
socketClient(const socketClient&) = delete;
socketClient& operator=(const socketClient&) = delete;
~socketClient()
{
--countObj;
}
void sConnect(char* myHost, int myPort)
{
char port[6];
struct addrinfo *result = NULL,
hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
_itoa_s(myPort, port, 6, 10);
int iResult = getaddrinfo(myHost, port, &hints, &result);
if (iResult != 0)
throw winsock_error("getaddrinfo() failed", iResult);
addrinfo_ptr result_ptr(result, &::freeaddrinfo);
// Connect to server.
int errorCode = 0;
for(struct addrinfo *ptr = result; ptr != NULL; ptr = ptr->ai_next)
{
// Create a SOCKET for connecting to server
socket_ptr sock( socket(result->ai_family, result->ai_socktype, result->ai_protocol) );
if (sock.get() == INVALID_SOCKET)
throw winsock_error("socket() failed", WSAGetLastError());
if (connect(sock.get(), result->ai_addr, (int)result->ai_addrlen) != SOCKET_ERROR)
{
ConnectSocket = std::move(sock);
return;
}
errorCode = WSAGetLastError();
}
throw winsock_error("connect() failed", errorCode);
}
int getNumBlock()
{
return numBlock;
}
void sWrite(const std::string &str)
{
int iResult;
const char *ptr = str.c_str();
int len = str.size();
// Send an string
while (len > 0)
{
iResult = send(ConnectSocket.get(), ptr, len, 0);
if (iResult == SOCKET_ERROR)
throw winsock_error("send() failed", WSAGetLastError());
ptr += iResult;
len -= iResult;
}
}
};