我需要在c ++中创建一个服务器,它可以响应多个客户,从而使用线程。
这是我的类Socket,实际的通信完成了:
typedef struct addrinfo addinfo;
class Socket
{
private:
WSADATA _wsaData;
int _iResult;
SOCKET _ListenSocket;
addrinfo* _result;
addrinfo _hints;
int _iSendResult;
char _recvbuf[BUF_LEN];
int _recvbuflen;
std::vector<SOCKET> _ClientSockets;
public:
Socket();
bool Setup();
bool CreateSocket();
bool Bind();
bool Listen();
bool Accept();
bool Send();
bool Shutdown();
~Socket();
};
Socket::Socket()
{
_ListenSocket = INVALID_SOCKET;
_ClientSockets.push_back(INVALID_SOCKET);
_result = NULL;
_recvbuflen = BUF_LEN;
}
bool Socket::Setup() {
_iResult = WSAStartup(MAKEWORD(2, 2), &_wsaData);
if (_iResult != 0) {
std::cout << "WSAStartup failed with error: " << _iResult << std::endl;
return false;
}
ZeroMemory(&_hints, sizeof(_hints));
_hints.ai_family = AF_INET;
_hints.ai_socktype = SOCK_STREAM;
_hints.ai_protocol = IPPROTO_TCP;
_hints.ai_flags = AI_PASSIVE;
_iResult = getaddrinfo(NULL, DEFAULT_PORT, &_hints, &_result);
if (_iResult != 0) {
std::cout << "getaddrinfo failed with error: " << _iResult << std::endl;
WSACleanup();
return false;
}
return true;
}
bool Socket::CreateSocket() {
_ListenSocket = socket(_result->ai_family, _result->ai_socktype, _result->ai_protocol);
if (_ListenSocket == INVALID_SOCKET) {
std::cout << "socket failed with error: " << WSAGetLastError() << std::endl;
freeaddrinfo(_result);
WSACleanup();
return false;
}
return true;
}
bool Socket::Bind() {
_iResult = bind(_ListenSocket, _result->ai_addr, (int)_result->ai_addrlen);
if (_iResult == SOCKET_ERROR) {
std::cout << "bind failed with error: " << WSAGetLastError() << std::endl;
freeaddrinfo(_result);
closesocket(_ListenSocket);
WSACleanup();
return false;
}
freeaddrinfo(_result);
return true;
}
bool Socket::Listen() {
_iResult = listen(_ListenSocket, SOMAXCONN);
if (_iResult == SOCKET_ERROR) {
std::cout << "listen failed with error: " << WSAGetLastError() << std::endl;
closesocket(_ListenSocket);
WSACleanup();
return false;
}
return true;
}
bool Socket::Accept() {
_ClientSockets.push_back(accept(_ListenSocket, NULL, NULL));
if (_ClientSockets[_ClientSockets.size() - 1] == INVALID_SOCKET) {
std::cout << "accept failed with error: " << WSAGetLastError() << std::endl;
closesocket(_ListenSocket);
WSACleanup();
return false;
}
return true;
}
bool Socket::Send() {
closesocket(_ListenSocket);
_iResult = recv(_ClientSockets[_ClientSockets.size() - 1], _recvbuf, _recvbuflen, 0);
if (_iResult > 0) {
_iSendResult = send(_ClientSockets[_ClientSockets.size() - 1], "Accepted", strlen("Accepted"), 0);
if (_iSendResult == SOCKET_ERROR) {
std::cout << "send failed with error: " << WSAGetLastError() << std::endl;
closesocket(_ClientSockets[_ClientSockets.size() - 1]);
WSACleanup();
return false;
}
}
else if (_iResult == 0)
std::cout << "Connection closing..." << std::endl;
else {
std::cout << "recv failed with error: " << WSAGetLastError() << std::endl;
closesocket(_ClientSockets[_ClientSockets.size() - 1]);
WSACleanup();
return false;
}
return true;
}
bool Socket::Shutdown() {
_iResult = shutdown(_ClientSockets[_ClientSockets.size() - 1], SD_SEND);
if (_iResult == SOCKET_ERROR) {
std::cout << "shutdown failed with error: " << WSAGetLastError() << std::endl;
closesocket(_ClientSockets[_ClientSockets.size() - 1]);
WSACleanup();
return false;
}
closesocket(_ClientSockets[_ClientSockets.size() - 1]);
WSACleanup();
return true;
}
Socket::~Socket()
{
}
这是主文件:
void interact(Socket* socket);
int main() {
Socket* socket = new Socket();
socket->Setup();
socket->CreateSocket();
socket->Bind();
socket->Listen();
while (1) {
socket->Accept();
std::thread trd(interact, socket);
trd.join();
system("PAUSE");
}
socket->Shutdown();
system("PAUSE");
return 0;
}
void interact(Socket* socket) {
std::cout << "Accepted" << std::endl;
socket->Send();
}
与第一个客户端进行通信很好,但在我尝试回到监听并完成与最后一个客户端的通信之后,它给出了错误代码10038 for accept和10093 for recv。我无法理解错误代码在我的代码中实际意味着什么。我怀疑它可能与我使用Accept的方式有关。是应该在交互功能中,还是在我调用线程之前?我能指点一下吗?
答案 0 :(得分:1)
所以你的有效控制流程是:
while (1) {
socket->Accept(); // uses socket->_ListenSocket
interact(socket); // calls socket->Send()
socket->Send(); // calls closesocket(_ListenSocket);
既然您故意关闭了侦听套接字,为什么您希望后续的呼叫接受工作呢?
其他说明: