用原始时代的C结构设计消息协议(C++asio网络库相关)

以下是根据asio库聊天室例子改写的代码功能增加了聊天的时候能知道对方name:

C结构体设计消息协议部分:

//structheader.h
#ifndef FND_STRUCT_HEADER_H
#define FND_STRUCT_HEADER_H
#include <string>
struct Header {
	int bodySize;
	int type;
};

enum MessageType {
	MT_BIND_NAME = 1,
	MT_CHAT_INFO = 2,
	MT_ROOM_INFO = 3,
};

// client send
struct BindName {
	char name[32];
	int nameLen;
};

// client send
struct ChatInformation {
	char information[256];
	int infoLen;
};


// serversend
struct RoomInformation {
	BindName name;
	ChatInformation chat;
};

//structHeader.cpp
#include "structHeader.h"
#include <cstdlib>
#include <cstring>
#include <iostream>
// cmd messagebody
bool parseMessage(const std::string &input, int *type, std::string &outbuffer) {
  // input should be cmd body
  auto pos = input.find_first_of(" ");
  if (pos == std::string::npos)
    return false;
  if (pos == 0)
    return false;
	// "BindName ok" -> substr -> BindName
  auto command = input.substr(0, pos);
  if (command == "BindName") {
    // we try to bind name
    std::string name = input.substr(pos + 1);
    if (name.size() > 32)
      return false;
    if (type)
      *type = MT_BIND_NAME;
    BindName bindInfo;
    bindInfo.nameLen = name.size();
    std::memcpy(&(bindInfo.name), name.data(), name.size());
    auto buffer = reinterpret_cast<const char *>(&bindInfo);
    outbuffer.assign(buffer, buffer + sizeof(bindInfo));
    return true;
  } else if (command == "Chat") {
    // we try to chat
    std::string chat = input.substr(pos + 1);
    if (chat.size() > 256)
      return false;
    ChatInformation info;
    info.infoLen = chat.size();
    std::memcpy(&(info.information), chat.data(), chat.size());
    auto buffer = reinterpret_cast<const char *>(&info);
    outbuffer.assign(buffer, buffer + sizeof(info));
    if (type)
      *type = MT_CHAT_INFO;
    return true;
  }
  return false;
}

通过reinterpret_cast将结构体类型转换成char *指针

string.assign赋值类似处理memcpy处理char *将结构体按字符串形式放入string类型的outbuffer里,是字符串string处理结构体的方式,要先转化成char *

bool parseMessage(const std::string& input, int* type, std::string& outbuffer);
#endif

//chat_message.app
#ifndef CHAT_MESSAGE_HPP
#define CHAT_MESSAGE_HPP

#include "structHeader.h"

#include <iostream>

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
// s -> c   c -> s message { header, body } // header length

class chat_message {
public:
  enum { header_length = sizeof(Header) };
  enum { max_body_length = 512 };

  chat_message(){}

  const char *data() const { return data_; }

  char *data() { return data_; }

  std::size_t length() const { return header_length + m_header.bodySize; }

  const char *body() const { return data_ + header_length; }

  char *body() { return data_ + header_length; }
  int type() const { return m_header.type; }

  std::size_t body_length() const { return m_header.bodySize; }
  void setMessage(int messageType, const void *buffer, size_t bufferSize) {
    assert(bufferSize <= max_body_length);
		m_header.bodySize = bufferSize;
		m_header.type = messageType;
		std::memcpy(body(), buffer, bufferSize);
		std::memcpy(data(), &m_header, sizeof(m_header));
  }

  bool decode_header() {
    std::memcpy(&m_header, data(), header_length);
    if (m_header.bodySize > max_body_length) {
      std::cout << "body size " << m_header.bodySize << " " << m_header.type
                << std::endl;
      return false;
		}
    return true;
  }

private:
  char data_[header_length + max_body_length];
	Header m_header;
};

#endif // CHAT_MESSAGE_HPP

结构体类型赋值给char *可以用memcpy,同样char *赋值给结构体类型也可以用memcpy

pod类型都可以用memcpy进行赋值
在这里插入图片描述
string的find_first_of返回的不是迭代器是位置,因为实现不是同个时代的产物

发布了142 篇原创文章 · 获赞 34 · 访问量 2187

猜你喜欢

转载自blog.csdn.net/qq_39885372/article/details/104078815