Web版PACS开发纪要二:DCM文件的网络传输
——解决文件传输数据“丢失”问题
目录
背景介绍
问题搜索
问题分析
问题解决
0背景介绍
该工程是上个月博文的延续。在利用“完成端口”完成了文件自动归档的基础上,本次需要利用socket套接字进行文件的远距离传输。虽然socket编程的参考书籍很多,但是在具体实现过程中还是遇到了各种各样的问题。下面继续记录一下工作中遇到的问题,一方面作为工作纪要,为后续工程的扩展做准备,另一方面作为自己学习的笔记,加深网络编程方面的知识。
首先说一下socket套接字传输文件部分的基本流程:首先利用上次完成的“文件夹实时监控”,将文件从分散的文件夹中归档到统一的目录下,默认为:e:\MedicalImages;然后利用socket套接字结合完成端口,将e:\MedicalImages文件夹下的文件传输到远端服务器。基本结构图如下:
1问题搜索
从图中可以看出,原始字节流(即源文件)比目标字节流(接收到的文件)多出了850字节。但是在调试过程中并未发现有send或recv函数发出错误,那么这“丢失”的850字节去哪里了呢?对此问题进行搜索
尝试一:send和recv函数是否是阻塞的?
send | 客户端和服务端都通过send函数来向TCP连接的另一端发送数据 客户端用send向服务端发送请求; 服务端用send向客户端发送应答 |
recv | 客户端和服务端都通过recv函数接收来自TCP连接另一端的数据 |
1.1简言之,阻塞就是send和recv必须完成其相应的任务才返回,将控制权交给自己编写的程序;非阻塞就是send和recv未等其任务完成就直接返回,将控制权交给调用者程序;
1.2阻塞时刻
send和recv函数的阻塞与accept函数的阻塞时刻略有不同,这是由于函数实现的功能以及TCP协议造成的。send函数的工作是将给定缓冲区(此缓冲区是程序中由程序员自己开辟的,存在于程序的堆或栈中)中的数据拷贝到TCP/IP协议栈的缓冲区(传输层开辟的接收/发送缓冲区,不同于程序员自己开辟的堆栈空间),在协议栈缓冲区未满时,阻塞和非阻塞的send函数效果相同都会直接返回,代表数据发送成功,其实此时数据依然存在于send端的TCP/IP协议栈的缓冲区中,并未真正发送出去;当协议栈缓冲区已满,阻塞和非阻塞的send函数就表现出了不同,阻塞send函数会将调用进程(线程)挂起,直到协议栈缓冲区中有足够的空间来存储send函数中指定的程序缓冲区数据,有时为了防止程序阻死会设置超时时间,当超过此时间阻塞send函数也会返回。非阻塞send函数发现协议栈缓冲区没有足够空间时,尽能力的拷贝,返回成功拷贝的大小;如缓存区可用空间为0,会立刻返回,并提示WSAEWOULDDBLOCK给程序员,告知“协议栈缓冲区已满,数据无法拷贝”——你自己想办法处理吧o(╯□╰)o”
【小结】:单步调试分项目,发现send和recv函数并未出现阻塞现象,也就是说在传送过程中TCP/IP协议栈的缓冲区空间充裕。那么为何会“丢失”数据呢?
参考博文:
http://blog.csdn.net/xiaofei0859/article/details/6037814 (Windows下情形)