6-获取磁盘分区信息

发布于:2025-09-12 ⋅ 阅读:(22) ⋅ 点赞:(0)

观察文件

获取server端电脑里面存在哪些盘符

int MakeDriveInfo() { //1==>A 2==>B (原本属于软盘的 )3==>C ... 26==>Z
    std::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位补0
        snprintf(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()

测试发现

image-20250911211852098

FFFE CCCC 0500 0000 0100 CC

这个地方多了cc是WORD对齐导致的

解决方法如下:

//ServerSocket.h
#pragma pack(push)
#pragma pack(1)
class CPacket
{
```
```
```
};
#pragma pack(pop)

加上以后的结果:

image-20250911212537601

FFFE 05000000 0100 E0 210C

发现盘符那个位置是E0转ASCII码不是C盘

下一个断点看了看

image-20250911213034708

没毛病,确实是C盘

但是strData是对象,取对象的地址,肯定并不会得到对象的值

string是对象,相当于对象中有个对象,对外层的对象传地址再取值,到里层对象那里是地址

有一个人解释的很清楚

image-20250911221308672

自己多次运行

image-20250911221342144

image-20250911221357873

发现后面那个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 *的
	}

image-20250911222643354

16进制43转成ASCII就是C


网站公告

今日签到

点亮在社区的每一天
去签到