⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket.cpp

📁 Linux socket 编程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* socket.cpp
 *
 * Copyright (c) 2000 Sean Walton and Macmillan Publishers.  Use may be in
 * whole or in part in accordance to the General Public License (GPL).
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
*/

/*****************************************************************************/
/*** socket.cpp                                                            ***/
/***                                                                       ***/
/*** Implements the C++ socket framework.                                  ***/
/*****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include "socket.h"

///////////////////////////////////////////////////////////////////////////////
/// SimpleString
//-----------------------------------------------------------------------------
//--- Constructors & Destructors
SimpleString::SimpleString(const char* s)
{
	Length = strlen(s);
	Buffer = new char[Length+1];
	strcpy(Buffer, s);
}

SimpleString::SimpleString(const SimpleString& s)
{
	Length = s.GetLength();
	Buffer = new char[Length+1];
	strcpy(Buffer, s.GetString());
}

SimpleString::~SimpleString(void)
{
	delete Buffer;
}

//-----------------------------------------------------------------------------
//--- Operator overload support
void SimpleString::Append(const char* s)
{
	Length += strlen(s);
	char *tmps=new char[Length+1];
	strcpy(tmps, Buffer);
	strcat(tmps, s);
	delete Buffer;
	Buffer = tmps;
}

void SimpleString::Append(const SimpleString& s)
{
	Length += s.GetLength();
	char *tmps=new char[Length+1];
	strcpy(tmps, Buffer);
	strcat(tmps, s.GetString());
	delete Buffer;
	Buffer = tmps;
}

///////////////////////////////////////////////////////////////////////////////
/// Exception
//-----------------------------------------------------------------------------
//--- Specific Implementation
void Exception::PrintException(void) const
{
	fprintf(stderr, "%s", Msg.GetString());
	if ( ErrNo != 0 )
	{
		errno = ErrNo;
		perror("-- Error");
	}
	else
		printf("\n");
}

///////////////////////////////////////////////////////////////////////////////
/// HostAddress
//-----------------------------------------------------------------------------
//--- Constructors & Destructors
HostAddress::HostAddress(const char* Name, ENetwork network)
{
	switch ( network )
	{
		case eIPv4:
		{	long s_addr;
			int port = 0;

			if ( Name != 0 )
			{
				char *portname = strrchr(Name, ':');
				if ( portname != 0  &&  (port = atoi(portname+1)) > 0 )
					*portname = 0;
				struct hostent *host = gethostbyname(Name);
				if ( host == NULL )
					throw NetDNSException(SimpleString("gethostbyname [") + Name + "]");
				s_addr = *reinterpret_cast<long*>(host->h_addr);
			}
			else
				s_addr = INADDR_ANY;
			struct sockaddr_in *addr = new struct sockaddr_in();
			addr->sin_family = network;
			addr->sin_port = htons(port);
			addr->sin_addr.s_addr = s_addr;
			Addr = reinterpret_cast<struct sockaddr*>(addr);
			break;
		}
		case eIPv6:
		{
			struct sockaddr_in6 *addr = new struct sockaddr_in6();
			addr->sin6_family = network;
			addr->sin6_port = 0;
			if ( Name == 0 )
				Name = "0::0";
			if ( inet_pton(eIPv6, Name, &addr->sin6_addr) == 0 )
				throw NetConversionException(SimpleString("inet_pton failed [") + Name + "]");
			Addr = reinterpret_cast<struct sockaddr*>(addr);
			break;
		}
		default :
			throw Exception("Network type not supported", ENOTSUP);
	}
	Network = network;
}

HostAddress::HostAddress(HostAddress& Address)
{
	switch ( Network )
	{
		case eIPv4:
		{
			Network = Address.Network;
			struct sockaddr_in *addr = new struct sockaddr_in();
			memcpy(addr, Address.Addr, sizeof(*addr));
			Addr = reinterpret_cast<struct sockaddr*>(addr);
			break;
		}
		case eIPv6:
		{
			Network = Address.Network;
			struct sockaddr_in6 *addr = new struct sockaddr_in6();
			memcpy(addr, Address.Addr, sizeof(*addr));
			Addr = reinterpret_cast<struct sockaddr*>(addr);
			break;
		}
	}
}

HostAddress::~HostAddress(void)
{
	delete Addr;
}

//-----------------------------------------------------------------------------
//--- Specific Implementation
void HostAddress::SetPort(int Port)
{
	switch ( Network )
	{
		case eIPv4:
		{
			struct sockaddr_in *inet = reinterpret_cast<struct sockaddr_in*>(Addr);
			inet->sin_port = htons(Port);
			break;
		}
		case eIPv6:
		{
			struct sockaddr_in6 *inet6 = reinterpret_cast<struct sockaddr_in6*>(Addr);
			inet6->sin6_port = htons(Port);
			break;
		}
	}
}

int HostAddress::GetPort(void) const
{
	switch ( Network )
	{
		case eIPv4: return (reinterpret_cast<struct sockaddr_in*>(Addr))->sin_port;
		case eIPv6: return (reinterpret_cast<struct sockaddr_in6*>(Addr))->sin6_port;
	}
}

int HostAddress::GetSize(void) const
{
	switch ( Network )
	{
		case eIPv4: return sizeof(struct sockaddr_in);
		case eIPv6: return sizeof(struct sockaddr_in6);
	}
}

int HostAddress::operator ==(HostAddress& Address) const
{
	if ( Network != Address.Network )
		return 0;
	switch ( Network )
	{
		case eIPv4:
		case eIPv6: return (memcmp(Addr, Address.Addr, GetSize()) == 0);
		default: return 0;
	}
}

const char* HostAddress::GetHost(bool byName)
{
	switch ( Network )
	{
		case eIPv4:
		{
			char *name;
			struct sockaddr_in *inet = reinterpret_cast<struct sockaddr_in*>(Addr);

			if ( byName )
			{
				char *addr = reinterpret_cast<char*>(&(inet->sin_addr.s_addr));
				int size = sizeof(inet->sin_addr.s_addr);
				struct hostent *host = gethostbyaddr(addr, size, GetNetwork());
				if ( host == NULL )
					throw NetDNSException(SimpleString("gethostbyaddr failed for [") +
						inet_ntoa(inet->sin_addr) + "]");
				name = host->h_name;
			}
			else
				name = inet_ntoa(inet->sin_addr);
			sprintf(HostName, "%s:%d", name, (inet->sin_port));
			break;
		}
		case eIPv6:
		{
			struct sockaddr_in6 *inet6 = reinterpret_cast<struct sockaddr_in6*>(Addr);
			inet_ntop(GetNetwork(), Addr, HostName, MaxHostName);
			char TempS[10];
			sprintf(TempS, ":%d", inet6->sin6_port);
			strncat(HostName, TempS, MaxHostName);
			break;
		}
		default: strncpy(HostName, "<unsupported>", MaxHostName); break;
	}
	HostName[MaxHostName-1] = 0;
	return HostName;
}

///////////////////////////////////////////////////////////////////////////////
/// TextMessage
//-----------------------------------------------------------------------------
//--- Constructors & Destructors
TextMessage::TextMessage(unsigned short Bytes)
{
	Buffer = new char[Bytes];
	Available = Size = Bytes;
}

TextMessage::TextMessage(const char* Msg, unsigned short Len)
{
	if ( Len == 0 )
		Len = strlen(Msg)+1;
	Buffer = new char[Len];
	memcpy(Buffer, Msg, Len);
	Available = Size = Len;
}

TextMessage::~TextMessage(void)
{
	delete Buffer;
}

//-----------------------------------------------------------------------------
//--- Operator overload support
void TextMessage::SetString(const char* str, int len)
{
	if ( len <= 0 )
		len = strlen(str)+1;
	if ( len >= Available )
	{
		delete Buffer;
		Buffer = new char[len];
		Available = len;
	}
	Size = len;
	strcpy(Buffer, str);
}

void TextMessage::Append(const char* str, int len)
{
	if ( len <= 0 )
		len = strlen(str);
	if ( Size+len > Available )
	{
		char *B = new char[Size+len];
		strcpy(B, Buffer);
		delete Buffer;
		Buffer = B;
		Available = Size+len;
	}
	Size += len;
	strcat(Buffer, str);
}

//-----------------------------------------------------------------------------
//--- Specific Implementation
char *TextMessage::Wrap(int& Bytes) const
{
	Bytes = Size;
	char *data = new char[Size];
	strcpy(data, Buffer);
	return data;
}

bool TextMessage::Unwrap(char *Data, int Bytes, int MsgNum)
{
	if ( MsgNum > 1 )
		Append(Data, Bytes-1);
	else
		SetString(Data, Bytes);
	return reinterpret_cast<bool>(Data[Bytes-1] == 0);
}

///////////////////////////////////////////////////////////////////////////////
/// Socket
//-----------------------------------------------------------------------------
//--- Constructors & Destructors
Socket::Socket(ENetwork Network, EProtocol Protocol)
{
	SD = socket(Network, Protocol, 0);
	if ( SD < 0 )
		throw NetException("Could not create socket");
}

Socket::Socket(Socket& sock)
{
	int err;
	socklen_t size=sizeof(err);
	if ( getsockopt(SD, SOL_SOCKET, SO_ERROR, &err, &size) != 0 )
		throw NetException("Socket error");
	if ( (SD = dup(sock.SD)) < 0 )
		throw FileException("Can't copy socket");
}

Socket::~Socket(void)
{
	if ( close(SD) != 0 )
		throw FileException("Can't close socket");
}

//-----------------------------------------------------------------------------
//--- Specific Implementation
void Socket::Bind(HostAddress& Addr)
{
	if ( bind(SD, Addr.GetAddress(), Addr.GetSize()) != 0 )
		throw NetConnectException("Could not bind socket");
}

int  Socket::Send(Message& Msg, int Options) const
{
	int bytes;
	char *buf = Msg.Wrap(bytes);
	bytes = send(SD, buf, bytes, Options);
	delete buf;
	if ( bytes < 0 )
		throw NetIOException("Could not send message");
	return bytes;
}

int  Socket::Send(HostAddress& Addr, Message& Msg, int Options) const
{
	int bytes;
	char *buf = Msg.Wrap(bytes);
	bytes = sendto(SD, buf, bytes, Options, Addr.GetAddress(), Addr.GetSize());
	delete buf;
	if ( bytes < 0 )
		throw NetIOException("Could not send directed message");
	return bytes;
}

int  Socket::Receive(Message& Msg, int Options) const
{	const int BufferSize = 65536;
	bool done;
	int bytes, cnt=0;
	char *buf = new char[BufferSize];
	do
	{
		bytes = recv(SD, buf, BufferSize, Options);
		if ( bytes < 0 )
		{
			delete buf;
			throw NetIOException("Could could get message");
		}
		cnt++;
		done = Msg.Unwrap(buf, bytes, cnt);
	}
	while ( !done );
	delete buf;
	return bytes;
}

int  Socket::Receive(HostAddress& Addr, Message& Msg, int Options) const
{	const int BufferSize = 65536;
	socklen_t len = Addr.GetSize();
	bool done;
	int bytes, cnt=0;
	char *buf = new char[BufferSize];
	do
	{
		bytes = recvfrom(SD, buf, BufferSize, Options, Addr.GetAddress(), &len);
		if ( bytes < 0 )
		{
			delete buf;
			throw NetIOException("Could could get message");
		}
		cnt++;
		done = Msg.Unwrap(buf, bytes, cnt);
	}
	while ( !done );
	delete buf;
	return bytes;
}

//-----------------------------------------------------------------------------
//--- Class configuration (CRUD)
void Socket::PermitRoute(bool Setting)
{
	int val = (Setting == 0);
	if ( setsockopt(SD, SOL_SOCKET, SO_DONTROUTE, &val, sizeof(val)) != 0 )
		throw NetConfigException("Socket Option: set DONTROUTE");
}

void Socket::KeepAlive(bool Setting)
{
	int val = (Setting != 0);
	if ( setsockopt(SD, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) != 0 )
		throw NetConfigException("Socket Option: set KEEPALIVE");
}

void Socket::ShareAddress(bool Setting)
{
	int val = (Setting != 0);
	if ( setsockopt(SD, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) != 0 )
		throw NetConfigException("Socket Option: set REUSEADDR");
}

int  Socket::GetReceiveSize(void)
{
	int val;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -