Linux C系统编程中的文件传输问题:只能传送文本文件,不能传送二进制文件。(TCP+文件I/O实现)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux C系统编程中的文件传输问题:只能传送文本文件,不能传送二进制文件。(TCP+文件I/O实现)相关的知识,希望对你有一定的参考价值。

其中的网络部分应该是没有问题的,毕竟文本都能完全传输正确(使用diff命令判别过)。也让服务器、客户端的发送接收方分别用字符串打印传送的数据,3方的结果都是一样的。
用Araxis Merge比较了发送前后的二进制文件,结果发现传送生成的新文件中大约有四分之一是错误(粗略估计,没仔细清点),碎块一般有2~18个字节,跟文件碎片差不多感觉的分布。
感觉是文件读写方面出错了,可是我用的是open/read/write之类的函数,照道理是对文件是否是文本不做区分的啊?
自己也用同样的方法另写了一个简单的CS,结果居然传送二进制文件传送成功了,没有道理啊。

二进制模式传输文本文件没有问题,但是ASCII模式传输二进制文件会出问题
因为有些控制字符会被错误处理。比如二进制文件中的0,在传输的时候会被当作字符串结束符,这样是无法传送的。所以传输二进制文件的时候状况与文本文件是不一样的。
参考技术A 下面这段是发送文件内容及其16进制编码的。

file = fopen("w:\\temp.dat","rb");
if(file)

buffer[0]=0;
char temp[64];
while(1)

r = fread(buffer,1,16,file);
buffer[r]=0;
int index=0;
for(index=0;index<r;index++)

sprintf(temp,"%02x ",(unsigned char)buffer[index]);
printf(temp);
send(AcceptSocket,temp,strlen(temp),0);

for(index=r;index<16;index++)

sprintf(temp," ");
printf(temp);
send(AcceptSocket,temp,strlen(temp),0);

for(index=0;index<r;index++)

if((unsigned char)buffer[index]>=0x20)

sprintf(temp,"%c",(unsigned char)buffer[index]);
printf(temp);
send(AcceptSocket,temp,strlen(temp),0);
else

sprintf(temp,".");
printf(temp);
send(AcceptSocket,temp,strlen(temp),0);


sprintf(temp,"\r\n");
printf(temp);
send(AcceptSocket,temp,strlen(temp),0);
//send(AcceptSocket,buffer,r,0);
if (r<16) break;


printf("(end)\r\n");

fclose(file);
追问

我也知道这么改可能会成功,可是为什么用open/write/read这种函数时会出错啊?可能是我有些倔强了吧,我就是想知道,为什么我的用法会出错。如果能回答的话,我悬赏加到200

追答

openg 加上O_BINARY 标志

参考技术B 应该是因为你从文件读出来的数据和发出去的数据不同,比如你用read(fd, buf, 1024); write(socketfd, buf, strlen(buf));这样可能会出错,我试过。最好是int num = read(fd, buf, 1024);write(socketfd, buf, num);就是将strlen(buf)改为read()函数的返回值! 参考技术C 你是用同一个程序传送文本和二进制文件的吗?
是全部按固定长度传送的吗?
传送的缓冲区多大?
你把传送的文本文件,用Araxis Merge比较,而不是diff,是否也完全一样?
如果有代码,可能更方便分析。追问

使用同一个程序;
按同样长度传送,但是有一个int记录实际读取到的长度;
缓冲区长度200;
只要是文本文件,不论Araxis Merge还是diff,结果都完全一样;
代码总共有5千多行,写得很乱,可读性太差,上传有点不切实际。

追答

这个可能要调试才能知道原因了。如果方便,传相关代码部分,到QQ 1969382627.

参考技术D 老夫做了这么久码农,可以负责任的告诉你,不可能fread可以,read却不可以的,绝对是你的程序流程出错了 ,先检查一下你的程序对不对吧追问

不好意思,你可能没看清楚。我用的是read,而没用过fread。如果程序流程出错,没道理文本能传正确啊。

Linux-sys文件系统

1、sys文件系统本质上和proc文件系统是一样的,都是虚拟文件系统。都在根目录下有个目录(一个是/proc目录,另一个是/sys目录),因此都不是硬盘中的文件,都是内核中的数据结构的可视化接口。

2、不同的是/proc中的文件只能读,但是/sys中的文件可以读写。读/sys中的文件就是获取内核中数据结构的值,而写入/sys中的文件就是设置内核中的数据结构的元素的值。

3、历史上刚开始先有/proc文件系统,后来人们希望通过这种技术来调试内核。实际做出来的时候确实是很有用,所以很多内核开发者都去内核添加代码向/proc目录中写文件,而且刚开始的时候内核管理者对proc目录的使用也没有什么经验也没有什么统一规划,后来导致的结果就是proc里边的内容又多又杂乱。

4、后来觉得proc中的内容太多太乱缺乏统一规划,于是乎又添加了sys目录。sys文件系统一开始就做了很好的规划和约定,所以后来使用sys目录时有了规矩。

以上是关于Linux C系统编程中的文件传输问题:只能传送文本文件,不能传送二进制文件。(TCP+文件I/O实现)的主要内容,如果未能解决你的问题,请参考以下文章

linux中利用write函数来写是不是只能写文本文档,而不能写二进制文件?

嵌入式linux怎样用串口传送文件

请教用C语言编的借助UDP协议实现的文件传输的程序

Linux系统编程进程间通信之无名管道

搭建FTP服务

Linux--用SecureCRT来上传和下载文件