6-获取磁盘分区信息
观察文件
获取server端电脑里面存在哪些盘符
int MakeDriveInfo() { //1==>A 2==>B (原本属于软盘的 )3==>C ... 26==>Zstd::string result;for (int i = 1; i < 26; i++) { //让其循环if (_chdrive(i) == 0) //改变当前的驱动,_chdrive函数(c和c++中)应该是封装了win的api函数GetLogicalDrives(说反了){if (result.size() > 0) {result += ',';}result += 'A' + i - 1;//切换成功}}CPacket pack(1, (BYTE*)result.c_str(), result.size()); //重载了构造函数(如果不重载成员变量需要一个个值赋值太麻烦了),打包用的,抽象Dump((BYTE*)pack.Data(), pack.Size()); //自己控制台输出打包数据(debug)//CserverSocket::getInstance()->Send(pack);return 0;
}
我们之前的构造函数只有解包的操作,没有打包的操作,打包发到client端的操作
新加一个构造函数
//下面是打包的操作CPacket(WORD nCmd, const BYTE* pData, size_t nSize) { //常量指针,指向的内容不能改变sHead = 0xFEFF; //头nLength = nSize + 2 + 2; //数据的长度加上命令长度加上校验的长度sCmd = nCmd; //命令if (nSize > 0) { //有数据strData.resize(nSize); //给包data容器重新设置长度memcpy((void*)strData.c_str(), pData, nSize); //给包打他字段设置上}else { //没有数据了,头字段和命令字段要清空strData.clear();}sSum = 0; //校验和for (size_t j = 0; j < strData.size(); j++) {sSum += BYTE(strData[j]) & 0xFF;} //添加校验和}
打包了就是Send函数,之前写的Send函数同样需要重载(这是给客户端送数据,所以直接是packet)
bool Send(const CPacket& pack) {if (m_client == -1) return false;return send(m_client, (const char*)&pack, pack.nLength+2+4, 0) > 0;}
谁来调用这个Send,当然是pserver
但是我们程序没有写好,需要一个测试函数,自己构造的这个包里面的信息能不能成功打印出来
void Dump(BYTE* pData, size_t nSize) {std::string strOut;for (size_t i = 0; i < nSize; i++) {char buf[8] = "";//缓冲区,把二进制的0/1当char一个字节来存入(质疑)if (i > 0 && (i % 16 == 0)) strOut += "\n"; //每隔16位补0snprintf(buf, sizeof(buf), "%02X ", pData[i] & 0xFF); //按16进制输出,不足两位补0,与上ff的原因是byte转成int过程中,负数的话前面补1,影响结果strOut += buf;}strOut += "\n";OutputDebugStringA(strOut.c_str());
}
这个Dump函数模拟的是客户端输出的情况,所以就两个值一个是这一个数据包的完整数据(模拟的暂时还不支持解包),和长度
所以还要另外写函数,来返回pack完整内容Data()还有Size()
测试发现
FFFE CCCC 0500 0000 0100 CC
这个地方多了cc是WORD对齐导致的
解决方法如下:
//ServerSocket.h
#pragma pack(push)
#pragma pack(1)
class CPacket
{
```
```
```
};
#pragma pack(pop)
加上以后的结果:
FFFE 05000000 0100 E0 210C
发现盘符那个位置是E0转ASCII码不是C盘
下一个断点看了看
没毛病,确实是C盘
但是strData是对象,取对象的地址,肯定并不会得到对象的值
string是对象,相当于对象中有个对象,对外层的对象传地址再取值,到里层对象那里是地址
有一个人解释的很清楚
自己多次运行
发现后面那个data部分是在变的,印证猜想
解决方法
让自己的包自带一个缓冲区,在packet成员变量里面加上
std::string strOut;//整个包的输出,这东西不用构造函数初始化
添加一个将packet有效数据添加到自身缓冲区的函数Data()
const char* Data() {strOut.resize(nLength + 6);BYTE* pData = (BYTE*)strOut.c_str();*(WORD*)pData = sHead; pData += 2;*(DWORD*)(pData) = nLength; pData += 4;*(WORD*)pData = sCmd; pData += 2;memcpy(pData, strData.c_str(), strData.size()); pData += strData.size();*(WORD*)pData = sSum;return strOut.c_str(); //c_str()接口是string类的一个函数,返回的是字符串的首地址,返回值类型是const char *的}
16进制43转成ASCII就是C