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

📄 tcpsocket.cpp

📁 WOW 服务模拟端 支持2.4.3版本 来自开源的ASCENT 自己REPACK
💻 CPP
字号:
/****************************************************************************
 *
 * Multiplatform High-Performance Async Network Library
 * Implementation of TCP Socket
 * Copyright (c) 2007 Burlex
 *
 * This file may be distributed under the terms of the Q Public License
 * as defined by Trolltech ASA of Norway and appearing in the file
 * COPYING included in the packaging of this file.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 */

#include "Network.h"

TcpSocket::TcpSocket(int fd, size_t readbuffersize, size_t writebuffersize, bool use_circular_buffer, const sockaddr_in * peer)
{
	SetFd(fd);
	if(use_circular_buffer)
	{
		// m_writeBuffer = new CircularBuffer;
		// m_readBuffer = new CircularBuffer;
		m_writeBuffer = new StraightBuffer;
		m_readBuffer = new StraightBuffer;
	}
	else
	{
		m_writeBuffer = new StraightBuffer;
		m_readBuffer = new StraightBuffer;
	}

	m_writeBuffer->Allocate(writebuffersize);
	m_readBuffer->Allocate(readbuffersize);
	memcpy(&m_peer, peer, sizeof(sockaddr));

	/* switch the socket to nonblocking mode */
	u_long arg = 1;
	ioctlsocket(fd, FIONBIO, &arg);
	m_writeLock = 0;
	m_deleted = false;
	m_connected = true;

	/* disable nagle buffering by default */
	int arg2 = 1;
	setsockopt(m_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&arg2, sizeof(int));
}

TcpSocket::~TcpSocket()
{
	delete m_writeBuffer;
	delete m_readBuffer;
}

void TcpSocket::OnRead(size_t len)
{
	/* This is called when the socket engine gets an event on the socket */

#ifdef NETLIB_IOCP
	if(!len)
	{
		/* socket disconnected */
		Disconnect();
		return;
	}

	/* IOCP is easy. */
	if(len != 0xFFFFFFFF)
		m_readBuffer->IncrementWritten(len);

	/* Wewt, we read again! */
	OnRecvData();

	if(!IsConnected())
		return;

	/* Setup another read event */
	WSABUF buf;
	buf.buf = (char*)m_readBuffer->GetBuffer();
	buf.len = m_readBuffer->GetSpace();

	DWORD recved;
	DWORD flags = 0;
	Overlapped * ov = new Overlapped;
	memset(ov, 0, sizeof(Overlapped));
	ov->m_op = IO_EVENT_READ;

	if(WSARecv(m_fd, &buf, 1, &recved, &flags, &ov->m_ov, 0) == SOCKET_ERROR)
	{
        if(WSAGetLastError() != WSA_IO_PENDING)
			Disconnect();
	}

#else

	/* Any other platform, we have to call recv() to actually get the data. */
	int bytes = recv(m_fd, (char*)m_readBuffer->GetBuffer(), m_readBuffer->GetSpace(), 0);

	/* Under some socket engines, if this returns 0, we're in deep poo poo. */
	/* Check if recv() failed. */
	if(bytes <= 0)
		Disconnect();			// whoopes. :P
	else
	{
		m_readBuffer->IncrementWritten(bytes);
		OnRecvData();
	}

#endif
}

void TcpSocket::OnWrite(size_t len)
{
	/* Lock the buffer so nothing can modify it */
	LockWriteBuffer();

	/* This is called when the socket engine gets an event on the socket */
#ifdef NETLIB_IOCP

	/* Data has already been output to the socket, we can clear the buffer */
	if(!len)
	{
		Disconnect();
		return;
	}

	m_writeBuffer->Remove(len);

	/* Do we still have data to write? */
	if(m_writeBuffer->GetSize())
		sSocketEngine.WantWrite(this);
	else
		InterlockedDecrement(&m_writeLock);

#else
	/* Push as much data out as we can in a nonblocking fashion. */
	int bytes = send(m_fd, (const char*)m_writeBuffer->GetBufferOffset(), m_writeBuffer->GetSize(), 0);

	if(bytes < 0)
		Disconnect();
	else
		m_writeBuffer->Remove(bytes);
#endif

	/* Unlock the write buffer, we're finished */
	UnlockWriteBuffer();
}

void TcpSocket::Finalize()
{
	sSocketEngine.AddSocket(this);
	OnConnect();
}

bool TcpSocket::Write(const void * data, size_t bytes)
{
	if(!m_connected)
		return false;

	bool rv = m_writeBuffer->Write(data, bytes);
	if(rv)
	{
#ifdef NETLIB_IOCP
		/* On windows since you have multiple threads this has to be guarded. */
		if(InterlockedCompareExchange(&m_writeLock, 1, 0) == 0)
			sSocketEngine.WantWrite(this);
#else
		if(!m_writeLock)
		{
			++m_writeLock;
			sSocketEngine.WantWrite(this);
		}
#endif
	}

    return rv;
}

void TcpSocket::Disconnect()
{
	if(!m_connected) return;
	m_connected = false;

	OnDisconnect();
	sSocketEngine.RemoveSocket(this);
	shutdown(m_fd, SD_BOTH);
	closesocket(m_fd);

	if(!m_deleted)
		Delete();
}

void TcpSocket::Delete()
{
	if(m_deleted) return;
	m_deleted = true;

	sSocketDeleter.Add(this);
	if(m_connected) Disconnect();
}

void TcpSocket::OnError(int errcode)
{
	/* Bleh.. :p */
	Disconnect();
}

bool TcpSocket::Writable()
{
	return (m_writeBuffer->GetSize() > 0) ? true : false;
}

⌨️ 快捷键说明

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