详细介绍:17.TCP编程(二)和序列化
一.概念回顾
建议先学上篇博客,再向下学习,上篇博客的链接如下:
二.远程命令分析功能
我们还是在原来的代码的基础上,增加一个CommandExec的类(我们可以把我们原来的shell直接拿来)
#pragma once
#include
#include
class Command
{
public:
//给你一个命令字符串"ls -l",让你执行,执行完,把结果进行返回
std::string Execute(std::string cmdstr)
{
//1. pipe
//2. fork + dup2(pipe[1],1) + exec*,把执行结果交给父进程(pipe[0])
//3. return
return std::string();
}
};
但是有一个接口完成了上面的基本功能







//给你一个命令字符串"ls -l",让你执行,执行完,把结果进行返回
std::string Execute(std::string cmdstr)
{
//1. pipe
//2. fork + dup2(pipe[1],1) + exec*,把执行结果交给父进程(pipe[0])
//3. return
FILE* fp = ::popen(cmdstr.c_str(),"r");
if(nullptr == fp)
{
return std::string("Failed");
}
char buffer[line_size];
std::string result;
while(true)
{
char* ret = ::fgets(buffer,sizeof(buffer),fp);
if(!ret)
{
break;
}
result += ret;
}
pclose(fp);
return result.empty() ? std::string("Done") : result;
}
三.将可执行命令设置进入白名单(防止危险命令)
#pragma once
#include
#include
#include
#include
const int line_size = 1024;
class Command
{
public:
Command()
{
_white_list.insert("ls");
_white_list.insert("pwd");
_white_list.insert("ls -l");
_white_list.insert("ll");
_white_list.insert("touch");
_white_list.insert("who");
_white_list.insert("whoami");
}
bool SafeCheck(const std::string& cmdstr)
{
if(_white_list.count(cmdstr))
{
return true;
}
return false;
}
//给你一个命令字符串"ls -l",让你执行,执行完,把结果进行返回
std::string Execute(std::string cmdstr)
{
//1. pipe
//2. fork + dup2(pipe[1],1) + exec*,把执行结果交给父进程(pipe[0])
//3. return
if(!SafeCheck(cmdstr))
{
return std::string(cmdstr + "不支持");
}
FILE* fp = ::popen(cmdstr.c_str(),"r");
if(nullptr == fp)
{
return std::string("Failed");
}
char buffer[line_size];
std::string result;
while(true)
{
char* ret = ::fgets(buffer,sizeof(buffer),fp);
if(!ret)
{
break;
}
result += ret;
}
pclose(fp);
return result.empty() ? std::string("Done") : result;
}
private:
std::set _white_list;
};




这里我们采取的是严格匹配,所以可执行的命令较少(可以用shell,但是安全一定要做好)

这里我们就基本完成了TCP套接字的初次使用
四.应用层协议
1.协议讲解



但是这样是不行的,对于我们的(两个机器位数,平台等)不同,这样数据会出现不匹配的问题


2.重新理解read、write、recv、send和tcp为什么支持全双工

这里操作系统会对于一个sockfd创建对应的两个缓冲区,用于发送和接收
两对接收和发送缓冲区,所以对应的就是全双工的了

![]()


3.面向字节流


TCP的发送方式就是基于拥塞控制,流量控制等操作,将部分报文进行发送,导致我们读取数据出现错误(所以在OS层面是,不能保证读取正确的)
UDP的发送方式就是用户数据报,发送的信息一定是完整的(和快递类似,只能收到一个完整的快递,不能只收到半个快递)
TCP无法确定报文完整性的,所以我们在用户层可以保证自己报文的完整性

浙公网安备 33010602011771号