C# DHCP/BOOTP/TFTP读取请求中显示额外字符的文件名字符串

C# DHCP/BOOTP/TFTP读取请求中显示额外字符的文件名字符串,c#,dhcp,tftp,C#,Dhcp,Tftp,在构建基本的Windows映像部署解决方案(使用WinPE和C#内置的自定义应用程序)时,我遇到了一个问题,即两台计算机不在同一子网/IP段上(没有静态IP地址或DHCP服务器和DNS/路由表)。为了解决这个问题,我编写了一个基本但成功的DHCP解决方案,并将其扩展到TFTP,以便在C#中进行远程引导 该应用程序使用RFC 1350、4578中的指南实现,并在RFC 2347中引用了协商的开始。我已经成功地编写了一个例程,将请求的文件发送到远程应用程序 我已经使用Wireshark应用程序检查了

在构建基本的Windows映像部署解决方案(使用WinPE和C#内置的自定义应用程序)时,我遇到了一个问题,即两台计算机不在同一子网/IP段上(没有静态IP地址或DHCP服务器和DNS/路由表)。为了解决这个问题,我编写了一个基本但成功的DHCP解决方案,并将其扩展到TFTP,以便在C#中进行远程引导

该应用程序使用RFC 1350、4578中的指南实现,并在RFC 2347中引用了协商的开始。我已经成功地编写了一个例程,将请求的文件发送到远程应用程序

我已经使用Wireshark应用程序检查了我发出的消息,发现DHCPOFFER和DHCPACK响应的格式不正确。这些都已经纠正了,但给我留下了一个关于TFTP实现的问题

客户端计算机正在请求提供的启动文件名,但在表示文件名字符串结尾的0字节之前向名称追加额外字节。请参阅以下摘录自我的代码,用于从TFTP读取请求(RRQ)消息中提取文件名:

其中“数据报”是使用UDP套接字接收的字节数组

用于将字符串转换为字节数组以传入DHCPOFFER/ACK消息的代码:

switch (option)
    {
        case BOOTFILE:
            {
            byte[] tmpbytes = new byte[Encoding.ASCII.GetByteCount("pxeboot.n12")];
            tmpbytes = Encoding.ASCII.GetBytes("pxeboot.n12");
            _totalLength = tmpbytes.Length + 2;
            _option = new byte[_totalLength];
            _option[0] = (byte)BOOTFILE;
            _option[1] = (byte)tmpbytes.Length;
            Array.Copy(tmpbytes, 0, _option, 2, tmpbytes.Length);
            Array.Copy(_option, 0, result, optionPosition, _option.Length);
            optionPosition = optionPosition + _totalLength;
            break;
            }
    }
在console.WriteLine()中使用Encoding.ASCII.getString(tmpbytes[])时,我用“pxeboot.n12”表示。在Wireshark和消息传递更正之前,我能够从TFTP RRQ中正确提取引导文件名(在本例中为pxeboot.n12),但它在对BCD文件(位于“boot\BCD”)的TFTP请求时失败


当我能够正确提取文件名(每个文件,每次)时,是否有任何其他选项应该传回(即选项93、94和97(系统架构、网络ID版本、UUID/GUID)或选项253(在Wireshark中使用另一个DHCP/TFTP解决方案时注意到)?

我必须使用string.SubString()方法:

stringfilestring=Encoding.ASCII.GetString(tmpbytes);
int pos=filestring.IndexOf(“?”);
filestring=filstring.SubString(0,pos-1);

从tmpbytes数组中删除不需要的字符


选项93、94和97现在在请求的DHCPOFFER消息post选项中传回。DHCP和TFTP实现现在都按预期工作。

我必须使用string.SubString()方法:

stringfilestring=Encoding.ASCII.GetString(tmpbytes);
int pos=filestring.IndexOf(“?”);
filestring=filstring.SubString(0,pos-1);

从tmpbytes数组中删除不需要的字符


选项93、94和97现在在请求的DHCPOFFER消息post选项中传回。DHCP和TFTP实现现在都按预期工作。

FTP具有文本和二进制模式。确保在发送二进制文件时使用二进制模式。唯一需要使用文本模式的时间是在使用不同t返回字符。在文本模式下,它将自动更正操作系统的返回字符。请您再扩展/解释一下好吗?我使用ASCII进行编码、到字节和从字节。在RFC 1350中,文件名以NVTASCII(ASCII的子集)返回,以零(0)结尾.第一个RFC 1350使用的是Base 64字符串(在unix/ultrix中使用的是uuencode和UUEDECODE)。根据语言的不同,ASCII编码可能无法工作。您可能需要使用诸如1252之类的Windows编码。ASCII用于字符0到127。127到255之间的字符可能会根据拉丁语或俄语等语言进行不同的映射。我不会将NVTASCII称为ASCII的子集,而是ASCII的一种类型,因为只有字符127到255是不同的。我会使用UTF8编码而不是ASCII。ASCII编码会删除不可打印的字符。@jdweng,我在ASCII和UTF-8/7之间的许多组合中尝试了UTF-8和UTF-7。仍然是失败的。如果在整个字节数组中使用I encoding.ASCII,则文件名显示为true,没有额外的字符。您应该不知道不能对二进制数据使用任何编码。应使用:string Convert.ToBase64String(字节[])。可能需要编码的文件名。FTP具有文本和二进制模式。发送二进制文件时,请确保使用二进制模式。在使用不同返回字符的系统之间传输数据时,才需要使用文本模式。在文本模式下,它将自动更正操作系统的返回字符。你能再详细解释一下吗?我使用ASCII进行编码,从字节到字节和从字节到字节。从RFC 1350,文件名以NVTASCII(ASCII的子集?)返回,以零(0)结尾。第一个RFC 1350使用Base 64字符串(在unix/ultrix中,uuencode和UUEDECODE是什么)。根据语言的不同,ASCII编码可能无法工作。您可能需要使用诸如1252之类的Windows编码。ASCII用于字符0到127。127到255之间的字符可能会根据拉丁语或俄语等语言进行不同的映射。我不会将NVTASCII称为ASCII的子集,而是ASCII的一种类型,因为只有字符127到255是不同的。我会使用UTF8编码而不是ASCII。ASCII编码会删除不可打印的字符。@jdweng,我在ASCII和UTF-8/7之间的许多组合中尝试了UTF-8和UTF-7。仍然是失败的。如果在整个字节数组中使用I encoding.ASCII,则文件名显示为true,没有额外的字符。您应该不知道不能对二进制数据使用任何编码。应使用:string Convert.ToBase64String(byte[])。可能需要编码的文件名。
switch (option)
    {
        case BOOTFILE:
            {
            byte[] tmpbytes = new byte[Encoding.ASCII.GetByteCount("pxeboot.n12")];
            tmpbytes = Encoding.ASCII.GetBytes("pxeboot.n12");
            _totalLength = tmpbytes.Length + 2;
            _option = new byte[_totalLength];
            _option[0] = (byte)BOOTFILE;
            _option[1] = (byte)tmpbytes.Length;
            Array.Copy(tmpbytes, 0, _option, 2, tmpbytes.Length);
            Array.Copy(_option, 0, result, optionPosition, _option.Length);
            optionPosition = optionPosition + _totalLength;
            break;
            }
    }