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

📄 connectionhandler.cpp

📁 swain-0.5.2.zip的源代码,比较好用,希望大家喜欢.
💻 CPP
字号:
/*
This file is part of SWAIN (http://sourceforge.net/projects/swain).
Copyright (C) 2006  Daniel Lindstr鰉 and Daniel Nilsson

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA  02110-1301, USA.
*/
#include "StdAfx.h"
#include "ConnectionHandler.h"

#include <stdio.h>

// This class is not a real packet it's just a marker that is put into the
// outgoing queue to signal that a connection should be closed.
class CloseConnection : public Packet {
public:
	CloseConnection(void) { }
	~CloseConnection(void) { }
	virtual void read(Socket *s, int size) { }
	virtual void write(Socket *s) { }
	virtual int getSize(void) { return 0; }
	virtual int getId(void) { return -1; }	// -1 should never be a valid packet id
};

ConnectionHandler::ConnectionHandler(PacketFactory *pf){
	InitializeCriticalSection(&lock);
	this->listen_socket = NULL;
	this->selector = new Select();
	this->selector->setTimeout(1000);
	this->run_t_listen = false;
	this->run_t_send = false;
	this->packetfactory = pf;
	for(int i=0; i<MAX_SOCKETS; i++){
		this->sockets[i] = NULL;
	}
	this->outgoing = new Queue();
	this->outgoing->setTimeout(1000);
	this->listen_thread = NULL;
	this->send_thread =  NULL;
}

ConnectionHandler::~ConnectionHandler(void){
	//ExitProcess(0); //tempon鋜t?
	this->run_t_listen = false;
	this->run_t_send = false;
	WaitForSingleObject(this->listen_thread, OBJECT_WAIT_TIME);
	WaitForSingleObject(this->send_thread, OBJECT_WAIT_TIME);
	selector->removeSockets();
	// TODO: close and delete all sockets
	if (listen_socket != NULL)
		delete(listen_socket);
	delete(selector);
	DeleteCriticalSection(&lock);
}

void ConnectionHandler::startListen(int port){
	if (listen_socket != NULL) {
		printf("ConnectionHandler::startListen: already listening!\n");
		return;
	}
	this->listen_socket = new Socket();
	this->listen_socket->startListen(port);
	this->selector->addSocket(this->listen_socket);
}

void ConnectionHandler::stopListen(){
	if (listen_socket == NULL) {
		printf("ConnectionHandler::stopListen: not listening!\n");
		return;
	}
	this->selector->removeSocket(this->listen_socket);
	listen_socket->close();
	delete listen_socket;
	listen_socket = NULL;
}


void ConnectionHandler::startReceive(){
	LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
	SIZE_T threadStackSize = 0;
	this->run_t_listen = true;
	this->listen_thread = CreateThread(lpThreadAttributes, threadStackSize, listen, (LPVOID)this, 0, NULL);
}


void ConnectionHandler::startSend(void){
	LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
	SIZE_T threadStackSize = 0;
	this->run_t_send = true;
	this->send_thread = CreateThread(lpThreadAttributes, threadStackSize, send, (LPVOID)this, 0, NULL);
}


void ConnectionHandler::stopReceive(){
	run_t_listen = false;
}

void ConnectionHandler::stopSend(){
	this->run_t_send = false;
}
int ConnectionHandler::addSocket(Socket *s){
	int i;
	EnterCriticalSection(&lock);
	for(i=0; i<MAX_SOCKETS; i++){
		if(sockets[i] == NULL){
			sockets[i] = s;
			break;
		}
	}
	LeaveCriticalSection(&lock);
	if (i >= MAX_SOCKETS) {
		printf("ConnectionHandler::addSocket: too many sockets!\n");
		return -1;
	}
	selector->addSocket(s);
	return i;
}

void ConnectionHandler::removeSocket(Socket *s){
	int i;
	this->selector->removeSocket(s);
	EnterCriticalSection(&lock);
	for (i = 0; i < MAX_SOCKETS; i++) {
		if (sockets[i] == s) {
			sockets[i] = NULL;
			break;
		}
	}
	LeaveCriticalSection(&lock);
	if (i >= MAX_SOCKETS) {
		printf("ConnectionHandler::removeSocket: socket not found!\n");
	}
}

Socket *ConnectionHandler::getSocket(int cid) {
	Socket *s;
	EnterCriticalSection(&lock);
	s = sockets[cid];
	LeaveCriticalSection(&lock);
	if (s == NULL) {
		printf("ConnectionHandler::getSocket: cid %d is not a valid socket!\n", cid);
	}
	return s;
}

int ConnectionHandler::getCid(Socket *s) {
	int i;
	EnterCriticalSection(&lock);
	for (i = 0; i < MAX_SOCKETS; i++) {
		if (sockets[i] == s) {
			break;
		}
	}
	LeaveCriticalSection(&lock);
	if (i >= MAX_SOCKETS) {
		printf("ConnectionHandler::getCid: socket not found!\n");
		return -1;
	}
	return i;
}

void ConnectionHandler::closeConnection(int cid){
	if (cid < 0 || cid >= MAX_SOCKETS) {
		printf("Bad cid %d\n", cid);
		return;
	}
	// Put a dymmy packet into the queue,
	// the connection will be closed when the dummy packet is dequeued.
	// This hack is to aviod a race condition when one thread closes the
	// connection before all enqueued packets are sent by the send thread.
	CloseConnection *cc = new CloseConnection();
	cc->setCId(cid);
	sendPacket(cc);
}

int ConnectionHandler::connectTo(const char *addr, short port){
	Socket *s = new Socket();
	int ret = -1;
	if (!s->connectTo(addr, port)) {
		delete s;
		return ret;
	}
	ret = this->addSocket(s);
	return ret;
}

void ConnectionHandler::setPacketHandler(PacketHandler *ph){
	if(ph == NULL)
		throw "packethandler = NULL";
	this->packethandler = ph;
	this->packethandler->setConnectionHandler(this);
}

void ConnectionHandler::startHandle(void){
	this->packethandler->startHandle();
}
void ConnectionHandler::stopHandle(void){
	this->packethandler->stopHandle();
}

DWORD WINAPI ConnectionHandler::listen(LPVOID lpParameter){
	ConnectionHandler *ch = (ConnectionHandler *)lpParameter;
	Socket *s = NULL, *newsock = NULL;
	int cid = 0;
	Packet *packet = NULL;
	short int id, size;

	while(ch->run_t_listen){
		if(NULL == (s = ch->selector->doSelect()))
			continue;
		else{
			//New incoming connection
			if(s == ch->listen_socket){
				if(NULL == (newsock = s->acceptConnection())){
					printf("Could not accept connection.\n");
					continue;
				}
				cid = ch->addSocket(newsock);
				ch->packethandler->newConnection(cid);
			}
			//Packet Recieved from a socket
			else{
				int cid = ch->getCid(s);
				if (cid != -1) {
					if (!s->receiveShort(&id) || !s->receiveShort(&size)) {
						printf("Error receiving header, closing connection %d\n", cid);
						ch->closeConnection(cid);
						continue;
					}
					packet = ch->packetfactory->makePacket(id);
					if (packet != NULL) {
						packet->read(s, size);
						packet->setCId(cid);
						ch->packethandler->handle(packet);
					} else {
						printf("Unknown packet (id=%d, size=%d)!\n", id, size);
						s->discardData(size);
					}
				}
			}		
		}
	}
	return NULL;
}

DWORD WINAPI ConnectionHandler::send(LPVOID lpParameter){
	ConnectionHandler *ch = (ConnectionHandler *)lpParameter;
	Packet *packet = NULL;
	Socket *s = NULL;

	while(ch->run_t_send){
		packet = (Packet *)ch->outgoing->dequeue();
		if(packet == NULL)
			continue;
		s = ch->getSocket(packet->getCId());
		if (packet->getId() == -1) {	// The special dymmy packet for closing connections
			if (s != NULL) {
				ch->packethandler->closedConnection(packet->getCId());
				s->close();
				ch->removeSocket(s);
				printf("Connection %d closed!\n", packet->getCId());
				delete s;
			} else {
				printf("Trying to close nonexisting connection %d, ignoring...\n", packet->getCId());
			}
			delete packet;
			continue;
		}
		if (s == NULL) {
			printf("Packet send to nonexisting connection %d, dropping it...\n", packet->getCId());
			delete packet;
			continue;
		}
		s->sendShort(packet->getId());
		s->sendShort(packet->getSize());
		packet->write(s);
		delete(packet);
	}
	return NULL;
}


void ConnectionHandler::sendPacket(Packet *p){
	this->outgoing->enqueue(p);
}


int ConnectionHandler::getAddresByCId(int cid){
	Socket *s = getSocket(cid);
	if (s == NULL) {
		return 0;
	} else {
		return s->getInetAddr();
	}
}

⌨️ 快捷键说明

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