1、利用流式套接字实现文件的传输网络编程技术实验报告实验名称实验四 利用流式套接字传输文件实验队 别姓 名学 号实验日期2015.12.11实验报告要求: 1.实验目的 2.实验要求 3.实验环境 4.实验作业 5.问题及解决 6.思考问题 7.实验体会【实验目的】1.掌握定长与变长流式套接字的使用方法2.加深对流式套接字的掌握3.掌握一些解决实际问题的能力【实验要求】客户端向服务器发起socket连接,并建立数据传输通道客户端向服务器发送要传输的文件名称,以#字符结尾,服务器逐字接收,直到接收到#(变长数据)客户端向服务器发送文件长度,4字节(定长数据)客户端向服务器文件内容(变长数据)服务端接
2、收完文件后,向客户端发送ok,以示成功接收客户端接收到OK后,关闭套接字服务器关闭套接字【实验环境】Dev c【实验作业】客户端:int tcp_client_fun_echo(FILE *fp,SOCKET s) int iResult; char sendlineMAXLINE,recvlineMAXLINE; char file20; char flong4; int i=0;/文件名发送控制 /初始化缓冲区 FILE *f;/写文件指针 char *buff;/读入文件内容 uint32_t nFileLen;/文件长度 printf(请输入文件名:n); scanf(%s,&file
3、); 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); return 0; memset(sendline,0,MAXLINE); memset(recvline,0,MAXLINE); while(i!=nFile
4、Len) recvlinei=*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); return iResult;服务器:int tcp_server_fun_echo(SOCKET s)
5、FILE *fp; int i=0; char flong4; int iResult = 0; uint32_t nFileLen=1; char recvlineMAXLINE; char file10; memset(file,0,sizeof(file); memset(recvline,0,sizeof(recvline); for(;) iResult=recv(s,&filei,1,0); if(iResult=SOCKET_ERROR) printf(recv函数调用错误,错误号:%d,WSAGetLastError(); return -1; if(filei=#) brea
6、k; else i+; filei=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,WS
7、AGetLastError(); return -1; fputs(recvline,fp); fclose(fp); printf(文件接收成功!n); return iResult;头文件(上次的实验报告中已经写过):#ifndef p_h/预处理指令,防止重复包含头文件 #include#include#include#include#include#pragma coment(lib,ws2_32.lib) using namespace std;class CSocketFrame public: int start_up(); int clean_up(); int set_add
8、ress(char *hname,char *sname,struct sockaddr_in *sap,char *protocol); int quit(SOCKET s); SOCKET tcp_server(ULONG uIP,USHORT uPort); SOCKET tcp_server(char *hname,char *sname); SOCKET tcp_client(char *hname,char *sname); SOCKET tcp_client(ULONG uIP,USHORT uPort);int CSocketFrame:start_up(void) WORD
9、wVersionRequested; WSADATA wsaData; int iResult; wVersionRequested=MAKEWORD(2,2); iResult=WSAStartup(wVersionRequested,&wsaData); if(iResult!=0) printf(WSAStartup 调用错误,错误号:%dn,WSAGetLastError(); return -1; /* if(LOBYTE(wsaData.wVersion!=2|HIBYTE(wsaData.wVersion)!=2) printf(无法找到可用的WSD版本n); WSACleanu
10、p(); return -1; /告诉用户无法找到可用的WSD else printf(WS2.2初始化成功!n); */ return 0;int CSocketFrame:clean_up(void) int iResult; iResult=WSACleanup(); if(iResult=SOCKET_ERROR) /WSACleanup()调用失败 printf(WSACleanup 调用错误,错误号:%dn,WSAGetLastError(); return -1; else printf(Winsocket dll释放成功!n) ; return 0;int CSocketFra
11、me:set_address(char *hname,char *sname,struct sockaddr_in *sap,char *protocol) struct servent *sp; struct hostent *hp; char *endptr; unsigned short port; unsigned long ulAddr=INADDR_NONE; /将地址结构socketsddr_in初始化为0,并将地址族设为AF_INET memset(sap,0,sizeof(*sap); sap-sin_family=AF_INET; if(hname!=NULL) /如果hn
12、ame不为空,转化地址格式 ulAddr=inet_addr(hname); if(ulAddr=INADDR_NONE|ulAddr=INADDR_ANY) /调用错误,调用gethostbyname获得主机地址 hp=gethostbyname(hname); if(hp=NULL) printf(未知的主机名,错误号:%dn,WSAGetLastError(); return -1; sap-sin_addr=*(struct in_addr *)hp-h_addr; else sap-sin_addr.S_un.S_addr=ulAddr; else /如果调用者没有指明一个主机名或地
13、址,则设为通配地址 sap-sin_addr.s_addr=htonl(INADDR_ANY); /尝试转换sname为一个整数 port=(unsigned short)strtol(sname,&endptr,0); if(*endptr=0) /如果成功转化为网络字节序 sap-sin_port=htons(port); else /如果失败,则假定是一个服务名称,通过getservbyname()函数获得端口号 sp=getservbyname(sname,protocol); if(sp=NULL) printf(未知服务,错误号:%dn,WSAGetLastError(); ret
14、urn -1; sap-sin_port=sp-s_port; return 0;int CSocketFrame:quit(SOCKET s) int iResult=0; iResult=closesocket(s); if(iResult=SOCKET_ERROR) printf(closesocket 调用错误,错误号:%dn,WSAGetLastError(); return -1; iResult=clean_up(); return iResult;SOCKET CSocketFrame:tcp_server(char *hname,char *sname) SOCKET Lis
15、tenSocket; int iResult=0; sockaddr_in local; const int on=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函数调用错误,错误号:%dn,WSAGetLastError(); WSACleanup(); return -1
16、; /绑定服务器地址 iResult=bind(ListenSocket,(struct sockaddr *) & local,sizeof(local); if(iResult=-1) printf(bind函数调用错误!错误号:%dn,WSAGetLastError(); closesocket(ListenSocket); WSACleanup(); return -1; /设置函数为监听状态,监听队列长度为NLISTEN iResult=listen(ListenSocket,SOMAXCONN); if(iResult=SOCKET_ERROR) printf(Listen函数调用
17、错误!错误号:%dn,WSAGetLastError(); quit(ListenSocket); return -1; return ListenSocket;SOCKET CSocketFrame:tcp_server(ULONG uIP,USHORT uPort) SOCKET ListenSocket=INVALID_SOCKET; int iResult=0; sockaddr_in local; const int on=1; /为服务器的本机地址设置用户输入的地址以及端口号 memset(&local,0,sizeof(local); local.sin_family=AF_IN
18、ET; 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函数调用错误,错误号:%dn,WSAGetLastError(); clean_up(); return -1; /绑定服务器地址 iResult=bind(ListenSocket,(struct sockaddr *) & local,sizeof(local); if(i
19、Result=SOCKET_ERROR) printf(bind函数调用错误!错误号:%dn,WSAGetLastError(); quit(ListenSocket); return -1; /设置函数为监听状态,监听队列长度为NLISTEN iResult=listen(ListenSocket,SOMAXCONN); if(iResult=SOCKET_ERROR) printf(Listen函数调用错误!错误号:%dn,WSAGetLastError(); quit(ListenSocket); return -1; return ListenSocket;SOCKET CSocket
20、Frame:tcp_client(char *hname,char *sname) int iResult=0; struct sockaddr_in peer; SOCKET ClientSocket; /为服务器的地址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
21、n,WSAGetLastError(); clean_up(); return -1; /请求建立连接 iResult=connect(ClientSocket,(struct sockaddr *) & peer,sizeof(peer); if(iResult=SOCKET_ERROR) printf(connect函数调用错误!错误号:%dn,WSAGetLastError(); quit(ClientSocket); return -1; return ClientSocket;SOCKET CSocketFrame:tcp_client(ULONG uIP,USHORT uPort)
22、 int iResult=0; struct sockaddr_in peer; SOCKET ClientSocket; /为服务器的地址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(s
23、ocket函数调用错误,错误号:%dn,WSAGetLastError(); clean_up(); return -1; /请求建立连接 iResult=connect(ClientSocket,(struct sockaddr *) & peer,sizeof(peer); if(iResult=SOCKET_ERROR) printf(connect函数调用错误!错误号:%dn,WSAGetLastError(); quit(ClientSocket); return -1; return ClientSocket;#endif【实验中出现问题及解决方法】问题1:如何获取文件长度解决:运
24、用fseek(),ftell(),rewind()进行文件长度的获取。问题2:如何发送一个整型数据,主要是文件长度?解决:利用sprintf()函数,将数字写到发送区(字符数组)。问题3:几个发送字符数组发送后,接收方接收发生干扰的问题?解决:利用用一个发送字符数组,其他数组只做辅助使用。用sprintf()函数,将数组合并。【思考问题】为什么有几个发送数组时,发送时没有错误,但是在接收时,会发生干扰?:这个问题还在思考,没有得出成熟的答案。【实验体会】这次利用定长与变长流式套接字实现了一个相对完整的功能,感觉还是相当不错的,学到了很多具体的东西,像在前面提到过的几个函数的使用。以及进一步加深了对文件操作使用的理解。最重要的是对在实际的操作之中,锻炼了发现问题解决问题的能力。因为解决的问题比较实际,在网络上的资料搜集中,有很多解决问题的方法,在实验的过程中,不断地去尝试,行不通,再去换解决方案(如果看我的原始代码的话,会有比较明显的体现,我把那些行不通的方案都注释掉了,都可以看见!)。在这之中也学到了很多的知识。成绩优良中及格不及格教师签名: 日期:
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1