計算機網絡 基於asio2的udp模擬protocol6樣例(未完)

config.h

#pragma once

#include <array>
#include <memory>
#include <vector>
#include <cstdint>
#include <asio2/udp/udp_cast.hpp>
#include <asio2/udp/udp_client.hpp>
#include <asio2/udp/udp_server.hpp>
#include <asio2/udp/udp_session.hpp>

using byte = uint8_t;
using uint16 = uint16_t;
using uint32 = uint32_t;
using uint64 = uint64_t;

constexpr uint32 MAX_BUFFER_SIZE = 1024;

constexpr uint64 CRC32_SETENCE = 0x104C11DB7;
constexpr uint32 CRC32_GENERATE = CRC32_SETENCE & 0xFFFF; //0x4C11DB7

enum class NetworkLayerStatus {
	PHYSICAL_LAYER_READY,
	NETWORK_LAYER_READY,
	FRAME_RECEIVED,
	DATA_TIMEOUT,
	ACK_TIMEOUT
};

constexpr uint32_t MAX_SEQ = 15;
constexpr uint32_t FRAME_LEN = 256;
constexpr uint32_t CACHE_SIZE = (MAX_SEQ + 1) / 2;

struct Frame {
	using uint8 = unsigned char;
	uint8 type;
	uint8 ack;
	uint8 seqNum;
	std::array<uint8, FRAME_LEN> data;
	uint8 CRC32;
};

main.cpp

#include "ProtocolApp/ProtocolApp.h"

int main(int argc, char* argv[]) {
	ProtocolApp app("1919");
	app.startServer().detach();
	app.startClient().detach();
	while (true) {
		std::this_thread::yield();
	}
	return 0;
}

ProtocolApp.h

#pragma once

#include <config.h>

class ProtocolApp {
public:
	using strView = std::string_view;
	explicit ProtocolApp(const strView& port):
		_port(port)
	{
		std::thread(&ProtocolApp::InitServer, this).detach();
		std::thread(&ProtocolApp::InitClient, this).detach();
	}

	virtual ~ProtocolApp() {
		_server.stop();
		_client.stop();
	}

	static void AddCRC32Tail(std::vector<byte>& data);
	static bool CheckCRC32Tail(const std::vector<byte>& data);

	void InitServer();
	void InitClient();

	[[nodiscard]] std::thread startServer() {
		return std::thread([this] {
			_server.start("127.0.0.1", _port);
		});
	}

	[[nodiscard]] std::thread startClient() {
		return std::thread([this] {
			if (!_client.start("127.0.0.1", _port))
				printf("start failure : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str());
		});
		
	}

private:
	strView			  _port;
	std::mutex		  _initMutex;

	asio2::udp_server _server;
	asio2::udp_client _client;
};

protocolApp.cpp

#include "ProtocolApp.h"

void ProtocolApp::InitServer() {
	_server.bind_recv([](std::shared_ptr<asio2::udp_session>& session_ptr, std::string_view s)
		{
			printf("recv : %u %.*s\n", (unsigned)s.size(), (int)s.size(), s.data());
			session_ptr->no_delay(true); // No effect
			session_ptr->send(s, []() {});
		}).bind_connect([](auto& session_ptr)
			{
				printf("client enter : %s %u %s %u\n", session_ptr->remote_address().c_str(), session_ptr->remote_port(),
					session_ptr->local_address().c_str(), session_ptr->local_port());
			}).bind_disconnect([](auto& session_ptr)
				{
					printf("client leave : %s %u %s\n", session_ptr->remote_address().c_str(),
						session_ptr->remote_port(), asio2::last_error_msg().c_str());
				}).bind_handshake([](auto& session_ptr, asio::error_code ec)
					{
						printf("client handshake : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str());
					}).bind_start([this](asio::error_code ec)
						{
							if (asio2::get_last_error())
								printf("start udp server failure : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str());
							else
								printf("start udp server success : %s %u\n", _server.listen_address().c_str(), _server.listen_port());
							//server.stop();
						}).bind_stop([&](asio::error_code ec)
							{
								printf("stop : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str());
							}).bind_init([&]()
								{
								});
							
}

void ProtocolApp::InitClient() {
	_client.connect_timeout(std::chrono::seconds(3));
	_client.local_endpoint(asio::ip::udp::v4(), 15678);
	_client.bind_connect([&](asio::error_code ec)
		{
			if (asio2::get_last_error())
				printf("connect failure : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str());
			else
				printf("connect success : %s %u\n", _client.local_address().c_str(), _client.local_port());

			_client.send(std::string("<abcdefghijklmnopqrstovuxyz0123456789>"));
		}).bind_disconnect([](asio::error_code ec)
			{
				printf("disconnect : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str());
			}).bind_recv([&](std::string_view sv)
				{
					printf("recv : %u %.*s\n", (unsigned)sv.size(), (int)sv.size(), sv.data());

					//std::this_thread::sleep_for(std::chrono::milliseconds(100));

					std::string s;
					s += '<';
					int len = 33 + std::rand() % (126 - 33);
					for (int i = 0; i < len; i++)
					{
						s += (char)((std::rand() % 26) + 'a');
					}
					s += '>';

					_client.send(std::move(s));

				});
}

void ProtocolApp::AddCRC32Tail(std::vector<byte>& data) {

	uint32 crc = ~0;
	size_t dataSize = data.size();

	std::array<byte, 4> crcTail = { 0x0, 0x0, 0x0, 0x0 };
	const byte* current = static_cast<byte*>(data.data());

	while (dataSize-- != 0) {
		byte s = byte(crc) ^ *current++;

		uint32 low = (s ^ (s << 6)) & 0xFF;
		uint32 tmp = (low * ((1 << 23) + (1 << 14) + (1 << 2)));
		crc = (crc >> 8) ^
			(low * ((1 << 24) + (1 << 16) + (1 << 8))) ^
			(tmp) ^
			(tmp >> 1) ^
			(low * ((1 << 20) + (1 << 12))) ^
			(low << 19) ^
			(low << 17) ^
			(low >> 2);
	}
	crc = ~crc;

	crcTail[0] = static_cast<byte>(crc >> 24);
	crcTail[1] = static_cast<byte>(crc >> 16 & 0xFF);
	crcTail[2] = static_cast<byte>(crc >> 8 & 0xFF);
	crcTail[3] = static_cast<byte>(crc & 0xFF);

	for (auto code : crcTail) {
		data.push_back(code);
	}
}

bool ProtocolApp::CheckCRC32Tail(const std::vector<byte>& data) {

	uint32 crc = ~0;
	size_t dataSize = data.size() - 4;

	std::array<byte, 4> crcTail = {
		data[data.size() - 4],
		data[data.size() - 3],
		data[data.size() - 2],
		data[data.size() - 1]
	};
	const byte* current = (byte*)data.data();

	while (dataSize-- != 0) {
		byte s = byte(crc) ^ *current++;

		uint32 low = (s ^ (s << 6)) & 0xFF;
		uint32 tmp = (low * ((1 << 23) + (1 << 14) + (1 << 2)));
		crc = (crc >> 8) ^
			(low * ((1 << 24) + (1 << 16) + (1 << 8))) ^
			(tmp) ^
			(tmp >> 1) ^
			(low * ((1 << 20) + (1 << 12))) ^
			(low << 19) ^
			(low << 17) ^
			(low >> 2);
	}
	crc = ~crc;

	return !(
		crcTail[0] ^ static_cast<byte>(crc >> 24) ||
		crcTail[1] ^ static_cast<byte>(crc >> 16 & 0xFF) ||
		crcTail[2] ^ static_cast<byte>(crc >> 8 & 0xFF) ||
		crcTail[3] ^ static_cast<byte>(crc & 0xFF)
	);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章