socket_generic.cpp
来自「这是一款2d游戏引擎」· C++ 代码 · 共 291 行
CPP
291 行
/* $Id: socket_generic.cpp,v 1.17 2003/11/11 10:13:25 grumbel Exp $
**
** ClanLib Game SDK
** Copyright (C) 2003 The ClanLib Team
** For a total list of contributers see the file CREDITS.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**
*/
#ifdef _MSC_VER
#pragma warning (disable:4786)
#define snprintf _snprintf
#endif
#ifndef WIN32
#include <errno.h>
#endif
#include "socket_generic.h"
#include <stdio.h>
#include "API/Core/System/clanstring.h"
/////////////////////////////////////////////////////////////////////////////
// CL_Socket_KeepAliveHelper operations:
void CL_Socket_KeepAliveHelper::keep_alive()
{
// performance note: it would be much more efficient if we maintained a global
// list of all sockets instanciated, and then do one select for them all.
//
// I'm too lazy to do that - at least until it becomes a real performance problem.
// -- mbn 2. marts 2001
if (impl->valid == false)
return;
fd_set rfds, wfds, efds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
FD_SET(impl->sock, &rfds);
FD_SET(impl->sock, &wfds);
FD_SET(impl->sock, &efds);
timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int nread = 0;
char buf = 0;
int result = select(impl->sock+1, &rfds, &wfds, &efds, &tv);
if (result > 0)
{
if (FD_ISSET(impl->sock, &rfds))
{
// Peek and see if there is anydata on the socket, if not
// the remote side has disconnected.
nread = recv(impl->sock, &buf, 1, MSG_PEEK);
if(nread == 0)
{
sig_disconnected();
impl->disconnect();
return;
}
else
sig_read_triggered();
}
if (FD_ISSET(impl->sock, &wfds)) sig_write_triggered();
if (FD_ISSET(impl->sock, &efds)) sig_exception_triggered();
}
}
/////////////////////////////////////////////////////////////////////////////
// CL_Socket_Generic static operations:
CL_IPAddress CL_Socket_Generic::create_ip_address(const sockaddr_in &addr_in)
{
char port[32];
memset(port, 0, 32);
snprintf(port,6,"%d",ntohs(addr_in.sin_port));
char *addr = inet_ntoa(addr_in.sin_addr);
return CL_IPAddress((std::string)addr, (std::string)port);
}
/////////////////////////////////////////////////////////////////////////////
// CL_Socket_Generic construction:
CL_Socket_Generic::CL_Socket_Generic()
: sock(-1), read(NULL), write(NULL), exception(NULL), keep_alive_helper(0), ref_count(0), valid(true)
{
}
CL_Socket_Generic::~CL_Socket_Generic()
{
delete read;
delete write;
delete exception;
disconnect();
delete keep_alive_helper;
}
/////////////////////////////////////////////////////////////////////////////
// CL_Socket_Generic attributes:
/////////////////////////////////////////////////////////////////////////////
// CL_Socket_Generic operations:
void CL_Socket_Generic::add_ref()
{
ref_count++;
}
void CL_Socket_Generic::release_ref()
{
ref_count--;
if (ref_count == 0) delete this;
}
std::string CL_Socket_Generic::get_error_message()
{
#ifdef WIN32
int err = WSAGetLastError();
switch (err)
{
case WSAEACCES:
return "Permission denied";
case WSAEADDRINUSE:
return "Address already in use";
case WSAEADDRNOTAVAIL:
return "Cannot assign requested address";
case WSAEAFNOSUPPORT:
return "Address family not supported by protocol family";
case WSAEALREADY:
return "Operation already in progress";
case WSAECONNABORTED:
return "Software caused connection abort";
case WSAECONNREFUSED:
return "Connection refused";
case WSAECONNRESET:
return "Connection reset by peer";
case WSAEDESTADDRREQ:
return "Destination address required";
case WSAEFAULT:
return "Bad address";
case WSAEHOSTDOWN:
return "Host is down";
case WSAEINPROGRESS:
return "Operation now in progress";
case WSAEINTR:
return "Interrupted function call";
case WSAEINVAL:
return "Invalid argument";
case WSAEISCONN:
return "Socket is already connected";
case WSAEMFILE:
return "Too many open files";
case WSAEMSGSIZE:
return "Message too long";
case WSAENETDOWN:
return "Network is down";
case WSAENETRESET:
return "Network dropped connection on reset";
case WSAENETUNREACH:
return "Network is unreachable";
case WSAENOBUFS:
return "No buffer space available";
case WSAENOPROTOOPT:
return "Bad protocol option";
case WSAENOTCONN:
return "Socket is not connected";
case WSAENOTSOCK:
return "Socket operation on nonsocket";
case WSAEOPNOTSUPP:
return "Operation not supported";
case WSAEPFNOSUPPORT:
return "Protocol family not supported";
case WSAEPROCLIM:
return "Too many processes";
case WSAEPROTONOSUPPORT:
return "Protocol not supported";
case WSAEPROTOTYPE:
return "Protocol wrong type for socket";
case WSAESHUTDOWN:
return "Cannot send after socket shutdown";
case WSAESOCKTNOSUPPORT:
return "Socket type not supported";
case WSAETIMEDOUT:
return "Connection timed out";
// case WSATYPE_NOT_FOUND:
// return "Class type not found";
case WSAEWOULDBLOCK:
return "Resource temporarily unavailable";
case WSAHOST_NOT_FOUND:
return "Host not found";
// case WSA_INVALID_HANDLE:
// return "Specified event object handle is invalid";
// case WSA_INVALID_PARAMETER:
// return "One or more parameters are invalid";
// case WSAINVALIDPROCTABLE:
// return "Invalid procedure table from service provider";
// case WSAINVALIDPROVIDER:
// return "Invalid service provider version number";
// case WSA_IO_INCOMPLETE:
// return "Overlapped I/O event object not in signaled state";
// case WSA_IO_PENDING:
// return "Overlapped operations will complete later";
// case WSA_NOT_ENOUGH_MEMORY:
// return "Insufficient memory available";
case WSANOTINITIALISED:
return "Successful WSAStartup not yet performed";
case WSANO_DATA:
return "Valid name, no data record of requested type";
case WSANO_RECOVERY:
return "This is a nonrecoverable error";
// case WSAPROVIDERFAILEDINIT:
// return "Unable to initialize a service provider";
// case WSASYSCALLFAILURE:
// return "System call failure";
case WSASYSNOTREADY:
return "Network subsystem is unavailable";
case WSATRY_AGAIN:
return "Nonauthoritative host not found";
case WSAVERNOTSUPPORTED:
return "Winsock.dll version out of range";
case WSAEDISCON:
return "Graceful shutdown in progress";
// case WSA_OPERATION_ABORTED:
// return "Overlapped operation aborted";
default:
return CL_String::format("Unknown socket error %1", err);
}
#else
return std::string(strerror(errno));
#endif
}
/////////////////////////////////////////////////////////////////////////////
// CL_Socket_Generic overridables:
CL_EventTrigger_Socket *CL_Socket_Generic::create_read_trigger()
{
return new CL_EventTrigger_Socket(this, CL_EventTrigger_Socket::read);
}
CL_EventTrigger_Socket *CL_Socket_Generic::create_write_trigger()
{
return new CL_EventTrigger_Socket(this, CL_EventTrigger_Socket::write);
}
CL_EventTrigger_Socket *CL_Socket_Generic::create_exception_trigger()
{
return new CL_EventTrigger_Socket(this, CL_EventTrigger_Socket::exception);
}
void CL_Socket_Generic::disconnect()
{
if(sock != -1)
{
#ifdef WIN32
closesocket(sock);
#else
close(sock);
#endif
}
sock = -1;
valid = false;
}
/////////////////////////////////////////////////////////////////////////////
// CL_Socket_Generic implementation:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?