Пример #1
0
HRESULT AnimObject::LoadMeshFromXFile(char* filename){
	if(!MeshType && !myMesh){
		MeshType = new AnimMesh(GetDevice());
		if(FAILED(MeshType->LoadModelsFromXFile(filename , false))){
			DisplayErrMsg("モデルの読み込みに失敗しました");
			return(E_FAIL);
		}
	}else{
		DisplayErrMsg("すでにモデルが登録されているアニメーションメッシュにモデルを読み込もうとしました。");
		return E_FAIL;
	}
	
	oldAnim= MeshType->GetAnimation(0);
	myMesh = true;
	return S_OK;
}
Пример #2
0
int WINAPI WinMain(HINSTANCE hInstance,
				   HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine,
				   int nCmdShow)
{	
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

	//生成
	App* app = NULL;

	try{
		app = new App(hInstance,FALSE);
	}catch(char *str){
		DisplayErrMsg(str);
		SAFE_DELETE(app);
		return(0);
	}

	//実行
	app->Run();

	//消去
	SAFE_DELETE(app);

	return(0);
}
Пример #3
0
DWORD CInternet::GetFileLength(HINTERNET hInt)
{
   TCHAR szErrMsg[512];
   char szLength[32];
   DWORD dwLength=0,dwBuffLen=sizeof(szLength);

   if(HttpQueryInfo (hInt, HTTP_QUERY_CONTENT_LENGTH, &szLength,&dwBuffLen, NULL)==FALSE)
   {
		_stprintf_s(szErrMsg, TEXT("%s: %d\n"), TEXT("HttpQueryInfo Error"),GetLastError());
		OutputDebugString(szErrMsg);
		DisplayErrMsg();
		return 0;
   }
   dwLength = (DWORD)atol(szLength);
#ifdef _DEBUG
   wsprintf (szErrMsg, TEXT("File Size %d\n"),dwLength);
   OutputDebugString(szErrMsg);
#endif
   return dwLength;
}
Пример #4
0
void SendPacket(const int index, const unsigned char* packet)
{
	int retval = 0;
	OverlapEx *sendOverlap = new OverlapEx;
	memset(sendOverlap, 0, sizeof(OverlapEx));
	sendOverlap->operation = OP_SEND;
	memset(&sendOverlap->originalOverlap, 0, sizeof(WSAOVERLAPPED));
	ZeroMemory(sendOverlap->buffer, MAX_BUFF_SIZE);
	sendOverlap->wsaBuf.buf = reinterpret_cast<CHAR*>(sendOverlap->buffer);
	sendOverlap->wsaBuf.len = packet[0];
	memcpy(sendOverlap->buffer, packet, packet[0]);

	Client *clientData = nullptr;
	gClientInfoSet->Search(index, &clientData);

	retval = WSASend(clientData->socket, &sendOverlap->wsaBuf, 1, NULL, 0, &sendOverlap->originalOverlap, NULL);
	if (0 != retval)
	{
		int errNo = WSAGetLastError();
		if (WSA_IO_PENDING != errNo)
			DisplayErrMsg("SendPacket :: WSASend", errNo);
		if (WSAECONNABORTED == errNo)
		{
			clientData->isConnect = false;
			closesocket(clientData->socket);
			
			// ToDo : 10054 error 처리
			// 각 플레이어에게 플레이어 접속 종료 알림
			Packet::Disconnect packet;
			packet.size = sizeof(Packet::Disconnect);
			packet.type = PacketType::Disconnect;
			packet.id = index;

			BroadcastingExceptIndex(index, reinterpret_cast<unsigned char*>(&packet));

			gClientInfoSet->Remove(index);
			DisplayDebugText("SendPacket :: Process error 10053.");
		}
	}
	return;
}
Пример #5
0
void WorkerThreadFunc(void)
{
	DWORD ioSize, key;
	OverlapEx *overlap;
	BOOL result;
	Client *clientData = nullptr;

	while (true)
	{
		result = GetQueuedCompletionStatus(ghIOCP, &ioSize, reinterpret_cast<PULONG_PTR>(&key), reinterpret_cast<LPOVERLAPPED*>(&overlap), INFINITE);

		if (false == result || 0 == ioSize)
		{
			if (false == result)
				DisplayErrMsg("WorkerThread :: GetQueuedCompletionStatus Fail !!", GetLastError());

			if (WSAENOTSOCK == GetLastError() || ERROR_NETNAME_DELETED == GetLastError() || 0 == ioSize)
			{
				gClientInfoSet->Search(key, &clientData);
				clientData->isConnect = false;
				closesocket(clientData->socket);

				// ToDo : 10054 error 처리
				// 각 플레이어에게 플레이어 접속 종료 알림
				Packet::Disconnect packet;
				packet.size = sizeof(Packet::Disconnect);
				packet.type = PacketType::Disconnect;
				packet.id = key;

				BroadcastingExceptIndex(key, reinterpret_cast<unsigned char*>(&packet));
				gClientInfoSet->Remove(key);

				std::string debugText = "WorkerThread :: Disconnect " + std::to_string(key) + " client. :(";
				DisplayDebugText(debugText);
			}
			continue;
		}
		if (OP_RECV == overlap->operation)
		{
			gClientInfoSet->Search(key, &clientData);
			
			unsigned char *buf_ptr = overlap->buffer;
			int remained = ioSize;
			while (0 < remained)
			{
				if (0 == clientData->recvOverlap.packetSize)
					clientData->recvOverlap.packetSize = buf_ptr[0];
				int required = clientData->recvOverlap.packetSize - clientData->previousDataSize;
				// 패킷을 완성 시킬 수 있는가? 없는가?
				if (remained >= required)
				{
					// 완성을 시킬 수 있는 상황이면
					// 패킷을 어떠한 공간에다가 고이 모셔와야 한다.
					// 그래서 패킷을 완성시키는 저장공간이 별도로 있어야한다. 
					// 데이터가 패킷단위로 오는 것이 아니기 때문에 패킷단위로 처리하고 남은데이터는 그 별도의 공간에 저장해야
					// 다음의 온 데이터가 온전하지 못한 채로 오게되면 별도의 공간에 집어넣고 하나의 패킷으로 마저 만들어 주어야 한다.
					memcpy(clientData->packetBuf + clientData->previousDataSize, buf_ptr, required);
					// +하는 이유는 지난번에 받은 데이터 이후에 저장을 해야하기 때문에 그 시작위치로 옮겨줌.
					ProcessPacket(key, clientData->packetBuf);
					// Packet 처리
					remained -= required;
					// 날아 있는 것은 필요한 것을 제외하고
					buf_ptr += required;
					// ???
					clientData->recvOverlap.packetSize = 0;
				}
				else
				{
					// 패킷을 완성 시킬 수 없는 크기이다.
					memcpy(clientData->packetBuf + clientData->previousDataSize, buf_ptr, remained);
					// buf_ptr의 모든 것을 packet에 저장한다.
					clientData->previousDataSize += remained;
					// 이전의 데이터가 남아있는 사이즈만큼 늘어났다.
					remained = 0;
					// 현재 recv의 남아있는 size는 이미 저장을 해두었으므로 초기화
				}
			}
			DWORD flags = 0;
			WSARecv(clientData->socket,
				&clientData->recvOverlap.wsaBuf,
				1, NULL, &flags,
				reinterpret_cast<LPWSAOVERLAPPED>(&clientData->recvOverlap),
				NULL);
		}
		else if (OP_SEND == overlap->operation)
		{
			// ioSize하고 실제 보낸 크기 비교 후 소켓 접속 끊기
			BYTE packetType = overlap->buffer[1];
			BYTE packetSize = overlap->buffer[0];

			if (BeCompeletedSendPacket(packetType, packetSize))
				delete overlap;
			else
			{
				std::string debugText = "WorkerThread :: " + std::to_string(key) + " client don't send " + std::to_string(packetType) + "No. packet";
				DisplayDebugText(debugText);
			}
		}
		else
		{
			DisplayDebugText("WorkerThread :: Unknown Event on worker_thread");
			continue;
		}
	}
	return;
}
Пример #6
0
void AcceptThreadFunc(void)
{
	int retval = 0;
	struct sockaddr_in listenAddr;
	int newID = -1;

	SOCKET acceptSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
	if (INVALID_SOCKET == acceptSocket)
	{
		DisplayErrMsg("AcceptThread :: acceptSocket Fail !!", WSAGetLastError());
		return;
	}

	// bind() : 소켓의 지역 IP주소와 지역 포트 번호를 결정, C++11의 bind라는 함수와 혼동 때문에::범위확인 연산자와 같이 사용.
	// msdn - The bind functio associates a local address with a socket

	// listenAddr	: 소켓 주소 구조체를 지역 IP주소와 지역 포트 번호로 초기화하여 전달한다.
	// AF_INET		: 인터넷 주초 체계(IPv4)를 사용한다는 의미
	// INADDR_ANY	: 서버의 지역 IP주소를 설정하는데 있어 다음과 같이 설정을 하면 서버가 IP주소를 2 개 이상 보유한 경우 
	//				(multihomed host라고 부름), 클라이언트가 어느 IP 주소로 접속하든 받아들일 수 있음
	// bind 함수의 2번째 인자는 항상 (SOCKADDR*)형으로 반환해야 함
	ZeroMemory(&listenAddr, sizeof(listenAddr));
	listenAddr.sin_family = AF_INET;
	listenAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	listenAddr.sin_port = htons(MY_SERVER_PORT);
	ZeroMemory(&listenAddr.sin_zero, 8);
	retval = ::bind(acceptSocket, reinterpret_cast<sockaddr*>(&listenAddr), sizeof(listenAddr));
	if (SOCKET_ERROR == retval)
	{
		DisplayErrMsg("AcceptThread :: bind Fail !!", WSAGetLastError());
		exit(1);
	}
	// listen() : 소켓의 TCP 포트 상태를 LISTENING으로 바꾼다. 이는 클라이언트 접속을 받아들일 수 있는 상태가 됨을 의미
	// msdn - The listen function places a socket in a state in which it is listening for an incomming connection.

	// SOMAXCONN : 클라이언트의 접속 정보는 연결 큐에 저장되는데, backlog는 이 연결 큐의 길이를 나타냄.
	//			SOMAXCONN의 의미는 하부 프로토콜에서 지원 가능한 최댓값을 사용
	listen(acceptSocket, SOMAXCONN);
	if (SOCKET_ERROR == retval)
	{
		DisplayErrMsg("AcceptThread :: listen Fail !!", WSAGetLastError());
		exit(1);
	}

	while (true)
	{
		struct sockaddr_in clientAddr;
		int addrSize = sizeof(clientAddr);

		// 접속한 클라이언트의 새 ID

		// accept() : 접속한 클라이언트와 통신할 수 있도록 새로운 소켓을 생성해서 리턴 또한 접속한 클라이언트의 주소정보도 알려줌
		//			: 서버입장에서는 원격 IP주소와 원격 포트번호, 클라이언트 입장에서는 지역 IP 주소와 지역 포트 번호
		// WSAAccept() : ?
		// msdn - The WSAAccept function conditionally accepts a connection based on the return value of a condition,
		//		provides quality of service flow specifications, and allows the transfer of connection data.
		SOCKET newClientSocket = WSAAccept(acceptSocket, reinterpret_cast<sockaddr*>(&clientAddr), &addrSize, NULL, NULL);
		if (INVALID_SOCKET == newClientSocket)
		{
			DisplayErrMsg("AcceptThread :: WSAAccept Fail !!", WSAGetLastError());
			break;
		}

		// 접속한 클라이언트의 새로운 ID 부여하는 구간 
		newID++;

		// Accept를 받은 이후에 등록을 해주어야 함
		HANDLE result = CreateIoCompletionPort(reinterpret_cast<HANDLE>(newClientSocket), ghIOCP, newID, 0);
		if (NULL == result)
		{
			DisplayErrMsg("AcceptThread :: CreateIoCompletionPort Fail !!", WSAGetLastError());
			closesocket(newClientSocket);
			continue;
		}

		gClientInfoSet->Add(newID);
		Player playerData;
		playerData.roomNo = 0;
		playerData.pos.x = DEFAULT_POS_X;
		playerData.pos.y = DEFAULT_POS_Y;
		playerData.pos.z = DEFAULT_POS_Z;
		gClientInfoSet->Update(newID, playerData);
		
		Client *clientData = nullptr;
		gClientInfoSet->Search(newID, &clientData);
		clientData->socket = newClientSocket;
		
		// error code 64를 해결하기 위한 delay를 줌.
		Sleep(10);

		// 새로운 클라이언트 접속 알림
		Packet::SetID clientSetIDPacket;
		clientSetIDPacket.size = sizeof(Packet::SetID);
		clientSetIDPacket.type = (BYTE)PacketType::SetID;
		clientSetIDPacket.id = newID;
		SendPacket(newID, reinterpret_cast<unsigned char*>(&clientSetIDPacket));

		// 새로운 소켓 Recv 수행
		DWORD flags = 0;
		// WSARecv() : 5번째, 6번째 두 인자를 NULL 값으로 사용하면 recv() 함수처럼 동기 함수로 동작
		retval = WSARecv(newClientSocket, &clientData->recvOverlap.wsaBuf, 1, NULL, &flags, &clientData->recvOverlap.originalOverlap, NULL);
		if (0 != retval)
		{
			int errNo = WSAGetLastError();
			if (WSA_IO_PENDING != errNo)
			{
				DisplayErrMsg("AcceptThread :: WSARecv", errNo);
			}
		}

		// Output
		std::string debugText = "AcceptThread :: ID " + std::to_string(newID) + " client Accept Success !!";
		DisplayDebugText(debugText);
	}

	return;
}