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

📄 netsocket.cpp

📁 vc++6.0开发网络典型应用实例导航 1. 本光盘提供了本书中所有的实例源程序文件。 2. 附录文件夹下是Winsock 函数参考以及错误码列表
💻 CPP
字号:
// NetSocket.cpp : implementation file
//

#include "stdafx.h"
#include "Netmsg.h"
#include "NetSocket.h"
#include "ContactView.h"
#include "Conversation.h"
#include "ConversationThread.h"
#include "SoundThread.h"
#include "FileSend.h"
#include <mmsystem.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//The class for contact sockets

CNetSocket::CNetSocket()
{
	m_nTimeOut = 5000;
	Contact = NULL;
	m_pFile = NULL;
	m_pArchiveIn = NULL;
	m_pArchiveOut = NULL;
	GetApp()->Sockets.AddTail(this);
}

CNetSocket::CNetSocket(CContact *contact)
{
	m_nTimeOut = 5000;
	Contact = contact;
	if (Contact->GetSock())
	{
		if (Contact->GetSock() != this)
		{
			if (::IsSocket(Contact->GetSock()))
			delete Contact->GetSock();
		}
	}
	Contact->SetSock(this);
	m_pFile = NULL;
	m_pArchiveIn = NULL;
	m_pArchiveOut = NULL;
	GetApp()->Sockets.AddTail(this);
}

CNetSocket::~CNetSocket()
{
	if (m_pArchiveOut != NULL)
	{
		m_pArchiveOut->Abort();
		delete m_pArchiveOut;
		m_pArchiveOut = NULL;
	}

	if (m_pArchiveIn != NULL)
	{
		m_pArchiveIn->Abort();
		delete m_pArchiveIn;
		m_pArchiveIn = NULL;
	}

	if (m_pFile != NULL)
		delete m_pFile;

	GetApp()->Sockets.RemoveAt(GetApp()->Sockets.Find(this));
}


// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CNetSocket, CSocket)
	//{{AFX_MSG_MAP(CNetSocket)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif	// 0

/////////////////////////////////////////////////////////////////////////////
// CNetSocket member functions


void CNetSocket::OnClose(int nErrorCode) 
{
	CSocket::OnClose(nErrorCode);
	
	if (Contact->Flags & CFL_AUTHENTICATE_NO)
	{
		GetApp()->View->DeleteContact(Contact);
		return;
	}

	Contact->SignOffline();	
}

void CNetSocket::Init()
{
	m_pFile = new CSocketFile(this);
	m_pArchiveIn = new CArchive(m_pFile, CArchive::load);
	m_pArchiveOut = new CArchive(m_pFile, CArchive::store);
}

void CNetSocket::OnReceive(int nErrorCode) 
{
	if (!IsSocket(this))
		return;

	CSocket::OnReceive(nErrorCode);
	TRY
	{
		do
		{
			CContact *pContact = Contact;
			CString tmp;
			m_pArchiveIn->ReadString(tmp);

#ifdef _DEBUG
			FILE *f = fopen("socklog.txt", "a");
			if (f)
			{
				fprintf(f, "IN: %s [%s]: %s\n", Contact->GetScreenName(), Contact->GetHostName().Get(), tmp);
				fclose(f);
			}
#endif
			Process(tmp);
			if (!IsSocket(this))
				return; //this class was destroyed while we were processing, get out.
		}
		while (!m_pArchiveIn->IsBufferEmpty());
	}
	CATCH(CFileException, e)
	{
		m_pArchiveOut->Abort();
		return;
	}
	END_CATCH
}

void CNetSocket::SendString(char *fmt, ...)
{
	va_list args;
	va_start(args, fmt);
	SendStringV(fmt, args);
}

void CNetSocket::SendStringV(char *fmt, va_list args)
{
	if (!IsSocket(this))
		return;
	if (!CAsyncSocket::FromHandle(m_hSocket))
		return;

	CString Sends;

	Sends.FormatV(fmt, args);
	Sends += "\n";
	TRY
	{
#ifdef _DEBUG
		FILE *f = fopen("socklog.txt", "a");
		if (f)
		{
			fprintf(f, "OUT: %s [%s]: %s", Contact->GetScreenName(), Contact->GetHostName().Get(), Sends);
			fclose(f);
		}
#endif
		m_pArchiveOut->WriteString(Sends);
		m_pArchiveOut->Flush();
	}
	CATCH (CFileException, e)
	{
		m_pArchiveOut->Abort();
		return;
	}
	END_CATCH
}

bool CNetSocket::Open()
{
	if (!Create()) return false;

	if (!Contact) return false;

	if (!Connect(Contact->GetHostName().Get(), 8400)) return false;

	m_pFile = new CSocketFile(this);
	Contact->WeConnected = true;

	m_pArchiveIn = new CArchive(m_pFile, CArchive::load);
	m_pArchiveOut = new CArchive(m_pFile, CArchive::store);

	Contact->SetSock(this);

	::SendMyOnline(Contact);

	return true;
}

void ::SendMyOnline(CContact *To)
{
	char font[512];
	uital2(&GetApp()->View->Me.uFont, sizeof(USERFONT), font);
	if (!To)
	{
		SendToAllOnline(false, false, "NAME %s", GetApp()->View->Me.GetScreenName());

		if (GetApp()->View->Me.IsAway())
		SendToAllOnline(false, false, "AWAY %s", GetApp()->View->Me.GetAwayReason());
		
		SendToAllOnline(false, false, "FONT %s", font); 
	}
	else
	{
		if ((To->IsBlocked()) || (GetApp()->View->Me.IsOffline())) return;
		if (!IsSocket(To->GetSock())) return;
		To->GetSock()->SendString("NAME %s", GetApp()->View->Me.GetScreenName());
		if (GetApp()->View->Me.IsAway())
		To->GetSock()->SendString("AWAY %s", GetApp()->View->Me.GetAwayReason());
		To->GetSock()->SendString("FONT %s", font);
	}
}

void CNetSocket::Process(CString data)
{
	if (!IsSocket(this))
		return;

	char Data[2128];
	strcpy(Data, data);
	char Process[64], Message[2048];
	strcpy(Process, strtok(Data, " "));
	char *msg = strtok(NULL, "");
	if (msg) strcpy(Message, msg);
	else strcpy(Message, "");
	if (!strcmp(Process, "NAME"))
	{
		Contact->SetScreenName(Message);

		GetApp()->View->BuildList();
		if (Contact->IsOnline()) return;

		if (Contact->Flags & CFL_AUTHENTICATE_NO)
		{
			Contact->Flags &= ~CFL_AUTHENTICATE_NO;

			char buf[512];
			sprintf(buf, "A connection from %s was recieved, \
this address is not in your contact list, do you wish to add it? \
If not the contact will remain on your list blocked.", Contact->GetHostName().Get());
			if (MessageBox(GetApp()->View->mainWnd->GetSafeHwnd(), buf, 
				"New Contact", MB_YESNO|MB_ICONQUESTION) == IDYES)
			{
				if (!IsSocket(this)) return;
			}
			else
			{
				if (!IsSocket(this)) return;
				Contact->Flags |= CFL_BLOCKED;
			}
			::SendMyOnline(Contact);
		}

		Contact->ShowOnline();
		return;
	}
	else if (!strcmp(Process, "OFFLINE"))
	{
		Contact->WeConnected = false;
		if (Contact->IsOffline()) return;
		Contact->ShowOffline();
		return;
	}
	else if (!strcmp(Process, "MESSAGE"))
	{
		if (Contact->IsBlocked())
		{
			SendString("ERROR You are blocked");
			return;
		}
		if (Contact->IsConvWindowOpen())
		{
			Contact->pThread->Conv->SendMessage(WM_RECEIVEDMESSAGE, 0, (LPARAM) nstrdup(Message));
		}
		else
		{
			GetApp()->View->NewConversation(Contact, nstrdup(Message));
		}
		return;
	}
	else if (!strcmp(Process, "TYPING"))
	{
		if (Contact->IsBlocked())
		{
			SendString("ERROR You are blocked");
			return;
		}

		if (Contact->IsConvWindowOpen())
		{
			Contact->pThread->Conv->SendMessage(WM_TYPENOTIFY, 1, 0);
		}
		return;
	}
	else if (!strcmp(Process, "NOTTYPING"))
	{
		if (Contact->IsBlocked())
		{
			SendString("ERROR You are blocked");
			return;
		}

		if (Contact->IsConvWindowOpen())
		{
			Contact->pThread->Conv->SendMessage(WM_TYPENOTIFY, 0, 0);
		}
		return;
	}
	else if (!strcmp(Process, "FILE"))
	{
		char buf[1024], len[64], port[64], filename[1024], *tport, *tlen, *tfilename;
		CContact *pContact = Contact;
		tport = strtok(Message, " ");
		tlen = strtok(NULL, " ");
		tfilename = strtok(NULL, "");

		if (Contact->IsBlocked())
		{
			SendString("ERROR You are blocked");
			return;
		}

		if (!tport || !tlen || !tfilename)
		{
			SendString("ERROR Invalid FONT format");
			return;
		}
		else if (atoi(tport) < 1 || strtoul(tlen, NULL, 10) <= 0 || !stricmp(tfilename, ""))
		{
			SendString("ERROR Invalid FONT format");
			return;
		}

		strcpy(port, tport);
		strcpy(len, tlen);
		strcpy(filename, tfilename);
		sprintf(buf, "The user %s is trying to send you a file called '%s', click OK to accept or Cancel to decline", Contact->GetScreenName(), filename);
		int result = MessageBox(Contact->IsConvWindowOpen() ? Contact->pThread->Conv->GetSafeHwnd() :
		GetApp()->View->GetSafeHwnd(), buf, "File transfer", MB_OKCANCEL|MB_ICONINFORMATION);

		if (!IsSocket(this)) 
			return;

		if (result == IDOK)
		{
			if (pContact->IsOffline()) 
			{
				MessageBox(NULL, "This user has gone offline", "Send file", MB_OK|MB_ICONSTOP);
				return;
			}
			SendString("FILEXFEROK");
			GetApp()->View->StartFileTransfer(GetApp()->View->GetSafeHwnd(), Contact, false, filename, atoi(port), strtoul(len, NULL, 10));
		}
		else
		{
			if (pContact->IsOffline()) 
			{
				return;
			}
			SendString("FILEXFERCANCEL");
		}
		return;
	}
	else if (!strcmp(Process, "FONT"))
	{// this could reeally go wrong if something was sent wrong, use SOME checking.
		if (Contact->IsBlocked())
		{
			SendString("ERROR You are blocked");
			return;
		}

		if (strlen(Message) != (sizeof(USERFONT) * 2))
		{ 
			SendString("ERROR Bad USERFONT size");
			return;
		}
		else
		{
			uifal2(&Contact->uFont, sizeof(USERFONT), Message);
			PluginsContactStatusChanged(Contact, CT_FONT);
		}
	}
	else if (!strcmp(Process, "FILEXFEROK"))
	{
		if (Contact->IsBlocked())
		{
			SendString("ERROR You are blocked");
			return;
		}

		if (Contact->IsTransfering())
		{
			if (Contact->Transfer->Sending)
				Contact->Transfer->TransferAccepted();
		}
		return;
	}
	else if (!strcmp(Process, "FILEXFERCANCEL"))
	{
		if (Contact->IsBlocked())
		{
			SendString("ERROR You are blocked");
			return;
		}

		if (Contact->IsTransfering())
		{
			if (Contact->Transfer->Sending)
				Contact->Transfer->TransferFailed();
		}
		return;
	}
	else if (!strcmp(Process, "CANCELXFER"))
	{
		if (Contact->IsBlocked())
		{
			SendString("ERROR You are blocked");
			return;
		}

		if (Contact->IsTransfering())
			Contact->Transfer->TransferFailed();
		return;
	}
	else if (!strcmp(Process, "TRANSFERCOMPLETE"))
	{
		//we don't need to be told this anymore, leave for protoctl compatibility
	}
	else if (!strcmp(Process, "AWAY"))
	{
		if (Contact->IsBlocked())
		{
			SendString("ERROR You are blocked");
			return;
		}

		Contact->SetAway(true, Message);
	}
	else if (!strcmp(Process, "BACK"))
	{
		if (Contact->IsBlocked())
		{
			SendString("ERROR You are blocked");
			return;
		}

		Contact->SetAway(false, Message);
	}

	else if (!strcmp(Process, "ERROR"))
	{
#ifdef _DEBUG
		FILE *f = fopen("socklog.txt", "a");
		if (f)
		{
			fprintf(f, "ERROR: %s [%s]: %s\n", Contact->GetScreenName(), Contact->GetHostName().Get(), Message);
			fclose(f);
		}
#endif		
	}

}

bool ::IsSocket(CNetSocket *Sock)
{
	if (!Sock) return false;
	POSITION pos;
	pos = GetApp()->Sockets.GetHeadPosition();
	while (pos)
	{
		if (GetApp()->Sockets.GetNext(pos) == Sock)
			return true;
	}
	return false;
}

⌨️ 快捷键说明

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