我正在编写一个用于TCP/IP网络客户端通信的类。在类头中,我创建了一个套接字成员。该类还包含一个用于调用WSAStartup和检查版本的方法。建立连接的方法首先调用WSAStartup,然后初始化调用socket()函数的套接字成员。请参阅下面的代码。我想知道这是否“正确”,或者是否有更好的方法。
头文件:
/*network.h*/
public class IPnetwork
{
private:
WSADATA wsaData ;
SOCKET hSocket ;
sockaddr_in socketAddress ;
static const int SERVER_PORT = 502 ;
unsigned long int = serverIP ;
public:
IPnetwork(char* serverIPaddress) ;
bool Connect() ;
bool Disconnect() ;
~IPnetwork() ;
private:
bool startWinSock() ;
} ;源码:
/*network.cpp*/
IPnetwork::IPnetwork(char* serverIPaddress)
{
serverIP = inet_addr(serverIPaddress) ;
}
bool IPnetwork::Connect()
{
/* start winsock */
if(!startWinSock())
{
return false ; /* winsock problem */
}
/* Create socket */
if ((hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
return false ; /* could not create socket */
}
/* fill socket address structure */
socketAddress.sin_family = AFINET ;
socketAddress.sin_port = htons(SERVER_PORT) ;
socketAddress.sin_addr.S_un.S_addr = serverIP ;
/* connect */
if(connect(hSocket,reinterpret_cast<sockaddr*>(&socketAddress), sizeof(sockAddr))!=0)
{
return false ; /* could not connect*/
}
return true ;
}
bool IPnetwork::startWinSock()
{
if(WSAStartup(MAKEWORD(REQ_WINSOCK_VER,0),&wsaData)==0)
{
/* Check if major version is at least REQ_WINSOCK_VER */
if (LOBYTE(wsaData.wVersion) < REQ_WINSOCK_VER)
{
return false ; /* winsock started but version is too low */
}
else
{
return true ; /* winsock started with right version*/
}
}
else
{
return false ; /* winsock not started */
}
}发布于 2013-03-12 00:33:59
你担心定义一个SOCKET类型的变量,以及它的构造函数什么时候运行?
这不是问题,因为SOCKET是一种与C兼容的普通旧数据整型类型,它保存一个套接字标识符。它不是一个物体。没有与变量本身相关的非平凡的构造或销毁。
发布于 2013-03-12 02:40:59
必须先调用WSAStartup(),然后才能调用socket(),否则将返回WSANOTINITIALISED错误。
您可以多次调用WSAStartup()。最好只调用一次WSAStartup(),但WinSock是引用计数的,因此如果需要,它可以被调用多次。您必须确保每次WSAStartup()成功时都调用一次WSACleanup(),否则引用计数将不平衡。例如,您可以在构造函数中调用WSAStartup(),在析构函数中调用WSACleanup():
public class IPnetwork
{
private:
WSADATA wsaData ;
bool wsaInit;
...
public:
IPnetwork(char* serverIPaddress) ;
~IPnetwork() ;
} ;。
IPnetwork::IPnetwork(char* serverIPaddress)
{
wsaInit = (WSAStartup(MAKEWORD(REQ_WINSOCK_VER,0), &wsaData) == 0);
...
}
IPnetwork::~IPnetwork()
{
if (wsaInit) WSACleanup();
}
bool IPnetwork::Connect()
{
if (!wsaInit)
return false ; /* winsock problem */
...
}尽管我通常会在单独的单例类中调用它们。
发布于 2013-03-12 00:56:56
虽然我同意@Ben的观点,你所做的一切都很好,但我个人会试着从你的代码主线中去掉这种丑陋的东西。在头文件中创建全局变量是很少见的,例如:
#ifndef WS_INITIATOR_INC_
#define WS_INITIATOR_INC_
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <stdexcept>
struct bad_version : public std::logic_error {
bad_version(std::string const &s) : logic_error(s) {}
};
struct winsock {
static const int version = 2;
WSADATA wsaData;
winsock() {
WSAStartup(MAKEWORD(2, 2),&wsaData);
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
throw bad_version("Could not initialize WinSock 2.2");
}
~winsock() {
WSACleanup();
}
} ws_initiator;
#endif将其包含在您的main.cpp (或您为包含main的文件指定的任何名称)中,它会自动初始化/清理套接字(以及链接到正确的库)。
https://stackoverflow.com/questions/15343692
复制相似问题