user-0 提问: smtp协议，mime，编码问题！

回复:
user: user-0
content: 网上找到一份答案了 http://blog.csdn.net/ccfboy/article/details/6170538

user: user-1
content: 1）6+1 =7 刚好是在 ASCII范围 2）ASCII，可用用文字表示，这样有错误，肉眼就可以判断出来了 3）编码传输为了方便 通常是 8 ～10 Bits      多余的1～3 bits  可以用来做 奇偶校验，      这样简单错误，很容易就判断出来了 4）ASCII 自带控制码，有时候可以在数据中，插入控制信息。所以就规定只能传输ASCII 大约是这样的，具体原因，还要查查资料。 这和当时的条件有关系。

user: user-0
content: 引用 13 楼 cc_mugiwala 的回复:[quote=引用 10 楼 lm_whales 的回复:] [quote=引用 8 楼 cc_mugiwala 的回复:] [quote=引用 6 楼 cc_mugiwala 的回复:] [quote=引用 5 楼 lm_whales 的回复:]  再看这个书上的原话：  上面写到“smtp不能传送可执行文件或其它的二进制对象”，“smtp限于传送7位的ascii码。许多其他的非英语国家的文字就无法传送” 其实并不是无法传送，只是端系统无法解析？对与传送都是0和1，只要是文件都可以传送的吧？  对呀，没法解析，没法确定有没有出错，没法校验。 不能确定会不会出错，你说能发送吗 要想保证传输不出问题，就必须编码 传输中，有错要么纠正，要么丢弃  另外 smtp 实现上，可能需要保留某些编码， 用于通讯协议， 如果二进制传输，不进行编码的话 那么就非常不可靠了  本质上，目前来说， 计算机相关的，一切数据传输，储存，计算，都是二进制的， 哪有不能传送二进制的呢 只是二进制，由于种种原因，原封不动传输的话， 容易出错，结果不能得到保证。 所以要编码。保证传输可靠。   [/quote]  “如果二进制传输，不进行编码的话 那么就非常不可靠了” ”只是二进制，由于种种原因，原封不动传输的话，容易出错，结果不能得到保证。所以要编码。保证传输可靠。“  我再问深一点，为什么二进制传输不能得到保证，而ascii的字符或者base64字符可以得到保证。。。，，或者说什么样的形式才能得到保证？[/quote] tcp连接应该已经保证数据的正确传输了

user: user-2
content: 请立即去研读相关RFC文档。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！

user: user-0
content: 引用 10 楼 lm_whales 的回复:[quote=引用 8 楼 cc_mugiwala 的回复:] [quote=引用 6 楼 cc_mugiwala 的回复:] [quote=引用 5 楼 lm_whales 的回复:]  再看这个书上的原话：  上面写到“smtp不能传送可执行文件或其它的二进制对象”，“smtp限于传送7位的ascii码。许多其他的非英语国家的文字就无法传送” 其实并不是无法传送，只是端系统无法解析？对与传送都是0和1，只要是文件都可以传送的吧？  对呀，没法解析，没法确定有没有出错，没法校验。 不能确定会不会出错，你说能发送吗 要想保证传输不出问题，就必须编码 传输中，有错要么纠正，要么丢弃  另外 smtp 实现上，可能需要保留某些编码， 用于通讯协议， 如果二进制传输，不进行编码的话 那么就非常不可靠了  本质上，目前来说， 计算机相关的，一切数据传输，储存，计算，都是二进制的， 哪有不能传送二进制的呢 只是二进制，由于种种原因，原封不动传输的话， 容易出错，结果不能得到保证。 所以要编码。保证传输可靠。   [/quote]  “如果二进制传输，不进行编码的话 那么就非常不可靠了” ”只是二进制，由于种种原因，原封不动传输的话，容易出错，结果不能得到保证。所以要编码。保证传输可靠。“  我再问深一点，为什么二进制传输不能得到保证，而ascii的字符或者base64字符可以得到保证。。。，，或者说什么样的形式才能得到保证？

user: user-2
content: 引用 11 楼 zhao4zhong1 的回复:既然要研究协议，相关RFC文档还是要研读的。 https://www.baidu.com/s?wd=smtp%20rfc%E6%96%87%E6%A1%A3&rsv_spt=1&rsv_iqid=0xb0fd6b54000afa68&issp=1&f=3&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=14&rsv_sug1=14&rsv_t=75f8A%2Bu5nhzsUXOzMRSmhmucJ9pNf2bMnlcVZIAz4I5tPjCDzHane79H7QeYtPgRJwHd&rsv_sug2=1&prefixsug=smtp%2520RFC&rsp=0&inputT=12392&rsv_sug4=12392

user: user-2
content: 既然要研究协议，相关RFC文档还是要研读的。

user: user-1
content: 引用 8 楼 cc_mugiwala 的回复:[quote=引用 6 楼 cc_mugiwala 的回复:] [quote=引用 5 楼 lm_whales 的回复:]  再看这个书上的原话：  上面写到“smtp不能传送可执行文件或其它的二进制对象”，“smtp限于传送7位的ascii码。许多其他的非英语国家的文字就无法传送” 其实并不是无法传送，只是端系统无法解析？对与传送都是0和1，只要是文件都可以传送的吧？  对呀，没法解析，没法确定有没有出错，没法校验。 不能确定会不会出错，你说能发送吗 要想保证传输不出问题，就必须编码 传输中，有错要么纠正，要么丢弃  另外 smtp 实现上，可能需要保留某些编码， 用于通讯协议， 如果二进制传输，不进行编码的话 那么就非常不可靠了  本质上，目前来说， 计算机相关的，一切数据传输，储存，计算，都是二进制的， 哪有不能传送二进制的呢 只是二进制，由于种种原因，原封不动传输的话， 容易出错，结果不能得到保证。 所以要编码。保证传输可靠。

user: user-0
content: 引用 7 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！  楼主学会使用抓包软件比如wireshark正当时。 赵老师说的是

user: user-0
content: 引用 6 楼 cc_mugiwala 的回复:[quote=引用 5 楼 lm_whales 的回复:] 1）6+1 =7 刚好是在 ASCII范围 2）ASCII，可用用文字表示，这样有错误，肉眼就可以判断出来了 3）编码传输为了方便 通常是 8 ～10 Bits      多余的1～3 bits  可以用来做 奇偶校验，      这样简单错误，很容易就判断出来了 4）ASCII 自带控制码，有时候可以在数据中，插入控制信息。所以就规定只能传输ASCII 大约是这样的，具体原因，还要查查资料。 这和当时的条件有关系。  按你说的，其实是没有技术上的原因，那么我可以这样吗： 发送端发送一段音频文件，其实并不需要用base64，我就把这段音频文件当作普通的文本传送，接收端一样可以接收到数据，只需要指定文件的类型是音频文件，比如mps。 那么其实任何文件(纯文本，音频，图像等)都可以当作纯文本传送(实际都是传送0和1)，而只需要制定文件类型，根本不需要制定Content-Transfer-encoding(编码)。 这样理解对吗？[/quote]  再看这个书上的原话：  上面写到“smtp不能传送可执行文件或其它的二进制对象”，“smtp限于传送7位的ascii码。许多其他的非英语国家的文字就无法传送” 其实并不是无法传送，只是端系统无法解析？对与传送都是0和1，只要是文件都可以传送的吧？

user: user-2
content: 理解和讨论之前请先学会如何观察！  楼主学会使用抓包软件比如wireshark正当时。

user: user-0
content: 引用 5 楼 lm_whales 的回复:1）6+1 =7 刚好是在 ASCII范围 2）ASCII，可用用文字表示，这样有错误，肉眼就可以判断出来了 3）编码传输为了方便 通常是 8 ～10 Bits      多余的1～3 bits  可以用来做 奇偶校验，      这样简单错误，很容易就判断出来了 4）ASCII 自带控制码，有时候可以在数据中，插入控制信息。所以就规定只能传输ASCII 大约是这样的，具体原因，还要查查资料。 这和当时的条件有关系。  按你说的，其实是没有技术上的原因，那么我可以这样吗： 发送端发送一段音频文件，其实并不需要用base64，我就把这段音频文件当作普通的文本传送，接收端一样可以接收到数据，只需要指定文件的类型是音频文件，比如mps。 那么其实任何文件(纯文本，音频，图像等)都可以当作纯文本传送(实际都是传送0和1)，而只需要制定文件类型，根本不需要制定Content-Transfer-encoding(编码)。 这样理解对吗？

user: user-0
content: 引用 1 楼 zhao4zhong1 的回复:仅供参考：#include <stdio.h> #include <string.h> #include <stdlib.h>  #define BASE64_VALUE_SZ 256 int     base64_value[BASE64_VALUE_SZ]; const unsigned char alphabet[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; class Base64Utility { public:     Base64Utility();     int base64_encode(char *src, int srclen, char *dst, int tail);     int base64_decode(char *src, int srclen, char *dst); private:     void base_64_init(void); }; Base64Utility::Base64Utility() {     base_64_init(); } void Base64Utility::base_64_init(void) {     int i;      for (i = 0; i < BASE64_VALUE_SZ; i++) base64_value[i] = -1;     for (i = 0; i < 64; i++) base64_value[(int) alphabet[i]] = i;     base64_value['='] = 0; } int Base64Utility::base64_encode(char *src, int srclen, char *dst, int tail) {     int     bits, char_count, len;     char    *o_char, *lim, *o_lim;     unsigned char   c;      if ( !src || !dst) return 0;     len = srclen;     lim = src + len;     o_char = dst;     o_lim  = dst + (len*4)/3 + 1;     char_count = 0;     bits = 0;     while ( (src < lim) && (o_char < o_lim)) {         c = *(src++);         bits += c;         char_count++;         if (char_count == 3) {             *(o_char++) = alphabet[bits >> 18];             *(o_char++) = alphabet[(bits >> 12) & 0x3f];             *(o_char++) = alphabet[(bits >> 6) & 0x3f];             *(o_char++) = alphabet[bits & 0x3f];             bits = 0;             char_count = 0;         } else {             bits <<= 8;         }     }     if (char_count != 0) {         bits <<= 16 - (8 * char_count);         *(o_char++) = alphabet[bits >> 18];         *(o_char++) = alphabet[(bits >> 12) & 0x3f];         if (char_count == 1) {             if (tail) {                 *(o_char++) = '=';                 *(o_char++) = '=';             }         } else {             *(o_char++) = alphabet[(bits >> 6) & 0x3f];             if (tail) {                 *(o_char++) = '=';             }         }     }     *(o_char) = 0;     return strlen(dst); } int Base64Utility::base64_decode(char *src, int srclen, char *dst) {     int j;     unsigned int k;     int c, base_result_sz;     long val;      if (!src || !dst) return 0;     base_result_sz = srclen;     val = c = 0;     for (j = 0; *src; src++) {         k = (int) *src % BASE64_VALUE_SZ;         if (base64_value[k] < 0) continue;         val <<= 6;         val += base64_value[k];         if (++c < 4) continue;         dst[j++] = (char) (val >> 16);         dst[j++] = (val >> 8) & 0xff;         dst[j++] = val & 0xff;         val = c = 0;     }     switch (c) {         case 2://xxxxxx xx0000             dst[j++] = (val >> 4) & 0xff;         break;         case 3://XXXXXX XXxxxx xxxx00             dst[j++] = (char) (val >> 10);             dst[j++] = (val >> 2) & 0xff;         break;     }     return j; } Base64Utility b64u; #define MAXLENS 1024768 #define MAXLEND 1366360 char bufd[MAXLEND]; char bufs[MAXLENS]; FILE *fs,*fd; int fsize; int main(int argc,char *argv[]) {     if (argc<4) {     USE:         printf("%s <-e|-E|-d> srcfile desfile\n",argv[0]);         return 1;     }     if (stricmp(argv[1],"-e") && stricmp(argv[1],"-d")) goto USE;     if (0==stricmp(argv[1],"-e")) {         fs=fopen(argv[2],"rb");         if (NULL==fs) {             printf("Can not open file %s!\n",argv[2]);             return 2;         }         fsize=fread(bufs,1,MAXLENS,fs);         if (fsize<=0) {             fclose(fs);             printf("Can not read file %s!\n",argv[2]);             return 3;         }         if (MAXLENS==fsize) printf("Warning: Up to %d bytes.\n",MAXLENS);         fclose(fs);         b64u.base64_encode(bufs,fsize,bufd,('E'==argv[2][1]));         fd=fopen(argv[3],"w");         if (NULL==fd) {             printf("Can not create file %s!\n",argv[3]);             return 4;         }         fprintf(fd,"%s",bufd);         fclose(fd);     } else {//0==stricmp(argv[1],"-d")         fd=fopen(argv[2],"rb");         if (NULL==fd) {             printf("Can not open file %s!\n",argv[2]);             return 2;         }         fsize=fread(bufd,1,MAXLEND,fd);         if (fsize<=0) {             fclose(fd);             printf("Can not read file %s!\n",argv[2]);             return 3;         }         if (MAXLEND==fsize) printf("Warning: Up to %d bytes.\n",MAXLEND);         fclose(fd);         fsize=b64u.base64_decode(bufd,fsize,bufs);         fs=fopen(argv[3],"wb");         if (NULL==fs) {             printf("Can not create file %s!\n",argv[3]);             return 4;         }         if (fsize!=(int)fwrite(bufs,1,fsize,fs)) {             printf("Write %s error!\n",argv[3]);             fclose(fs);             return 5;         }         fclose(fs);     }     return 0; }   赵老师，不好意思，我可能把问题的重点没突出，base64的转换我是知道的，我的问题是：          为什么编码会影响数据的传送，因为对于任何编码，传送的都是0和1，这两者应该没关系。  我举个例子：机器A要给机器B发送一份邮件，内容是一句话：“hello”，那么A会首先把“hello”用ascii码进行编码成2进制数据，假如编码的结果是“001001001”，然后进行网络传送，机器B接收到这一串2进制数据，然后用ascii解码，得到“hello”。 现在我想在邮件内容中加入一段非文本数据假如是一段音频数据"100100100"，那直接传送到网络上不就好了？它已经是一串2进制序列了，为什么还要用base64进行编码呢？

user: user-2
content: 电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

user: user-0
content: 这是网上搜的： SMTP至少还有如下缺点。 1)        命令过于简单，没提供认证等功能。 2)        只传送7位的ASCII码，不能传送二进制文件。  想不通，“只传送7位的ASCII码，不能传送二进制文件”，计算机又不理解你什么ascii还是二进制，对计算机来说不都是0和1的序列，，，你是ascii还是二进制，最终都是变成0和1来传送。。

user: user-2
content: 仅供参考：#include <stdio.h> #include <string.h> #include <stdlib.h>  #define BASE64_VALUE_SZ 256 int     base64_value[BASE64_VALUE_SZ]; const unsigned char alphabet[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; class Base64Utility { public:     Base64Utility();     int base64_encode(char *src, int srclen, char *dst, int tail);     int base64_decode(char *src, int srclen, char *dst); private:     void base_64_init(void); }; Base64Utility::Base64Utility() {     base_64_init(); } void Base64Utility::base_64_init(void) {     int i;      for (i = 0; i < BASE64_VALUE_SZ; i++) base64_value[i] = -1;     for (i = 0; i < 64; i++) base64_value[(int) alphabet[i]] = i;     base64_value['='] = 0; } int Base64Utility::base64_encode(char *src, int srclen, char *dst, int tail) {     int     bits, char_count, len;     char    *o_char, *lim, *o_lim;     unsigned char   c;      if ( !src || !dst) return 0;     len = srclen;     lim = src + len;     o_char = dst;     o_lim  = dst + (len*4)/3 + 1;     char_count = 0;     bits = 0;     while ( (src < lim) && (o_char < o_lim)) {         c = *(src++);         bits += c;         char_count++;         if (char_count == 3) {             *(o_char++) = alphabet[bits >> 18];             *(o_char++) = alphabet[(bits >> 12) & 0x3f];             *(o_char++) = alphabet[(bits >> 6) & 0x3f];             *(o_char++) = alphabet[bits & 0x3f];             bits = 0;             char_count = 0;         } else {             bits <<= 8;         }     }     if (char_count != 0) {         bits <<= 16 - (8 * char_count);         *(o_char++) = alphabet[bits >> 18];         *(o_char++) = alphabet[(bits >> 12) & 0x3f];         if (char_count == 1) {             if (tail) {                 *(o_char++) = '=';                 *(o_char++) = '=';             }         } else {             *(o_char++) = alphabet[(bits >> 6) & 0x3f];             if (tail) {                 *(o_char++) = '=';             }         }     }     *(o_char) = 0;     return strlen(dst); } int Base64Utility::base64_decode(char *src, int srclen, char *dst) {     int j;     unsigned int k;     int c, base_result_sz;     long val;      if (!src || !dst) return 0;     base_result_sz = srclen;     val = c = 0;     for (j = 0; *src; src++) {         k = (int) *src % BASE64_VALUE_SZ;         if (base64_value[k] < 0) continue;         val <<= 6;         val += base64_value[k];         if (++c < 4) continue;         dst[j++] = (char) (val >> 16);         dst[j++] = (val >> 8) & 0xff;         dst[j++] = val & 0xff;         val = c = 0;     }     switch (c) {         case 2://xxxxxx xx0000             dst[j++] = (val >> 4) & 0xff;         break;         case 3://XXXXXX XXxxxx xxxx00             dst[j++] = (char) (val >> 10);             dst[j++] = (val >> 2) & 0xff;         break;     }     return j; } Base64Utility b64u; #define MAXLENS 1024768 #define MAXLEND 1366360 char bufd[MAXLEND]; char bufs[MAXLENS]; FILE *fs,*fd; int fsize; int main(int argc,char *argv[]) {     if (argc<4) {     USE:         printf("%s <-e|-E|-d> srcfile desfile\n",argv[0]);         return 1;     }     if (stricmp(argv[1],"-e") && stricmp(argv[1],"-d")) goto USE;     if (0==stricmp(argv[1],"-e")) {         fs=fopen(argv[2],"rb");         if (NULL==fs) {             printf("Can not open file %s!\n",argv[2]);             return 2;         }         fsize=fread(bufs,1,MAXLENS,fs);         if (fsize<=0) {             fclose(fs);             printf("Can not read file %s!\n",argv[2]);             return 3;         }         if (MAXLENS==fsize) printf("Warning: Up to %d bytes.\n",MAXLENS);         fclose(fs);         b64u.base64_encode(bufs,fsize,bufd,('E'==argv[2][1]));         fd=fopen(argv[3],"w");         if (NULL==fd) {             printf("Can not create file %s!\n",argv[3]);             return 4;         }         fprintf(fd,"%s",bufd);         fclose(fd);     } else {//0==stricmp(argv[1],"-d")         fd=fopen(argv[2],"rb");         if (NULL==fd) {             printf("Can not open file %s!\n",argv[2]);             return 2;         }         fsize=fread(bufd,1,MAXLEND,fd);         if (fsize<=0) {             fclose(fd);             printf("Can not read file %s!\n",argv[2]);             return 3;         }         if (MAXLEND==fsize) printf("Warning: Up to %d bytes.\n",MAXLEND);         fclose(fd);         fsize=b64u.base64_decode(bufd,fsize,bufs);         fs=fopen(argv[3],"wb");         if (NULL==fs) {             printf("Can not create file %s!\n",argv[3]);             return 4;         }         if (fsize!=(int)fwrite(bufs,1,fsize,fs)) {             printf("Write %s error!\n",argv[3]);             fclose(fs);             return 5;         }         fclose(fs);     }     return 0; }