網上與UDT相關的資料不多,與UDT相關的源碼例子更少。最近在接觸UDT,也是因為缺少相關的資料,導緻學習起來甚感痛苦。下面将我自己這兩天弄出來的代碼貼出來,希望對在尋找相關資料的童鞋有一定的幫助。與服務端相對應的用戶端在另一篇博文中
#include <iostream>
#include "udt.h"
#include <io.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define MAXLEN 4096
int main(int argc,char *argv[])
{
if ((argc != 4))
{
cout<<"Use: appserver.exe server_port client_ip client_port"<<endl;
return 0;
}
//startup
//這裡是對UDT的啟動記性初始化操作
if (UDT::ERROR == UDT::startup())
cout<<"startup: "<<UDT::getlasterror().getErrorMessage()<<endl;
}else{
cout<<"startup suc..."<<endl;
//socket
//像聲明一個普通的socket一樣聲明一個UDTSOCKET
UDTSOCKET serv = UDT::socket(AF_INET, SOCK_DGRAM, 0);
if (UDT::ERROR == serv)
{
cout<<"socket: "<<UDT::getlasterror().getErrorMessage()<<endl;
}else{
cout<<"client suc..."<<endl;
}
//聲明udp socket,這裡是udp的哈,不是udt
int sersocket = socket(AF_INET,SOCK_DGRAM,0);
if (SOCKET_ERROR == sersocket)
cout<<"udp socket error!"<<endl;
cout<<"clientsocket suc..."<<endl;
//為了能夠在區域網路中直接進行處理,先預設設定兩個
sockaddr_in my_addr,client_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(atoi(argv[1]));
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), '\0', 8);
bind(sersocket,(struct sockaddr*)&my_addr,sizeof(my_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(atoi(argv[3]));
client_addr.sin_addr.s_addr = inet_addr(argv[2]);
//client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(&(client_addr.sin_zero), '\0', 8);
int mss = 1052;//最大傳輸機關
//設定收發緩沖區大小 接收限時 和位址重用
if( !( UDT::ERROR != (UDT::setsockopt(serv, 0, UDT_SNDBUF, new int(32000), sizeof(int)))
&& UDT::ERROR != (UDT::setsockopt(serv, 0, UDP_RCVBUF, new int(32000), sizeof(int)))
&& UDT::ERROR != (UDT::setsockopt(serv,0,UDT_REUSEADDR,new int(1),sizeof(int)))
&& UDT::ERROR != (UDT::setsockopt(serv, 0, UDT_RENDEZVOUS, new bool(true), sizeof(bool))))
&& UDT::ERROR != (UDT::setsockopt(serv, 0, UDT_MSS, &mss, sizeof(int)) ))
cout<<"udt socket: "<<UDT::getlasterror().getErrorMessage()<<endl;
UDT::close(serv);
//這裡是直接将udp的接口綁定在udt的接口之上,如果不這樣做的話是沒法使用UDT中的SOCK_DGRAM的
if (UDT::ERROR == UDT::bind2(serv,sersocket))
cout<<"udt bind2:"<<UDT::getlasterror().getErrorMessage()<<endl;
cout<<"bind2 suc"<<endl;
//這裡也是關鍵部分,與client端對應的connect操作,就是互相之間的打洞處理
if (UDT::ERROR == UDT::connect(serv, (sockaddr*)&client_addr, sizeof(client_addr)))
cout << "connect: " << UDT::getlasterror().getErrorMessage();
UDT::close(serv);
return 0;
cout<<"connetc suc"<<endl;
//這裡已經可以正常接收了,接收從client發過來的filename,目的是用于本地的檔案建立
char filename[100];
if (UDT::ERROR == UDT::recvmsg(serv, filename, 100))
cout << "recv:" << UDT::getlasterror().getErrorMessage() << endl;
cout <<"filename: "<< filename <<endl;
//使用FILE進行檔案操作,關于檔案的相關操作這裡不詳述了,實在不懂的可以留言
FILE *fp;
char localfile[100];
memset(localfile,0,sizeof(localfile));
strcpy(localfile,"d:\\");
strcat(localfile,filename);
if((fp = fopen(localfile,"w+"))==NULL)
cout<<filename<<" open failure!"<<endl;
fclose(fp);
fp = fopen(localfile,"wb");
char data[MAXLEN];
int len=0,package=0,filelen=0;
UDT::TRACEINFO trace;
UDT::perfmon(serv,&trace);
while(1)
//前面部分打開檔案後,這裡就是循環接收檔案并儲存
memset(data,0,sizeof(data));
len = UDT::recvmsg(serv, data, MAXLEN);
filelen += len;
//cout<<"filelen = "<<filelen<<endl;
if (strncmp("quit",data,4)==0)
{
cout<<data<<endl;
fclose(fp);
break;
}else
package ++;//record recv all the packages
}
fwrite(data,len,1,fp);
fp = fopen(localfile,"rb");
fseek(fp,0,SEEK_END);//move to the end
filelen = ftell(fp)
fseek(fp,0,SEEK_SET);
cout<<"filesize = "<<filelen<<endl;
UDT::perfmon(serv,&trace);
cout << "speed = " << trace.mbpsRecvRate << "Mbits/sec" << endl;
cout<<"recv all the packages: "<<package<<endl;
UDT::close(serv);
UDT::cleanup();
return 1;
}
運作效果截圖:
簡單截圖如下: