利用流式套接字实现文件的传输.docx
- 文档编号:11341599
- 上传时间:2023-02-28
- 格式:DOCX
- 页数:15
- 大小:18.49KB
利用流式套接字实现文件的传输.docx
《利用流式套接字实现文件的传输.docx》由会员分享,可在线阅读,更多相关《利用流式套接字实现文件的传输.docx(15页珍藏版)》请在冰豆网上搜索。
利用流式套接字实现文件的传输
网络编程技术实验报告
实验名称
实验四利用流式套接字传输文件实验
队别
姓名
学号
实验日期
2015.12.11
实验报告要求:
1.实验目的2.实验要求3.实验环境4.实验作业5.问题及解决
6.思考问题7.实验体会
【实验目的】
1.掌握定长与变长流式套接字的使用方法
2.加深对流式套接字的掌握
3.掌握一些解决实际问题的能力
【实验要求】
客户端向服务器发起socket连接,并建立数据传输通道
客户端向服务器发送要传输的文件名称,以"#"字符结尾,服务器逐字接收,直到接收到#(变长数据)
客户端向服务器发送文件长度,4字节(定长数据)
客户端向服务器文件内容(变长数据)
服务端接收完文件后,向客户端发送ok,以示成功接收
客户端接收到OK后,关闭套接字
服务器关闭套接字
【实验环境】
Devc
【实验作业】
客户端:
inttcp_client_fun_echo(FILE*fp,SOCKETs)
{
intiResult;
charsendline[MAXLINE],recvline[MAXLINE];
charfile[20];
charflong[4];
inti=0;//文件名发送控制
//初始化缓冲区
FILE*f;//写文件指针
char*buff;//读入文件内容
uint32_tnFileLen;//文件长度
printf("请输入文件名:
\n");
scanf("%s",&file);
f=fopen(file,"rb");
if(f==NULL)
printf("打开文件失败或文件不存在!
\n");
fseek(f,0,SEEK_END);
nFileLen=ftell(f);
rewind(f);//回到到文件头部
buff=(char*)malloc(nFileLen);
iResult=fread(buff,1,nFileLen,f);
if(iResult!
=nFileLen)
{
printf("读入文件错误!
\n");
return0;
}
memset(sendline,0,MAXLINE);
memset(recvline,0,MAXLINE);
while(i!
=nFileLen)
{
recvline[i]=*buff;
i++;
buff++;
}
//文件名传输结束
sprintf(sendline,"%s#%d%s",file,nFileLen,recvline);
iResult=send(s,sendline,sizeof(sendline),0);
if(iResult==SOCKET_ERROR)
{
printf("send函数调用错误,错误号:
%d",WSAGetLastError());
return-1;
}
fclose(fp);
printf("文件发送完成!
\n");
returniResult;
}
服务器:
inttcp_server_fun_echo(SOCKETs)
{
FILE*fp;
inti=0;
charflong[4];
intiResult=0;
uint32_tnFileLen=1;
charrecvline[MAXLINE];
charfile[10];
memset(file,0,sizeof(file));
memset(recvline,0,sizeof(recvline));
for(;;)
{
iResult=recv(s,&file[i],1,0);
if(iResult==SOCKET_ERROR)
{
printf("recv函数调用错误,错误号:
%d",WSAGetLastError());
return-1;
}
if(file[i]=='#')
break;
else
i++;
}
file[i]='\0';
fp=fopen(file,"w+");
if(fp==NULL)
printf("文件打开失败!
");
//接收文件长度
iResult=recv(s,flong,4,0);
if(iResult==SOCKET_ERROR)
{
printf("recv函数调用错误,错误号:
%d",WSAGetLastError());
return-1;
}
sscanf(flong,"%d",&nFileLen);
iResult=recv(s,recvline,nFileLen,0);
if(iResult==SOCKET_ERROR)
{
printf("recv函数调用错误,错误号:
%d",WSAGetLastError());
return-1;
}
fputs(recvline,fp);
fclose(fp);
printf("文件接收成功!
\n");
returniResult;
}
头文件(上次的实验报告中已经写过):
#ifndefp_h//预处理指令,防止重复包含头文件
#include
#include
#include
#include
#include
#pragmacoment(lib,"ws2_32.lib")
usingnamespacestd;
classCSocketFrame
{
public:
intstart_up();
intclean_up();
intset_address(char*hname,char*sname,structsockaddr_in*sap,char*protocol);
intquit(SOCKETs);
SOCKETtcp_server(ULONGuIP,USHORTuPort);
SOCKETtcp_server(char*hname,char*sname);
SOCKETtcp_client(char*hname,char*sname);
SOCKETtcp_client(ULONGuIP,USHORTuPort);
};
intCSocketFrame:
:
start_up(void)
{
WORDwVersionRequested;
WSADATAwsaData;
intiResult;
wVersionRequested=MAKEWORD(2,2);
iResult=WSAStartup(wVersionRequested,&wsaData);
if(iResult!
=0)
{
printf("WSAStartup调用错误,错误号:
%d\n",WSAGetLastError());
return-1;
}
/*
if(LOBYTE(wsaData.wVersion!
=2||HIBYTE(wsaData.wVersion)!
=2))
{
printf("无法找到可用的WSD版本\n");
WSACleanup();
return-1;
//告诉用户无法找到可用的WSD
}
else
{
printf("WS2.2初始化成功!
\n");
}*/
return0;
}
intCSocketFrame:
:
clean_up(void)
{
intiResult;
iResult=WSACleanup();
if(iResult==SOCKET_ERROR)
{
//WSACleanup()调用失败
printf("WSACleanup调用错误,错误号:
%d\n",WSAGetLastError());
return-1;
}
else
printf("Winsocketdll释放成功!
\n");
return0;
}
intCSocketFrame:
:
set_address(char*hname,char*sname,structsockaddr_in*sap,char*protocol)
{
structservent*sp;
structhostent*hp;
char*endptr;
unsignedshortport;
unsignedlongulAddr=INADDR_NONE;
//将地址结构socketsddr_in初始化为0,并将地址族设为AF_INET
memset(sap,0,sizeof(*sap));
sap->sin_family=AF_INET;
if(hname!
=NULL)
{
//如果hname不为空,转化地址格式
ulAddr=inet_addr(hname);
if(ulAddr==INADDR_NONE||ulAddr==INADDR_ANY)
{
//调用错误,调用gethostbyname获得主机地址
hp=gethostbyname(hname);
if(hp==NULL)
{
printf("未知的主机名,错误号:
%d\n",WSAGetLastError());
return-1;
}
sap->sin_addr=*(structin_addr*)hp->h_addr;
}
else
sap->sin_addr.S_un.S_addr=ulAddr;
}
else
//如果调用者没有指明一个主机名或地址,则设为通配地址
sap->sin_addr.s_addr=htonl(INADDR_ANY);
//尝试转换sname为一个整数
port=(unsignedshort)strtol(sname,&endptr,0);
if(*endptr=='\0')
{
//如果成功转化为网络字节序
sap->sin_port=htons(port);
}
else
{
//如果失败,则假定是一个服务名称,通过getservbyname()函数获得端口号
sp=getservbyname(sname,protocol);
if(sp==NULL)
{
printf("未知服务,错误号:
%d\n",WSAGetLastError());
return-1;
}
sap->sin_port=sp->s_port;
}
return0;
}
intCSocketFrame:
:
quit(SOCKETs)
{
intiResult=0;
iResult=closesocket(s);
if(iResult==SOCKET_ERROR)
{
printf("closesocket调用错误,错误号:
%d\n",WSAGetLastError());
return-1;
}
iResult=clean_up();
returniResult;
}
SOCKETCSocketFrame:
:
tcp_server(char*hname,char*sname)
{
SOCKETListenSocket;
intiResult=0;
sockaddr_inlocal;
constinton=1;
//为服务器的本机地址设置用户输入的地址以及端口号
if(set_address(hname,sname,&local,(char*)"tcp")!
=0)
return-1;
//创建套接字
ListenSocket=socket(AF_INET,SOCK_STREAM,0);
if(ListenSocket==INVALID_SOCKET)
{
printf("socket函数调用错误,错误号:
%d\n",WSAGetLastError());
WSACleanup();
return-1;
}
//绑定服务器地址
iResult=bind(ListenSocket,(structsockaddr*)&local,sizeof(local));
if(iResult==-1)
{
printf("bind函数调用错误!
错误号:
%d\n",WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return-1;
}
//设置函数为监听状态,监听队列长度为NLISTEN
iResult=listen(ListenSocket,SOMAXCONN);
if(iResult==SOCKET_ERROR)
{
printf("Listen函数调用错误!
错误号:
%d\n",WSAGetLastError());
quit(ListenSocket);
return-1;
}
returnListenSocket;
}
SOCKETCSocketFrame:
:
tcp_server(ULONGuIP,USHORTuPort)
{
SOCKETListenSocket=INVALID_SOCKET;
intiResult=0;
sockaddr_inlocal;
constinton=1;
//为服务器的本机地址设置用户输入的地址以及端口号
memset(&local,0,sizeof(local));
local.sin_family=AF_INET;
local.sin_addr.S_un.S_addr=htonl(uIP);
local.sin_port=htons(uPort);
ListenSocket=socket(AF_INET,SOCK_STREAM,0);
if(ListenSocket==INVALID_SOCKET)
{
printf("socket函数调用错误,错误号:
%d\n",WSAGetLastError());
clean_up();
return-1;
}
//绑定服务器地址
iResult=bind(ListenSocket,(structsockaddr*)&local,sizeof(local));
if(iResult==SOCKET_ERROR)
{
printf("bind函数调用错误!
错误号:
%d\n",WSAGetLastError());
quit(ListenSocket);
return-1;
}
//设置函数为监听状态,监听队列长度为NLISTEN
iResult=listen(ListenSocket,SOMAXCONN);
if(iResult==SOCKET_ERROR)
{
printf("Listen函数调用错误!
错误号:
%d\n",WSAGetLastError());
quit(ListenSocket);
return-1;
}
returnListenSocket;
}
SOCKETCSocketFrame:
:
tcp_client(char*hname,char*sname)
{
intiResult=0;
structsockaddr_inpeer;
SOCKETClientSocket;
//为服务器的地址peer设置用户输入的地址以及端口号
if(set_address(hname,sname,&peer,(char*)"tcp")!
=0)
return-1;
//创建套接字
ClientSocket=socket(AF_INET,SOCK_STREAM,0);
if(ClientSocket==INVALID_SOCKET)
{
printf("socket函数调用错误,错误号:
%d\n",WSAGetLastError());
clean_up();
return-1;
}
//请求建立连接
iResult=connect(ClientSocket,(structsockaddr*)&peer,sizeof(peer));
if(iResult==SOCKET_ERROR)
{
printf("connect函数调用错误!
错误号:
%d\n",WSAGetLastError());
quit(ClientSocket);
return-1;
}
returnClientSocket;
}
SOCKETCSocketFrame:
:
tcp_client(ULONGuIP,USHORTuPort)
{
intiResult=0;
structsockaddr_inpeer;
SOCKETClientSocket;
//为服务器的地址peer设置用户输入的地址以及端口号
memset(&peer,0,sizeof(peer));
peer.sin_family=AF_INET;
peer.sin_addr.S_un.S_addr=htonl(uIP);
peer.sin_port=htons(uPort);
//创建套接字
ClientSocket=socket(AF_INET,SOCK_STREAM,0);
if(ClientSocket==INVALID_SOCKET)
{
printf("socket函数调用错误,错误号:
%d\n",WSAGetLastError());
clean_up();
return-1;
}
//请求建立连接
iResult=connect(ClientSocket,(structsockaddr*)&peer,sizeof(peer));
if(iResult==SOCKET_ERROR)
{
printf("connect函数调用错误!
错误号:
%d\n",WSAGetLastError());
quit(ClientSocket);
return-1;
}
returnClientSocket;
}
#endif
【实验中出现问题及解决方法】
问题1:
如何获取文件长度
解决:
运用fseek(),ftell(),rewind()进行文件长度的获取。
问题2:
如何发送一个整型数据,主要是文件长度?
解决:
利用sprintf()函数,将数字写到发送区(字符数组)。
问题3:
几个发送字符数组发送后,接收方接收发生干扰的问题?
解决:
利用用一个发送字符数组,其他数组只做辅助使用。
用sprintf()函数,将数组合并。
【思考问题】
为什么有几个发送数组时,发送时没有错误,但是在接收时,会发生干扰?
:
这个问题还在思考,没有得出成熟的答案。
【实验体会】
这次利用定长与变长流式套接字实现了一个相对完整的功能,感觉还是相当不错的,学到了很多具体的东西,像在前面提到过的几个函数的使用。
以及进一步加深了对文件操作使用的理解。
最重要的是对在实际的操作之中,锻炼了发现问题解决问题的能力。
因为解决的问题比较实际,在网络上的资料搜集中,有很多解决问题的方法,在实验的过程中,不断地去尝试,行不通,再去换解决方案(如果看我的原始代码的话,会有比较明显的体现,我把那些行不通的方案都注释掉了,都可以看见!
)。
在这之中也学到了很多的知识。
成绩
优
良
中
及格
不及格
教师签名:
日期:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 利用 套接 实现 文件 传输