利用流式套接字实现文件的传输.docx

上传人:b****6 文档编号:8443423 上传时间:2023-01-31 格式:DOCX 页数:15 大小:18.67KB
下载 相关 举报
利用流式套接字实现文件的传输.docx_第1页
第1页 / 共15页
利用流式套接字实现文件的传输.docx_第2页
第2页 / 共15页
利用流式套接字实现文件的传输.docx_第3页
第3页 / 共15页
利用流式套接字实现文件的传输.docx_第4页
第4页 / 共15页
利用流式套接字实现文件的传输.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

利用流式套接字实现文件的传输.docx

《利用流式套接字实现文件的传输.docx》由会员分享,可在线阅读,更多相关《利用流式套接字实现文件的传输.docx(15页珍藏版)》请在冰豆网上搜索。

利用流式套接字实现文件的传输.docx

利用流式套接字实现文件的传输

网络编程技术实验报告

实验名称

实验四利用流式套接字传输文件实验

队别

姓名

学号

实验日期

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()函数,将数组合并。

【思考问题】

为什么有几个发送数组时,发送时没有错误,但是在接收时,会发生干扰?

这个问题还在思考,没有得出成熟的答案。

【实验体会】

这次利用定长与变长流式套接字实现了一个相对完整的功能,感觉还是相当不错的,学到了很多具体的东西,像在前面提到过的几个函数的使用。

以及进一步加深了对文件操作使用的理解。

最重要的是对在实际的操作之中,锻炼了发现问题解决问题的能力。

因为解决的问题比较实际,在网络上的资料搜集中,有很多解决问题的方法,在实验的过程中,不断地去尝试,行不通,再去换解决方案(如果看我的原始代码的话,会有比较明显的体现,我把那些行不通的方案都注释掉了,都可以看见!

)。

在这之中也学到了很多的知识。

成绩

及格

不及格

教师签名:

日期:

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1