以下是根据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返回的不是迭代器是位置,因为实现不是同个时代的产物