为什么文件传输之前先要发送一个OK信息

wuxia2118 2019-05-04 10:08:22
我看了任何文件传输程序,在传输文件之前接收方都要发送一个OK信息,发送方收到OK信息之后才能发送。我把发送接收OK信息的代码去掉就不能完整地传输文件呢?下面是我的示例程序,大家能分析下是为什么吗
发送方
#include "stdafx.h"
#include<iostream.h>
#include<winsock2.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
int main(){
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData)) //初始化WinSock协议栈
{ cout<<"Winsock不能被初始化!";
WSACleanup();
return 0;
}
SOCKET sockSer, sockConn; //注意服务器端必须创建两个套接字
sockSer=socket(AF_INET,SOCK_STREAM,0); //初始化套接字
SOCKADDR_IN addrSer,addrCli; //注意服务器端要创建两个套接字地址
addrSer.sin_family=AF_INET;
addrSer.sin_port=htons(5566);
addrSer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");

bind(sockSer,(SOCKADDR*)&addrSer,sizeof(SOCKADDR)); //绑定套接字
listen(sockSer,5);

int len=sizeof(SOCKADDR);
cout<<"服务器等待客户端的连接……"<<endl;

sockConn=accept(sockSer,(SOCKADDR*)&addrCli,&len); //接受连接,注意返回值
if(sockConn==INVALID_SOCKET){
cout<<"服务器接受客户端连接失败!"<<endl;
return 0;}
else cout<<"服务器接受客户端连接成功!"<<endl;

char fileName[256]="C:\\cf.jpg";

char filebuf[1000],OK[3],fsize[50];
/***打开要传输的文件***/
FILE *fp; //创建文件指针
if((fp=fopen(fileName,"rb"))==NULL) { //以只读字节型模式打开文件
cout << "不能打开文件: " << fileName << endl;
closesocket(sockConn); //关闭socket,对方等待的recv()函数将返回0
closesocket(sockSer); WSACleanup();
return 0; } //文件打开失败则退出
/***获取文件长度***/
fseek(fp,0L,SEEK_END); //将文件的位置指针移到文件末尾
long int size=ftell(fp); //获取当前文件位置指针值,该值即为文件长度
fseek(fp,0L,SEEK_SET); //将文件的位置指针移到文件开头
long int fileSize=size;
//fileSize = htonl(size); //将文件长度存入结构变量fileMsg
itoa(fileSize,fsize,10);
send(sockConn, fsize, strlen(fsize)+1, 0); //发送fileName
cout<<fsize;
/***接收对方发送来的OK信息***/
if (recv(sockConn, OK, sizeof(OK), 0) <= 0) {
cout << "接收OK失败,程序退出!\n";
closesocket(sockSer); WSACleanup();
return 0; }

/***发送文件内容***/

if (strcmp(OK, "OK") == 0) {
while(!feof(fp)) { //当文件没有到末尾时

size=fread(filebuf,1,sizeof(filebuf),fp); //每次读1000字节
send(sockConn, filebuf, size, 0); //每次写size个字节
}
cout << "文件发送完毕"; //显示传输完成
fclose(fp); } //关闭文件



closesocket(sockSer);
WSACleanup();
return 0; }

接收方

#include "stdafx.h"
#include<iostream.h>
#include<winsock2.h>
#include <stdio.h>
#include "direct.h" //_mkdir()函数需要
#pragma comment(lib,"ws2_32.lib")
int main(){
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData)) {
cout<<"Winsock不能被初始化!";
WSACleanup();
return 0; }
SOCKET sockCli; //创建套接字sockCli
sockCli=socket(AF_INET,SOCK_STREAM,0);

SOCKADDR_IN addrSer; //客户端只要创建一个套接字地址
addrSer.sin_family=AF_INET;
addrSer.sin_port=htons(5566);
addrSer.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");

int res=connect(sockCli,(SOCKADDR*)&addrSer, sizeof(SOCKADDR));
if(res){ cout<<"客户端连接服务器失败"<<endl;
return -1; }
else{ cout<<"客户端连接服务器成功"<<endl; }
char sendbuf[256], recvbuf[256];

long int filelen;
char filedir[200]= "D:\\TANG\\"; //指定接收到的文件的保存目录
char ok[3]="OK",fsize[50];
char fileBuffer[1000];//接收文件数据的缓冲区
/***创建文件的保存目录***/
_mkdir(filedir); //_mkdir()用于创建文件夹
/***接收文件名及文件长度信息***/
if((filelen=recv(sockCli,fsize,sizeof(fsize),0))<=0){
cout<<"未接收到文件名字及文件长度!\n";
closesocket(sockCli); WSACleanup();
return 0; }
filelen=atol(fsize);
/***创建文件准备接收文件内容***/
char filename[256]="e:\\cf.jpg";
FILE *fp; //创建文件指针
if((fp=fopen(filename,"wb"))==NULL) {//以只写方式打开文件
cout<<"不能打开文件:"<<filename<<endl;
closesocket(sockCli);
WSACleanup();
return 0; } //文件打开失败则退出
cout<<filelen;
send(sockCli,ok,sizeof(ok),0); //发送接收文件数据的确认信息
/***接收文件数据并写入文件***/
long int size=0; //接收到的数据长度
do {
size=recv(sockCli,fileBuffer,sizeof(fileBuffer),0);
fwrite(fileBuffer,1,size,fp); //写入文件,每次写size字节
filelen-=size;
}while(size!=0 && filelen>0); //循环条件是size!=0 && filelen>0
/***文件传输完成结束程序***/
cout<<"接收文件"<<filename<<"完毕!\n";
fclose(fp);

while(1){
cout<<"客户端说:>";
cin>>sendbuf;
if(strcmp(sendbuf,"bye")==0){
break;}
send(sockCli,sendbuf,strlen(sendbuf)+1,0);
if(recv(sockCli,recvbuf,256,0)>0)
cout<<"服务器说:>"<<recvbuf<<endl;
else {cout<<"服务器已关闭连接"<<endl;
break;}
}
closesocket(sockCli);
WSACleanup();
return 0;
}
...全文
783 19 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
XM3990205HZ2552 2019-09-07
  • 打赏
  • 举报
回复
请问,windows上的IO重定向,可以直接把打开的文件描述符定向到socket描述符吗
worldy 2019-08-29
  • 打赏
  • 举报
回复
引用 3 楼 wuxia2118 的回复:
去掉了,直接发文件会出错,接收到的文件少了几Kb。


不可能的,发送OK不是必须的,完全可以去掉,只要明确文件发送的起点及终点(可以指明文件长度)
月竹影 2019-08-28
  • 打赏
  • 举报
回复
你刚开始学,还是想办法先调试起来,还有一个简单或者傻的办法,就是发送任何数据之前先发送一个整数的长度,表示下来要发送多长的数据块,接收的时候先接收4个字节的整数长度,然后就知道剩余还有多少数据需要接收,在循环接收完剩余的数据就行。
char szBuf[1024] ={0};
strcpy(szBuf,filebuf,size);
int iDataSize= size;
send(sock,(char*)&iDataSize,sizeof(iDataSize),0);
send(sock,szBuf,iDataSize,0);

接收端:
int iDataSize= 0;
char szBuf[1024] ={0};
int iRet = recv(sock,(char*)&iDataSize,sizeof(iDataSize),0);
if(iRet ==sizeof(iDataSize))
{
int iTotalRecvLen = 0;
while(iTotalRecvLen <iDataSize)
{
iRet = recv(sock,szBuf+,iDataSize-iTotalRecvLen,0);
if(iRet<=0)
break;
iTotalRecvLen+=iRet;
}
}

我博客里写了一套开源的通信框架,你有空可以看看,不过对你来讲,可能比较复杂。
https://blog.csdn.net/moonbamboo/article/details/99286765
wuxia2118 2019-08-16
  • 打赏
  • 举报
回复
我这个 异步通信的文件传输程序
https://download.csdn.net/download/wuxia2118/11522767
wuxia2118 2019-08-16
  • 打赏
  • 举报
回复
我这个不异步通信的文件传输程序确实不需要发送OK消息,也可以收发文件。所以我猜想发送OK信息,可能是为了隔断前面的发送文件大小/文件名 和后面的 发送 文件内容, 使 前 后的发送数据不会发送粘包现象,我这只是猜想,不知道如何证实。
wuxia2118 2019-08-16
  • 打赏
  • 举报
回复
引用 12 楼 索尼与三星 的回复:
请问你这个程序怎么运行?小白不懂,同一项目下,两个.c文件都有main函数,怎么运行?

要建立两个项目,一个是服务器端,一个客户端,才能相互通信
xhx515253 2019-08-15
  • 打赏
  • 举报
回复
了解下文件传输协议Xmodem,Ymodem。接收者是根据协议解析数据的。
索尼与三星 2019-08-14
  • 打赏
  • 举报
回复
请问你这个程序怎么运行?小白不懂,同一项目下,两个.c文件都有main函数,怎么运行?
wuxia2118 2019-05-31
  • 打赏
  • 举报
回复
我发现异步接收文件的程序,可不需要发送和接收OK信息
lbh_ITsy 2019-05-11
  • 打赏
  • 举报
回复
这和它们之间的协议有关吧
sichuanwww 2019-05-10
  • 打赏
  • 举报
回复
学习研究一下
wuxia2118 2019-05-09
  • 打赏
  • 举报
回复
我用VC6,确实不知道怎么加断点调试。
一彤 2019-05-07
  • 打赏
  • 举报
回复
这就是神秘莫测的协议
翅膀又硬了 2019-05-07
  • 打赏
  • 举报
回复
你不会加断点调试吗?
wuxia2118 2019-05-06
  • 打赏
  • 举报
回复
引用 4 楼 Eleven 的回复:
接收端接收到文件长度以后,按这个长度来循环recv接收后续的数据。
我是说发送OK标记的作用,发送文件长度的作用,那我倒是知道的
Eleven 2019-05-06
  • 打赏
  • 举报
回复
接收端接收到文件长度以后,按这个长度来循环recv接收后续的数据。
wuxia2118 2019-05-06
  • 打赏
  • 举报
回复
去掉了,直接发文件会出错,接收到的文件少了几Kb。
smwhotjay 2019-05-05
  • 打赏
  • 举报
回复
可以去掉。直接发文件。
zgl7903 2019-05-05
  • 打赏
  • 举报
回复
个人理解 就是用Ok做了个简单的分界协议

18,363

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧