【基于udp文件传输实验报告】udp实验结果及分析

 实验报告

 课程名称

 课程名称 《数据库技术》

 学生姓名 ***

 学 号 ********

 专业班级 电子信息工程

 指导教师

 

  成  绩      

       

 2015年6月 8 日

 实验名称:     基于UDP的文件传输

 1.实验目的熟练掌握Socket编程;

 分析UDP与TCP的异同。

 2.实验设备和条件

 硬件环境:PC机

 操作系统: Windows 或者 Linux

 语言环境: Visual C++ ,VS,GCC,Java均可

 3.实验要求

 参考TCP文件传输demo, 基于UDP实现send.mp3文件的传输,并测试接收到的文件与发送的文件是否一致。

 请各位同学于第15周星期三或星期四上课时将纸质版(双面打印)上交!

 4.实验内容:测试数据与实验结果(可以抓图粘贴)

 (1)发送端代码。

 #include "stdafx.h"

 #include <Winsock2.h>

 #include <stdio.h>

 #define MAX_LENGTH 1024

 int _tmain(int argc, _TCHAR* argv[])

 {

 ?WORD wVersionRequested;

  WSADATA wsaData;

 ?wVersionRequested = MAKEWORD(2, 2);

 ?if (WSAStartup(wVersionRequested, &wsaData)!= 0)//初始化ws2_32.dll动态库

  {

  ?printf("WSAStartup() failed!\n");//Winsock初始化错误

 exit(-1);

 ?}

 ?if (wsaData.wVersion != wVersionRequested)

 ?{

  printf("The version of Winsock is not suited!\n");//Winsock版本不匹配

  ?WSACleanup();//结束对ws2_32.dll的调用

  ?exit(-2);

  }

 ?//说明ws2_32.dll正确加载

  printf("Load ws2_32.dll successfully!\n");

  //创建套接字

 ?SOCKET servsock;

 ?printf("Create Socket...\n");

 ?servsock = socket(AF_INET, SOCK_DGRAM, 0);//数据报套接字

  int servport = 5555;

 ?int iSockErr = 0;

  //定义服务器地址结构

 ?sockaddr_in udpaddr;

  int len = sizeof(udpaddr);

  memset(&udpaddr, 0, sizeof(udpaddr));

 ?udpaddr.sin_family = AF_INET;

  udpaddr.sin_port = htons(servport);

 ?//将一个点分十进制IP地址字符串转换成32位数字表示的IP地址

  udpaddr.sin_addr.s_addr = inet_addr("172.16.4.94");////INADDR_ANY

 ?//读取mp3文件

  FILE *fp = NULL;

 ?errno_t err;

  err = fopen_s(&fp, "七里香.mp3", "rb");

  if (fp == NULL){

 printf("Open !\n");

  getchar();

  ?exit(-5);

 ?}

  char buffer[MAX_LENGTH] = "\0";

  char *bufptr = buffer;

 ?int i = 0;

  while (!feof(fp))

 ?{

  ?int iBytesRead = fread(bufptr, 1, MAX_LENGTH, fp);

  int iRet = sendto(servsock, buffer, sizeof(buffer), 0, (struct sockaddr*)&udpaddr, len);

 if (iRet != SOCKET_ERROR)

 ? {

 ? ?iRet = recvfrom(servsock, buffer, sizeof(buffer), 0, (struct sockaddr*)&udpaddr, &len);

 }

  else

  ?{

  printf("send!\n");

  break;

  }

 if (iRet == SOCKET_ERROR)

  ?{

 ? //closesocket(clisock);

 ? printf("send !\n");

  ? break;

  }

  else if (iRet == 0)

 ? {

  printf("send mp3!\n");

  break;

 ? }

  if (iBytesRead == 0)

 ? {

  ? printf("send mp3 !\n");

 ? ?break;

  }

 ? //printf("%d", &len);

  ?printf("send packet %d lenth: %d\n", i++, iBytesRead);

 ? Sleep(10);

  }

  sendto(servsock, "", 0, 0, (struct sockaddr*)&udpaddr, len);

  //关闭

 ?shutdown(servsock, 2);

  closesocket(servsock);

 ?WSACleanup();

 ?getchar();

 ?return 0;

 }

 (2)接收端代码。

 #include "stdafx.h"

 #include <Winsock2.h>

 #include <stdio.h>

 #define MAX_LENGTH 1024*10

 int _tmain(int argc, _TCHAR* argv[])

 {

 ?WORD wVersionRequested;

 ?WSADATA wsaData;

 ?wVersionRequested = MAKEWORD(2, 2);

  if (WSAStartup(wVersionRequested, &wsaData) != 0)//初始化ws2_32.dll动态库

  {

 ? printf("WSAStartup() failed!\n");//Winsock初始化错误

  exit(-1);

  }

  if (wsaData.wVersion!= wVersionRequested)

  {

  ?printf("The version of Winsock is not suited!\n");//Winsock版本不匹配

 ? WSACleanup();//结束对ws2_32.dll的调用

  ?exit(-2);

 ?}

  //说明ws2_32.dll正确加载

 ?printf("Load ws2_32.dll successfully!\n");

  //获取本机IP地址

 ?char PCname[100] = { "" };

  char *IPaddress = NULL;

 ?gethostname(PCname, sizeof(PCname));

  printf("Local Hostname is %s.\n", PCname);

 ?struct hostent FAR * lpHostEnt = gethostbyname(PCname);

 ?if (lpHostEnt == NULL)

  {

 //产生错误

 ? printf("gethostbyname failed!\n");

  return -1;

  }

 ?//获取IP

 ?LPSTR lpAddr = lpHostEnt->h_addr_list[0];

  if (lpAddr)

 ?{

 struct in_addr inAddr;

  memmove(&inAddr, lpAddr, 4);

 //转换为标准格式

  IPaddress = inet_ntoa(inAddr);//将一个32位数字表示的IP地址转换成点分十进制IP地址字符串

  ?if (sizeof(IPaddress) == 0)

  ? printf("get host IP failed!\n");

 ? else

  ?printf("Local HostIP is %s.\n", IPaddress);

  }

  //创建套接字

 ?//SOCKET servsock, clisock;

  SOCKET servsock;

 ?printf("Create Socket...\n");

  servsock = socket(AF_INET, SOCK_DGRAM, 0);//数据报套接字

 ?int servport = 5555;

 ?int iSockErr = 0;

  //定义服务器地址结构

  sockaddr_in udpaddr, cliaddr;

  memset(&udpaddr, 0, sizeof(udpaddr));

  memset(&cliaddr, 0, sizeof(cliaddr));

 ?int clilen = sizeof(cliaddr);

  udpaddr.sin_family = AF_INET;

  udpaddr.sin_port = htons(servport);

  //将一个点分十进制IP地址字符串转换成32位数字表示的IP地址

  udpaddr.sin_addr.s_addr = inet_addr(IPaddress);//"127.0.0.1"//INADDR_ANY

 ?//绑定套接字到服务器地址结构

  printf("Binding...\n");

  iSockErr = bind(servsock, (sockaddr *)&udpaddr, sizeof(udpaddr));

  if (iSockErr == SOCKET_ERROR)

 ?{

 ? printf("Binding failed:%d\n", WSAGetLastError());//根据不同的错误类型进行不同的处理

  ?exit(-3);

  }

  //函数调用成功,进行其他处理

  char buff[256] = "\0";

  char buffer[MAX_LENGTH] = "\0";

  int len = 0;

 ?//接收欢迎词

 ?memset(buffer, 0, sizeof(buffer));

 ?FILE *fp = NULL;

 ?errno_t err;

  err = fopen_s(&fp, "七里香.mp3", "wb");

  int i = 0;

  while (1)

 ?{

 len = recvfrom(servsock, buffer, sizeof(buffer), 0, (struct sockaddr*)&cliaddr, &clilen);

  if (len == SOCKET_ERROR) {

  printf("recv error!\n");

  break;

  }

  ?else if (len == 0)

  {

  printf("recv finished!\n");

 ? break;

 }

  buffer[len] = 0;

 printf("received packet %d lenth: %d\n\n", i++, len);

 ? fwrite(buffer, 1, len, fp);

  ?sendto(servsock, buff, sizeof(buff), 0, (struct sockaddr*)&cliaddr, clilen);

 ? Sleep(8);

 ? //printf("%d\n",&len);

 ?}

  fclose(fp);

 ?//shutdown(clisock, 2);

 ?//?closesocket(clisock);

  shutdown(servsock, 2);

 ?closesocket(servsock);

 ?WSACleanup();

 ?getchar();

  return 0;

 }

 (3)简单的代码移植后接收端是否能正确接收?如果不能请分析原因,并尝试调整发送端读取数据的大小和延迟时间,以及接收端缓冲区的大小来解决数据丢包问题。给出参数调整的理由。

 答: 简单的代码移植可能不能正确接受,因为会出现丢包现象。丢包现象在UDP中是很常见的现象。在UDP文件传输中,文件将从client 端发向server端。与TCP不同的是,UDP不需要链接,可以直接传输,但是稳定性不好,容易丢包。调整client端中Sleep(10)的大小来解决这个问题,使client的延迟时间大于server的延迟时间,例如server的sleep(8)。

推荐访问:文件传输 实验 报告 udp