图像检索服务器编写问题记录——用socket传输图片
来源:互联网 发布:投诉数据分析ppt 编辑:程序博客网 时间:2024/04/29 03:39
1.用readn代替read的原因
为避免频繁的调用read。read调用系统调用,系统调用需要在用户态和核心态转换,需要保存上下文,频繁调用read,会使系统性能下降,in指标上升。为避免频繁调用read,我们在用户空间创建用户缓冲区,将套接字的缓冲区的内容全部读入用户缓冲区后,一次性把用户缓冲区的内容用read写入内核缓冲区。这样可以提高效率。相同的writen也是这个原因。
ssize_t unpluo_readn(int fd,void* vptr,int n){size_t nleft=n;char *ptr=(char*)vptr;ssize_t nread;while(nleft>0){if(nread=read(fd,ptr,nleft)<0){if(errno==EINTR)nread=0;else return -1;}else if(nread==0)break;nleft-=nread;ptr+=nread;}return (n-nleft);}
2.标准IO与文件IO的区别
FILE的fopen等标准IO是库文件,标准IO将硬盘上的文件一次性读入内存中,使用文件指针加以操作,在fclose之后,将内存中的文件写回磁盘。所以通常说标准文件是流操作。标准IO的操作一直在用户态。
read、write等文件IO是系统调用(使用了系统调用),文件IO用于文件在用户态和核心态之间的传输。
通常的搭配。标准IO打开文件,fopen调用read从磁盘上将内容拷贝至内存,标准IO操作内存中的文件流,fclose调用write将文件从内存拷贝回硬盘。
3.服务器端
4.客户端逻辑:先从客户端接收图片大小,创建图片大小的空文件,然后接收客户端发来的图片。
void servluo_match(int sockfd){char recv[MAXLINE];char flen[7];unpluo_readn(sockfd,flen,7);fprintf(stderr,"the size of image is %s\n",flen);int bytes=atoi(flen);FILE *dlf=NULL;if(bytes>0){char filename[100];strcpy(filename,"image/tmp.jpg");dlf=fopen(filename,"wb");if(dlf==NULL){fprintf(stderr,"failed open file\n");return;}fprintf(stderr,"start recv image %s\n",filename);while(bytes>MAXLINE){unpluo_readn(sockfd,recv,MAXLINE);bytes-=MAXLINE;fwrite(recv,MAXLINE,1,dlf);}if(bytes<=MAXLINE){unpluo_readn(sockfd,recv,bytes);char *tmp=recv;strcat(tmp,"\r\n");fwrite(recv,bytes,1,dlf);tmp=NULL;}fclose(dlf);fprintf(stderr,"write done");}}此处的坑是:在读取图片最后的那点数据时,需要在文件结尾加上\r\n,不然图片传输过来都是打不开的。其他考虑:
1.如果客户端放在windows下,就需要将每个接收到的\r\n替换成\n了。
逻辑:先发送图片大小,然后再发送图片
void str_cli(FILE *fp, int sockfd){char send[MAXLINE];//while(1)//{fprintf(stderr,"please input the name of retrieved image file:");fflush(stdin);fflush(stdout);fflush(stderr);char tmp[100];if(fgets(tmp,MAXLINE,fp)==NULL)continue;char *filename=strtok(tmp,"\n");//需要去除\n否则文件打开失败FILE *ulf=fopen(filename,"rb");if(ulf==NULL){fprintf(stderr,"failed open %s\n",filename);continue;}fprintf(stderr,"open file %s,",filename);long filelen;//计算文件长度fseek(ulf,0,SEEK_END);filelen=ftell(ulf);rewind(ulf);char flen[7];sprintf(flen,"%d\n",filelen);fprintf(stderr,"it's size is %s",flen);unpluo_writen(sockfd,flen,7);//至此发送文件大小long left=filelen;while(left>MAXLINE){fread(send,MAXLINE,1,ulf);unpluo_writen(sockfd,send,MAXLINE);left-=MAXLINE;}if(left<=MAXLINE){fread(send,left,1,ulf);unpluo_writen(sockfd,send,left);}fclose(ulf);fprintf(stderr,"send %s ok\n",filename);//}return;}此处的坑是:客户端分两次发送文件大小和图片,但是于服务器而言可能是一次性接收的一堆内容,所以第一次发送文件大小的char[]大小一定要与服务器端一致,否则,服务器端【图片的字节】被【大小的字节】给占了。
0 0
- 图像检索服务器编写问题记录——用socket传输图片
- 图像检索服务器编写问题记录——epoll+多线程传输图片时的问题
- 图像检索服务器编写问题记录——日志系统问题记录
- 图像检索服务器编写问题记录——加入信号安装后的问题
- 图像检索服务器编写问题记录——特征库的存储问题
- 图像检索服务器编写问题记录——服务器端模型选择+epoll和非阻塞IO
- 图像检索服务器编写问题记录——拒绝可恶的编译器优化
- 图像检索服务器编写问题记录——日志定时写回
- 图像检索服务器编写问题记录——服务器端模型再思考
- 图像检索服务器编写问题记录——线程中信号的处理方式思考
- 图像检索服务器编写问题记录——添加线程池
- 图像检索服务器编写问题记录——SIFT尺度不变特征变换匹配算法学习
- 图像检索服务器编写问题记录——MSER最大稳定极值区域检测
- 图像检索服务器编写问题记录——TCP粘包了!!!
- 图像检索服务器编写问题记录——服务端的任务队列线程分配的反思
- 图像检索服务器编写问题记录——关于任务队列的思考
- 图像检索服务器编写问题记录——回忆历次版本更改
- 图像检索服务器编写问题记录——用单例模式确保log类、server类只返回一个实例
- 1. Why Machine Learning Strategy 为什么需要机器学习策略(《MACHINE LEARNING YEARNING》翻译)
- 【专题】单调队列
- JSP和Servlet的相互调用
- 梁勇2011JAVA语言程序设计基础篇第16章编程题16.16闪烁的标签
- c++设计模式之命令模式
- 图像检索服务器编写问题记录——用socket传输图片
- (6)DTD的基本结构
- PAT 1091. Acute Stroke (30)
- 虚拟机Linux下安装JDK
- C# 委托学习(1) 基本概念学习
- 基于visual c++之windows核心编程代码分析(11)实现屏幕截取
- 评价特征 分类
- 关于Fragment中的getActivity()返回null导致程序崩溃的解决方案
- python标准库之logging