基于UDT connect连接通信以及文件传输

转自:http://blog.csdn.net/pingd/article/details/16341467


SERVER端

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include "udt.h"  
  3. #include <io.h>  
  4.   
  5. #pragma comment(lib,"ws2_32.lib")  
  6.   
  7. using namespace std;  
  8.   
  9. #define MAXLEN 4096  
  10.   
  11. int main(int argc,char *argv[])  
  12.  {     
  13.      if ((argc != 4))  
  14.      {  
  15.         cout<<"Use: appserver.exe server_port client_ip client_port"<<endl;  
  16.         return 0;  
  17.      }  
  18.   
  19.      //startup  
  20.     //这里是对UDT的启动记性初始化操作  
  21.      if (UDT::ERROR == UDT::startup())  
  22.      {  
  23.          cout<<"startup: "<<UDT::getlasterror().getErrorMessage()<<endl;  
  24.      }else{  
  25.         cout<<"startup suc..."<<endl;  
  26.      }  
  27.   
  28.      //socket  
  29.     //像声明一个普通的socket一样声明一个UDTSOCKET  
  30.      UDTSOCKET serv = UDT::socket(AF_INET, SOCK_DGRAM, 0);  
  31.      if (UDT::ERROR == serv)  
  32.     {  
  33.         cout<<"socket: "<<UDT::getlasterror().getErrorMessage()<<endl;  
  34.     }else{  
  35.         cout<<"client suc..."<<endl;  
  36.     }  
  37.   
  38.      //声明udp socket,这里是udp的哈,不是udt  
  39.      int sersocket = socket(AF_INET,SOCK_DGRAM,0);  
  40.      if (SOCKET_ERROR == sersocket)  
  41.     {  
  42.         cout<<"udp socket error!"<<endl;  
  43.     }else{  
  44.         cout<<"clientsocket suc..."<<endl;  
  45.     }  
  46.   
  47.     //为了能够在局域网中直接进行处理,先默认设置两个  
  48.      sockaddr_in my_addr,client_addr;  
  49.      my_addr.sin_family = AF_INET;  
  50.      my_addr.sin_port = htons(atoi(argv[1]));  
  51.      my_addr.sin_addr.s_addr = INADDR_ANY;  
  52.      memset(&(my_addr.sin_zero), '\0', 8);  
  53.      bind(sersocket,(struct sockaddr*)&my_addr,sizeof(my_addr));  
  54.   
  55.      client_addr.sin_family = AF_INET;  
  56.      client_addr.sin_port = htons(atoi(argv[3]));  
  57.      client_addr.sin_addr.s_addr = inet_addr(argv[2]);  
  58.      //client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  
  59.      memset(&(client_addr.sin_zero), '\0', 8);  
  60.   
  61.      int mss = 1052;//最大传输单位  
  62.      //设置收发缓冲区大小 接收限时  和地址重用  
  63.     if(   !( UDT::ERROR != (UDT::setsockopt(serv, 0, UDT_SNDBUF, new int(32000), sizeof(int)))  
  64.         && UDT::ERROR != (UDT::setsockopt(serv, 0, UDP_RCVBUF, new int(32000), sizeof(int)))  
  65.         && UDT::ERROR != (UDT::setsockopt(serv,0,UDT_REUSEADDR,new int(1),sizeof(int)))  
  66.         && UDT::ERROR != (UDT::setsockopt(serv, 0, UDT_RENDEZVOUS, new bool(true), sizeof(bool))))  
  67.         && UDT::ERROR != (UDT::setsockopt(serv, 0, UDT_MSS, &mss, sizeof(int)) ))  
  68.     {  
  69.         cout<<"udt socket: "<<UDT::getlasterror().getErrorMessage()<<endl;  
  70.         UDT::close(serv);  
  71.         return 0;  
  72.     }  
  73.     //这里是直接将udp的接口绑定在udt的接口之上,如果不这样做的话是没法使用UDT中的SOCK_DGRAM的  
  74.      if (UDT::ERROR == UDT::bind2(serv,sersocket))  
  75.      {  
  76.         cout<<"udt bind2:"<<UDT::getlasterror().getErrorMessage()<<endl;  
  77.         return 0;  
  78.      }else{  
  79.         cout<<"bind2 suc"<<endl;  
  80.      }  
  81.     //这里也是关键部分,与client端对应的connect操作,就是相互之间的打洞处理  
  82.      if (UDT::ERROR == UDT::connect(serv, (sockaddr*)&client_addr, sizeof(client_addr)))  
  83.      {  
  84.        cout << "connect: " << UDT::getlasterror().getErrorMessage();  
  85.        UDT::close(serv);  
  86.        return 0;  
  87.      }else{  
  88.         cout<<"connetc suc"<<endl;  
  89.      }  
  90.     //这里已经可以正常接收了,接收从client发过来的filename,目的是用于本地的文件创建  
  91.      char filename[100];  
  92.      if (UDT::ERROR == UDT::recvmsg(serv, filename, 100))  
  93.      {  
  94.        cout << "recv:" << UDT::getlasterror().getErrorMessage() << endl;  
  95.        return 0;  
  96.      }  
  97.      cout <<"filename: "<< filename <<endl;  
  98.   
  99.     //使用FILE进行文件操作,关于文件的相关操作这里不详述了,实在不懂的可以留言  
  100.      FILE *fp;  
  101.      char localfile[100];  
  102.      memset(localfile,0,sizeof(localfile));  
  103.      strcpy(localfile,"d:\\");  
  104.      strcat(localfile,filename);  
  105.      if((fp = fopen(localfile,"w+"))==NULL)  
  106.      {  
  107.         cout<<filename<<" open failure!"<<endl;  
  108.         return 0;  
  109.      }  
  110.      fclose(fp);  
  111.      fp = fopen(localfile,"wb");  
  112.   
  113.      char data[MAXLEN];  
  114.      int len=0,package=0,filelen=0;  
  115.      UDT::TRACEINFO trace;  
  116.      UDT::perfmon(serv,&trace);    
  117.      while(1)  
  118.      {  
  119.         //前面部分打开文件后,这里就是循环接收文件并保存  
  120.         memset(data,0,sizeof(data));  
  121.         len = UDT::recvmsg(serv, data, MAXLEN);  
  122.         filelen += len;  
  123.         //cout<<"filelen = "<<filelen<<endl;  
  124.         if (strncmp("quit",data,4)==0)  
  125.         {  
  126.             cout<<data<<endl;  
  127.             fclose(fp);  
  128.             break;  
  129.         }else  
  130.         {  
  131.             package ++;//record recv all the packages  
  132.         }  
  133.         fwrite(data,len,1,fp);        
  134.      }  
  135.      fclose(fp);  
  136.      fp = fopen(localfile,"rb");  
  137.      fseek(fp,0,SEEK_END);//move to the end  
  138.      filelen = ftell(fp)  
  139.      fseek(fp,0,SEEK_SET);  
  140.      cout<<"filesize = "<<filelen<<endl;  
  141.      UDT::perfmon(serv,&trace);  
  142.      cout << "speed = " << trace.mbpsRecvRate << "Mbits/sec" << endl;  
  143.      cout<<"recv all the packages: "<<package<<endl;  
  144.   
  145.      fclose(fp);  
  146.      UDT::close(serv);  
  147.      UDT::cleanup();  
  148.   
  149.      return 1;  
  150.  }   

上面一篇文章中提出了服务端的,其实这里没有严格意义的服务端和客户端之分,因为我在代码中是基于UDP的,不存在服务端与客户端,两个都是对等的,只是我这里进行一下简单的区分而已。在这里,客户端所进行的主要操作就是首先给服务端发送文件名,然后将文件直接通过fopen(),fread()等一系列的操作将文件发送过去。

        与客户端相对应的源码在另一篇博文中:http://blog.csdn.net/pingd/article/details/16341467

        CLIENT端

[cpp]  view plain copy
  1. #include <iostream>  
  2. #include "udt.h"  
  3. #include <io.h>  
  4.   
  5. #pragma comment(lib,"ws2_32.lib")  
  6.   
  7. using namespace std;  
  8.   
  9. #define MAXLEN 4096  
  10.   
  11. int main(int argc,char *argv[])  
  12.  {  
  13.      if ((argc != 5))  
  14.      {  
  15.         cout<<"Usage: appclient.exe client_port server_ip server_port local_filename"<<endl;  
  16.         return 0;  
  17.      }  
  18.   
  19.      //startup  
  20.      if (UDT::ERROR == UDT::startup())  
  21.      {  
  22.         cout<<"startup: "<<UDT::getlasterror().getErrorMessage()<<endl;  
  23.      }else{  
  24.         cout<<"startup suc..."<<endl;  
  25.      }  
  26.   
  27.      //Initialize the UDT library  
  28.     UDTSOCKET client = UDT::socket(AF_INET, SOCK_DGRAM, 0);  
  29.     if (UDT::ERROR == client)  
  30.     {  
  31.         cout<<"socket: "<<UDT::getlasterror().getErrorMessage()<<endl;  
  32.     }else{  
  33.         cout<<"client suc..."<<endl;  
  34.     }  
  35.   
  36.     //声明udp socket  
  37.     int clientsocket = socket(AF_INET,SOCK_DGRAM,0);  
  38.     if (SOCKET_ERROR == clientsocket)  
  39.     {  
  40.         cout<<"udp socket error!"<<endl;  
  41.     }else{  
  42.         cout<<"clientsocket suc..."<<endl;  
  43.     }  
  44.   
  45.      sockaddr_in serv_addr,my_addr;  
  46.      serv_addr.sin_family = AF_INET;  
  47.      serv_addr.sin_port = htons(atoi(argv[3]));  
  48.      serv_addr.sin_addr.s_addr = inet_addr(argv[2]);  
  49.      memset(&(serv_addr.sin_zero), '\0', 8);  
  50.   
  51.      my_addr.sin_family = AF_INET;  
  52.      my_addr.sin_port = htons(atoi(argv[1]));  
  53.      my_addr.sin_addr.s_addr = INADDR_ANY;  
  54.      memset(&(my_addr.sin_zero), '\0', 8);  
  55.      bind(clientsocket,(struct sockaddr*)&my_addr,sizeof(my_addr));  
  56.   
  57.      int mss = 1052;//最大传输单位  
  58.      //设置收发缓冲区大小 接收限时  和地址重用  
  59.     if(   !( UDT::ERROR != (UDT::setsockopt(client, 0, UDT_SNDBUF, new int(32000), sizeof(int)))  
  60.         && UDT::ERROR != (UDT::setsockopt(client, 0, UDP_RCVBUF, new int(32000), sizeof(int)))  
  61.         && UDT::ERROR != (UDT::setsockopt(client,0,UDT_REUSEADDR,new int(1),sizeof(int)))  
  62.         && UDT::ERROR != (UDT::setsockopt(client, 0, UDT_RENDEZVOUS, new bool(true), sizeof(bool))))  
  63.         && UDT::ERROR != (UDT::setsockopt(client, 0, UDT_MSS, &mss, sizeof(int))))  
  64.     {  
  65.         cout<<"udt socket: "<<UDT::getlasterror().getErrorMessage()<<endl;  
  66.         UDT::close(client);  
  67.         return 0;  
  68.     }  
  69.   
  70.      if (UDT::ERROR == UDT::bind2(client,clientsocket))  
  71.      {  
  72.         cout<<"udt bind2:"<<UDT::getlasterror().getErrorMessage()<<endl;  
  73.         return 0;  
  74.      }else{  
  75.         cout<<"bind2 suc"<<endl;  
  76.      }  
  77.        
  78.      // connect to the server, implict bind  
  79.      if (UDT::ERROR == UDT::connect(client, (sockaddr*)&serv_addr, sizeof(serv_addr)))  
  80.      {  
  81.        cout << "connect: " << UDT::getlasterror().getErrorMessage();  
  82.        UDT::close(client);  
  83.        return 0;  
  84.      }else{  
  85.         cout<<"connect suc"<<endl;  
  86.      }  
  87.   
  88.      char* hello = argv[4];  
  89.      if (UDT::ERROR == UDT::sendmsg(client, hello, strlen(hello) + 1,-1,true))  
  90.      {  
  91.        cout << "send: " << UDT::getlasterror().getErrorMessage();  
  92.        return 0;  
  93.      }  
  94.   
  95.      FILE *fp;  
  96.      fp = fopen(hello,"rb");  
  97.      fseek(fp,0,SEEK_END);  
  98.      int filesize = ftell(fp);  
  99.      //rewind(fp);//移动到头部  
  100.      fseek(fp,0,SEEK_SET);  
  101.      static int filepos = 0;//记录文件偏移量  
  102.      cout<<"filesize = "<<filesize<<endl;  
  103.   
  104.      char data[MAXLEN+1];  
  105.      int len=0,package=0;  
  106.      UDT::TRACEINFO trace;  
  107.      UDT::perfmon(client,&trace);  
  108.      while(1)  
  109.      {  
  110.         memset(data,0,sizeof(data));  
  111.         fread(data,MAXLEN,1,fp);  
  112.         if(filesize>=MAXLEN)  
  113.         {  
  114.             len = UDT::sendmsg(client,data,MAXLEN,-1,true);  
  115.             if (len<0)  
  116.             {  
  117.                 cout<<"send failure!!\n"<<endl;  
  118.                 break;  
  119.             }  
  120.             filesize -= MAXLEN;  
  121.             package ++;//record send all the packages  
  122.         }else  
  123.         {  
  124.             len = UDT::sendmsg(client,data,filesize,-1,true);  
  125.             if (len<0)  
  126.             {  
  127.                 cout<<"send failure!!\n"<<endl;  
  128.                 break;  
  129.             }  
  130.             package ++;//record recv all the packages  
  131.             char *quit = "quit";  
  132.             if (UDT::ERROR == UDT::sendmsg(client,quit,strlen(quit)+1,-1,true))  
  133.             {  
  134.                 cout<<"send quit error"<<endl;  
  135.                 fclose(fp);  
  136.                 break;  
  137.             }  
  138.             break;  
  139.         }  
  140.      }  
  141.      UDT::perfmon(client,&trace);  
  142.      cout << "speed = " << trace.mbpsSendRate << "Mbits/sec" << endl;  
  143.      cout<<"send all the packages: "<<package<<endl;  
  144.   
  145.      fclose(fp);  
  146.      UDT::close(client);  
  147.      UDT::close(clientsocket);  
  148.      UDT::cleanup();  
  149.   
  150.      return 1;  
  151.  }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值