int main(int argc, char **argv) { if (argc < 2) { std::cout << "Usage: " << argv[0] << " server-ip" << std::endl; return 0; } kNet::SetLogChannels(LogUser | LogInfo | LogError); EnableMemoryLeakLoggingAtExit(); Network network; MessageListener listener; const unsigned short cServerPort = 1234; Ptr(MessageConnection) connection = network.Connect(argv[1], cServerPort, SocketOverUDP, &listener); if (connection) { // Run the main client loop. connection->RunModalClient(); } return 0; }
/// handle connection void GameEconomicServerClientConsole::Connect(networkconfiguration &tempnetwork) { /// Get Urho subsystem Network* network = GetSubsystem<Network>(); /// Define Variables bool success=true; cout << "Connecting Server Console Interface to Host ("<< tempnetwork.hostserver.CString() << " on port " << tempnetwork.hostport << ")." << endl; /// Get currenttime Urho3D::Time systemtime(context_); unsigned int currenttime = systemtime.GetSystemTime(); /// Get eventmap and time Urho3D::VariantMap NetworkClientIdentity; NetworkClientIdentity[NetworkClientIdentity::NETWORK_CLIENTYPE] =Unauthenticated; NetworkClientIdentity[NetworkClientIdentity::NETWORK_CLIENTARRIVAL]= currenttime; /// Set Identity ///newConnection->SetIdentity(NetworkClientIdentity); serverconnection = network->Connect(tempnetwork.hostserver, tempnetwork.hostport, 0, NetworkClientIdentity); return; }
void RunClient(const char *address, unsigned short port, SocketTransportLayer transport) { Ptr(MessageConnection) connection = network.Connect(address, port, transport, this); if (!connection) { cout << "Unable to connect to " << address << ":" << port << "." << endl; return; } connection->RegisterInboundMessageHandler(this); cout << "Waiting for connection.." << endl; while(connection->GetConnectionState() == ConnectionPending) Clock::Sleep(100); if (connection->GetConnectionState() != ConnectionOK) { cout << "Failed to connect to server!" << endl; return; } cout << "Connected to " << connection->ToString() << "." << endl; RunLatencyTest(connection); }
void SceneReplication::HandleConnect(StringHash eventType, VariantMap& eventData) { Network* network = GetSubsystem<Network>(); String address = textEdit_->GetText().Trimmed(); if (address.Empty()) address = "localhost"; // Use localhost to connect if nothing else specified // Connect to server, specify scene to use as a client for replication clientObjectID_ = 0; // Reset own object ID from possible previous connection network->Connect(address, SERVER_PORT, scene_); UpdateButtons(); }
void RunClient(const char *address, unsigned short port, SocketTransportLayer transport) { Ptr(MessageConnection) connection = network.Connect(address, port, transport, this); if (!connection) { cout << "Unable to connect to " << address << ":" << port << "." << endl; return; } cout << "Waiting for connection.." << endl; while(connection->GetConnectionState() == ConnectionPending) Clock::Sleep(100); if (connection->GetConnectionState() != ConnectionOK) { cout << "Failed to connect to server!" << endl; return; } cout << "Connected to " << connection->ToString() << "." << endl; const int numMessagesToSend = 100000; connection->NetworkSendSimulator().enabled = true; connection->NetworkSendSimulator().packetDuplicationRate = 1.0; // connection->NetworkSendSimulator().constantPacketSendDelay = 50.f; // connection->NetworkSendSimulator().packetLossRate = 0.1f; // connection->NetworkSendSimulator().uniformRandomPacketSendDelay = 100.f; PolledTimer statsPrint(1000.f); cout << "Sending messages to server..." << endl; int numMessagesSent = 0; for(int i = 0; i < numMessagesToSend; ++i) { connection->Process(); if (connection->NumOutboundMessagesPending() < 1000) { SendMessage(connection); ++numMessagesSent; } Clock::Sleep(1); if (statsPrint.Test()) { cout << "Sent " << numMessagesSent << " messages to server." << endl; statsPrint.StartMSecs(1000.f); } } connection->Disconnect(); }
void Chat::HandleConnect(StringHash eventType, VariantMap& eventData) { Network* network = GetSubsystem<Network>(); String address = textEdit_->GetText().Trimmed(); if (address.Empty()) address = "localhost"; // Use localhost to connect if nothing else specified // Empty the text edit after reading the address to connect to textEdit_->SetText(String::EMPTY); // Connect to server, do not specify a client scene as we are not using scene replication, just messages. // At connect time we could also send identity parameters (such as username) in a VariantMap, but in this // case we skip it for simplicity network->Connect(address, CHAT_SERVER_PORT, 0); UpdateButtons(); }
void RunClient(const char *address, unsigned short port, SocketTransportLayer transport, int numConcurrentConnections, int numTotalConnections) { cout << "Starting connection flood."; std::vector<Ptr(MessageConnection)> connections; int numConnectionAttempts = 0; while(numConnectionAttempts < numTotalConnections || connections.size() > 0) { // Start new connections. while((int)connections.size() < numConcurrentConnections && numConnectionAttempts < numTotalConnections) { ++numConnectionAttempts; Ptr(MessageConnection) connection = network.Connect(address, port, transport, this); if (connection && connection->GetSocket()) { LOG(LogUser, "Connecting from local port %d. Connection 0x%p", (int)connection->GetSocket()->LocalPort(), connection.ptr()); connections.push_back(connection); } else break; } // Disconnect any established connections. for(int i = 0; i < (int)connections.size(); ++i) { if (connections[i]->GetConnectionState() == ConnectionOK || connections[i]->GetConnectionState() == ConnectionClosed) { LOG(LogUser, "Closing connection 0x%p.", connections[i].ptr()); connections[i]->Close(0); connections.erase(connections.begin() + i); --i; } } Clock::Sleep(1); } cout << "Finished connection flood." << endl; }
void GameManager::NET_PlayGameFlow() { Network network; PacketType type; ErrorType error; try { Network::Initialize(); } catch (Network::Exception) { puts("초기화 도중 문제가 발생했습니다."); return; } try { network.Connect("10.73.42.117", 9000); } catch (Network::Exception ex) { switch (ex) { case Network::NETWORK_ERROR: puts("서버와 연결에 실패했습니다."); break; case Network::PARAMETER_ERROR: puts("함수의 인수가 잘못되었습니다."); break; } return; } puts("접속 성공!"); try { const wchar_t name[MAX_NAME_LEN] = L"지면 F"; const int studentID = 141055; error = network.SubmitName(name, studentID); if (error == ET_DUPLICATED_NAME) { puts("이미 존재하는 이름입니다."); return; } Network::GameStartData gameStartData; puts("게임 시작 대기중"); network.WaitForStart(&gameStartData); wprintf_s(L"매칭되었습니다. 상대방 이름: %s, 학번: %d\n", gameStartData.oppositionName, gameStartData.oppositionStudentID); bool allOver = false; while (!allOver) //10판 종료 { ShipData shipData; Network::Initialize(); char mapData[MAP_SIZE]; while (true) { ReadyToFight(m_Player1); ReadyToFight(m_Player2); m_GameRenderer->RenderPages(GAMEPLAY, NET_PLAY); for (int i = 0; i < DEFAULT_SHIP_COUNT; ++i) { Position netPosition; if (i != 4) netPosition = ConvertPosionForNET((ShipType)i, m_ShipPositions[i]); else if (i == 4) netPosition = ConvertPosionForNET((ShipType)(i - 1), m_ShipPositions[i]); shipData.SetShip((ShipData::ShipType)(i + 1), Coord(netPosition.m_X, netPosition.m_Y), netPosition.m_direction == 0 ? ShipData::DIR_VERTICAL : ShipData::DIR_HORIZONTAL); } shipData.ToMapData(mapData); error = network.SubmitMap(mapData); if (error == ET_INVALID_MAP) puts("유효하지 않은 맵 데이터입니다."); else break; } bool gameOver = false; while (!gameOver) { error = network.GetPacketType(&type); switch (type) { case PKT_SC_ERROR: if (error == ET_OPPOSITION_DISCONNECTED) puts("상대방의 접속이 끊어졌습니다."); else puts("알 수 없는 에러입니다."); return; case PKT_SC_MY_TURN: /* 공격 위치 전송 x, y는 0~7 사이의 정수이다.*/ { Coordinate netShot; bool isAttacked; while (true) { do { netShot = m_Player1->RandomAttack(); //Make AI Attack T-T //netShot = m_GameInterface->AttackInterface(FIRST_MAP_GOTOX, FIRST_MAP_GOTOY); //Manual Mode isAttacked = m_Player2->CheckAttacked(netShot); } while (isAttacked); Coord myShot(netShot.m_X, netShot.m_Y); error = network.SubmitAttack(myShot); if (error == ET_INVALID_ATTACK) printf_s("유효하지 않은 공격"); else break; } break; } case PKT_SC_ATTACK_RESULT: { Network::AttackResultData attackResult = network.GetAttackResult(); Coordinate shot; shot.m_X = attackResult.pos.mX; shot.m_Y = attackResult.pos.mY; HitResult shotResult = (HitResult)attackResult.attackResult; if (attackResult.isMine) //내 에너미 맵에 내가 공격한 결과를 반영 마크 { m_GameRenderer->PrintResult(shotResult); m_GameRenderer->PrintTurn(++m_Turn, DEFAULT_MAP_SIZE); m_Player1->MarkOnEnemyMap(shot, shotResult); m_Player2->MarkOnMyMap(shot, shotResult); m_Player1->RenderUpdateEnemyMapStatus(FIRST_MAP_GOTOX, FIRST_MAP_GOTOY); } else //내가 어택당하는 함수 { m_Player1->MarkOnMyMap(shot, shotResult); m_Player1->RenderUpdateMyMapStatus((m_MapSize + 3) * 4 + 30, FIRST_MAP_GOTOY); } break; } case PKT_SC_GAME_OVER: { Network::GameResultData gameResult = network.GetGameResult(); ResetGame(); if (gameResult.isWinner) puts("승리!!!"); else puts("패배..."); printf_s("턴 수: %d\n", gameResult.turns); gameOver = true; break; } default: throw Network::UNEXPECTED_PACKET; break; } } network.GetPacketType(&type); if (type == PKT_SC_NEXT_GAME) { puts("다음 게임을 준비해주세요."); } else if (type == PKT_SC_ALL_OVER) { Network::FinalResultData finalResult = network.GetFinalResult(); allOver = true; } else throw Network::UNEXPECTED_PACKET; } } catch (Network::Exception ex) { switch (ex) { case Network::NETWORK_ERROR: puts("네트워크에 문제가 발생했습니다."); break; case Network::SERVER_CLOSED: puts("서버와의 연결이 끊어졌습니다."); break; case Network::PARAMETER_ERROR: puts("함수의 인수가 잘못되었습니다."); break; case Network::UNEXPECTED_PACKET: puts("서버에서 잘못된 정보가 전송되었습니다."); break; default: break; } } network.Disconnect(); m_GameStatus = WIN; }
void GameManager::Networking() { Network network; PacketType type; ErrorType error; srand((unsigned int)time(NULL)); /* ** 네트워크 초기화 */ try { Network::Initialize(); } catch (Network::Exception) { puts("초기화 도중 문제가 발생했습니다."); return; } /* ** 서버에 연결 서버의 IP와 포트는 당일날 공지된다. */ const char* ip = "10.73.42.117"; const unsigned short port = 9001; try { network.Connect(ip, port); } catch (Network::Exception ex) { switch (ex) { case Network::NETWORK_ERROR: puts("서버와 연결에 실패했습니다."); break; case Network::PARAMETER_ERROR: puts("함수의 인수가 잘못되었습니다."); break; } return; } puts("접속 성공!"); try // 예외 처리를 위해 try문으로 모두 감싼다. { /* ** 이름&학번 전송 최대 길이는 MAX_NAME_LEN-1 == 15글자. 성공시 ET_OK가 리턴된다. 이미 있는 이름을 쓰면 ET_DUPLICATED_NAME이 온다. */ const wchar_t name[MAX_NAME_LEN] = L"버틸수없다"; const int studentID = 141044; error = network.SubmitName(name, studentID); if (error == ET_DUPLICATED_NAME) { puts("이미 존재하는 이름입니다."); return; } /* ** 게임 시작 대기 게임이 시작되면 상대방의 정보가 들어온다. Network::GameStartData 구조체로 상대방 정보를 가져온다. */ Network::GameStartData gameStartData; puts("게임 시작 대기중"); network.WaitForStart(&gameStartData); wprintf_s(L"매칭되었습니다. 상대방 이름: %s, 학번: %d\n", gameStartData.oppositionName, gameStartData.oppositionStudentID); /* ** 게임 시작 맵 제출부터 게임 종료까지 n회 반복한다. 하나의 게임이 끝나고 다음 게임을 시작해야 한다면 PKT_SC_NEXT_GAME 패킷이 모든 게임이 끝나면 PKT_SC_ALL_OVER 패킷이 들어온다. */ bool allOver = false; while (!allOver) { SetGame(); /* ** 맵 제출 자신이 배치한 맵 데이터를 서버로 전송한다. 맵 데이터를 만드는 방법에는 두 가지가 있다. 하나는 직접 MAP_WIDHT * MAP_HEIGHT 크기의 맵을 만드는 것이고, 하나는 ShipData 구조체를 이용해서 만드는 것이다. */ char mapData[MAP_SIZE]; //TransferMyMapData(mapData, m_Attacker); memset(mapData, MI_EMPTY, sizeof(mapData)); int shiptype = 1; for (auto ship : *m_Attacker->GetShipList()) { for (int i = 0; i < ship->GetShipType(); ++i){ auto position = ship->GetShipPos(i); mapData[position.y*MAP_WIDTH + position.x] = shiptype; } shiptype++; //하드코딩 } while (true) { error = network.SubmitMap(mapData); if (error == ET_INVALID_MAP) puts("유효하지 않은 맵 데이터입니다."); else break; } /* ** 게임 루프 내 차례라면 공격 위치를 전송한다. 차례가 끝나면 공격자와 공격 위치, 공격 결과를 받는다. 한 게임이 끝나면 PKT_SC_GAME_OVER 패킷이 들어온다. */ bool gameOver = false; while (!gameOver) { error = network.GetPacketType(&type); switch (type) { // 에러가 발생하는 경우(상대방의 접속 종료) case PKT_SC_ERROR: if (error == ET_OPPOSITION_DISCONNECTED) puts("상대방의 접속이 끊어졌습니다."); else puts("알 수 없는 에러입니다."); return; // 내 차례 case PKT_SC_MY_TURN: { /* ** 공격 위치 전송 x, y는 0~7 사이의 정수이다. */ while (true) { // Coord pos = MakeAttackPos(); Position attackpos = m_Attacker->RandomAttack(); error = network.SubmitAttack({ attackpos.x, attackpos.y }); if (error == ET_INVALID_ATTACK) puts("유효하지 않은 공격 위치입니다."); else break; } break; } // 공격 결과 case PKT_SC_ATTACK_RESULT: { Network::AttackResultData attackResult = network.GetAttackResult(); Position attackpos; attackpos.x = attackResult.pos.mX; attackpos.y = attackResult.pos.mY; HitResult hitResult = TranslateHitResult(attackResult.attackResult); if (attackResult.isMine){ // puts("공격 결과:"); m_Attacker->ReceiveHitResult(attackpos, hitResult); } else { puts("피격 결과:"); //HandleOpositionAttackResult(attackResult.attackResult, attackResult.pos.mX, attackResult.pos.mY); m_Zido_Attacker->ZidoMarkByGM(attackpos); } printf_s("X: %d, Y: %d, RESULT: %s\n", attackResult.pos.mX, attackResult.pos.mY, ATTACK_RESULT_STR[attackResult.attackResult]); break; } // 게임 종료 case PKT_SC_GAME_OVER: { Network::GameResultData gameResult = network.GetGameResult(); if (gameResult.isWinner) puts("승리!!!"); else puts("패배..."); printf_s("턴 수: %d\n", gameResult.turns); gameOver = true; break; } default: throw Network::UNEXPECTED_PACKET; break; } } /* ** 종료후 처리 */ network.GetPacketType(&type); if (type == PKT_SC_NEXT_GAME) { puts("다음 게임을 준비해주세요."); } else if (type == PKT_SC_ALL_OVER) { Network::FinalResultData finalResult = network.GetFinalResult(); puts("모두 종료"); printf_s("승리 횟수: %d, 평균 턴 수: %.1f", finalResult.winCount, finalResult.avgTurns); allOver = true; } else throw Network::UNEXPECTED_PACKET; } } catch (Network::Exception ex) { switch (ex) { case Network::NETWORK_ERROR: puts("네트워크에 문제가 발생했습니다."); break; case Network::SERVER_CLOSED: puts("서버와의 연결이 끊어졌습니다."); break; case Network::PARAMETER_ERROR: puts("함수의 인수가 잘못되었습니다."); break; case Network::UNEXPECTED_PACKET: puts("서버에서 잘못된 정보가 전송되었습니다."); break; default: break; } } /* ** 연결 종료 참고로 소멸시에도 자동으로 Disconnect를 호출한다. */ network.Disconnect(); _getch(); }