我在使用服务器-客户端 FTP 模拟程序时遇到了一些问题。该程序不断给我“未定义的参考”错误。我在 Windows 上使用 C::B 10.05,并尝试包括 winsock.h、winsock2.h 以及我在互联网上找到的更多解决方案,但没有奏效。这是源代码。非常感谢任何帮助。谢谢。
//Router Head file
#include <winsock.h>
#include <fstream>
#include <iostream>
#include <time.h>
#include <winsock2.h>
#include <list>
#include <stdio.h>
#define MAXBUFSIZE 2048 //maximum packet size
#define MAXHOSTNAMELEN 256 //maximum length of host name
#define ROUTER_PORT1 7000 //router port number 1
#define ROUTER_PORT2 7001 //router port number 2
#define PEER_PORT1 5000 //port number of peer host 1
#define PEER_PORT2 5001 //port number of peer host 2
#define TIMEOUT_USEC 300000 //time-out value
#define TRACE 1
using namespace std ;
struct EVENT_LIST
{
bool empty;
DWORD count; //count is the packet number
short destination; //destination of this packet
int len; //length of this packet
char Buffer[MAXBUFSIZE]; //buffer for packet
};
class Router
{
public:
char localhost[MAXHOSTNAMELEN]; //local host name
Router(char *fn="log.txt");
~Router();
void Run();
private:
ofstream fout;
float damage_rate, delay_rate; //damage rate: dropped and delayed
SOCKET Sock1, Sock2; //sockets used for communcation with peer host 1 and 2
EVENT_LIST FileBuf; //buffer for delayed packets
protected:
SOCKADDR_IN sa_in_peer1; // address structure for peer host 1 address
SOCKADDR_IN sa_in_peer2; // address structure for peer host 2 address
bool IsDamage() const;
bool IsDelayed() const;
void SendProc();
};
//Router.cpp
//////////////////////////////////////////////////////////
//
// Router Constructor
// arguements:
// fn: A string of log file name
//
//////////////////////////////////////////////////////////
Router::Router(char *fn) //Constructor
{
WSADATA wsadata;
HOSTENT* hp;
char peer_name1[MAXHOSTNAMELEN], peer_name2[MAXHOSTNAMELEN];
SOCKADDR_IN sa_in;
FileBuf.empty=true;
try
{
if (WSAStartup(0x0202,&wsadata)!=0)
throw "Error in starting WSAStartup()\n";
}
//Display any needed error response.
catch (char *str) { cerr<<str<<":"<<dec<<WSAGetLastError()<<endl; return;}
//Get Host name
gethostname(localhost,MAXHOSTNAMELEN);
cout<<"Router starting on host:"<<localhost<<endl<<flush;
//Open the log file
fout.open(fn);
try
{
//Create the Udp Sock1
if((Sock1 = socket(AF_INET,SOCK_DGRAM,0))==INVALID_SOCKET)
throw "Create UDP Socket1 failed\n";
//Fill-in UDP Port and Address info.
sa_in.sin_family = AF_INET;
sa_in.sin_port = htons(ROUTER_PORT1);
sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
//Bind the UDP port1
if (bind(Sock1,(LPSOCKADDR)&sa_in,sizeof(sa_in)) == SOCKET_ERROR)
throw "can't bind the socket1";
//Create the Udp Sock2
if((Sock2 = socket(AF_INET,SOCK_DGRAM,0))==INVALID_SOCKET)
throw "Create UDP Socket2 failed\n";
//Fill-in UDP Port and Address info.
sa_in.sin_family = AF_INET;
sa_in.sin_port = htons(ROUTER_PORT2);
sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
//Bind the UDP port2
if (bind(Sock2,(LPSOCKADDR)&sa_in,sizeof(sa_in)) == SOCKET_ERROR)
throw "can't bind the socket2";
cout<<"\nPlease enter the first peer host name:"<<flush; //enter the dropping rate.
cin>>peer_name1;
cout<<"\nPlease enter the second peer host name:"<<flush; //enter the dropping rate.
cin>>peer_name2;
cout<<"\nPlease enter the drop rate:"<<flush; //enter the dropping rate.
cin>>damage_rate;
cout<<"\nPlease enter the delay rate:"<<flush; //enter the dropping rate.
cin>>delay_rate;
//creat peer host1
if((hp=gethostbyname(peer_name1)) == NULL)
throw "get server name failed\n";
memset(&sa_in_peer1,0,sizeof(sa_in_peer1));
memcpy(&sa_in_peer1.sin_addr,hp->h_addr,hp->h_length);
sa_in_peer1.sin_family = hp->h_addrtype;
sa_in_peer1.sin_port = htons(PEER_PORT1);
//creat peer host2
if((hp=gethostbyname(peer_name2)) == NULL)
throw "get client name failed\n";
memset(&sa_in_peer2,0,sizeof(sa_in_peer2));
memcpy(&sa_in_peer2.sin_addr,hp->h_addr,hp->h_length);
sa_in_peer2.sin_family = hp->h_addrtype;
sa_in_peer2.sin_port = htons(PEER_PORT2);
if (TRACE)
{
fout<<"Peer host 1: "<<peer_name1<<endl;
fout<<"Peer host 2: "<<peer_name2<<endl;
fout<<"Damage Rate: "<<damage_rate<<endl;
}
}
catch (char *str) {cerr<<str<<":"<<dec<<WSAGetLastError()<<endl; exit(1);}
srand( (unsigned)time( NULL ) );
};
//////////////////////////////////////////////////////////
//
// Router::IsDamage
// The function that generates random damages according to damage rate.
//
//////////////////////////////////////////////////////////
bool Router::IsDamage() const
{
return ( (((float)rand())/RAND_MAX) < ((float)damage_rate/100));
}
//////////////////////////////////////////////////////////
//
// Router::IsDelayed
// The function that generates random delayed according to delay rate.
//
//////////////////////////////////////////////////////////
bool Router::IsDelayed() const
{
return ( (((float)rand())/RAND_MAX) < ((float)delay_rate/100));
};
//////////////////////////////////////////////////////////
//
// Router::Run
// The function receives packets from peer hosts and forwards to destinations.
// It also drops packets and stores delayed packets for future sending.
// It calls SendProc to send delayed packets.
//
//////////////////////////////////////////////////////////
void Router::Run()
{
fd_set readfds;
struct timeval *tp=new timeval;
SOCKADDR from;
int RetVal, fromlen, recvlen, wait_count;
EVENT_LIST temp;
DWORD CurrentTime, count1, count2;
count1=0;
count2=0;
wait_count=0;
tp->tv_sec=0;
tp->tv_usec=TIMEOUT_USEC;
while (1)
{
try
{
FD_ZERO(&readfds);
FD_SET(Sock1,&readfds);
FD_SET(Sock2,&readfds);
fromlen=sizeof(from);
if((RetVal=select(1,&readfds,NULL,NULL,tp))==SOCKET_ERROR) //check for incoming packets.
throw "Timer error!";
else if(RetVal>0) //There are incoming packets.
{
if(!FileBuf.empty) wait_count++;
if(FD_ISSET(Sock1, &readfds)) //incoming packet from peer host 1
{
if((recvlen=recvfrom(Sock1, temp.Buffer, sizeof(temp.Buffer), 0, &from, &fromlen))==SOCKET_ERROR)
throw " Get buffer error!";
if (TRACE)
{
fout<<"Router: Receive packet "<<count1<<" from peer host 1"<<endl;
cout<<"Router: Receive packet "<<count1<<" from peer host 1"<<endl;
}
temp.count=count1;
count1++;
temp.destination=2;
}
else if(FD_ISSET(Sock2, &readfds)) //incoming packet from peer host 2
{
if((recvlen=recvfrom(Sock2, temp.Buffer, sizeof(temp.Buffer), 0, &from, &fromlen))==SOCKET_ERROR)
throw " Get buffer error!";
if (TRACE)
{
fout<<"Router: Receive packet "<<count2<<" from peer host 2"<<endl;
cout<<"Router: Receive packet "<<count2<<" from peer host 2"<<endl;
}
temp.count=count2;
count2++;
temp.destination=1;
}
else continue;
temp.len=recvlen;
CurrentTime=GetTickCount();
if(FileBuf.empty&&IsDelayed()) //if the packet is delayed.
{
FileBuf=temp;
FileBuf.empty=false;
if (TRACE)
{
fout<<"Router: Packet "<<temp.count<<" received from peer host "<<(temp.destination==1?2:1)<<" has been delayed!"<<endl;
cout<<"Router: Packet "<<temp.count<<" received from peer host "<<(temp.destination==1?2:1)<<" has been delayed!"<<endl;
}
}
else if(IsDamage()) //if the packet is dropped: dropping packet by no forwarding the packet.
{
if (TRACE)
{
fout<<"Router: Packet "<<temp.count<<" received from peer host "<<(temp.destination==1?2:1)<<" has been dropped by router!"<<endl;
cout<<"Router: Packet "<<temp.count<<" received from peer host "<<(temp.destination==1?2:1)<<" has been dropped by router!"<<endl;
}
}
else //otherwise, packet is forwarded to destination
{
if(temp.destination==1) //forward packets received from 2 to 1.
{
if(sendto(Sock1, temp.Buffer, temp.len,0,(SOCKADDR*)&sa_in_peer1,sizeof(sa_in_peer1))==SOCKET_ERROR)
throw "Send packet error!";
if (TRACE)
{
fout<<"Router: Send packet "<<temp.count<<" received from peer host "<<(temp.destination==1?2:1) <<" to host "<<temp.destination<<endl;
cout<<"Router: Send packet "<<temp.count<<" received from peer host "<<(temp.destination==1?2:1) <<" to host "<<temp.destination<<endl;
}
if(!FileBuf.empty&&FileBuf.destination==1)
{
wait_count=0;
SendProc();
}
}
else
{ //forward packets received from 1 to 2.
if(sendto(Sock2, temp.Buffer, temp.len,0,(SOCKADDR*)&sa_in_peer2,sizeof(sa_in_peer2))==SOCKET_ERROR)
throw "Send packet error1";
if (TRACE)
{
fout<<"Router: Send packet "<<temp.count<<" received from peer host "<<(temp.destination==1?2:1) <<" to host "<<temp.destination<<endl;
cout<<"Router: Send packet "<<temp.count<<" received from peer host "<<(temp.destination==1?2:1) <<" to host "<<temp.destination<<endl;
}
if(!FileBuf.empty&&FileBuf.destination==2)
{
wait_count=0;
SendProc();
}
}
}
}
else //If there is no incoming packet and there is a delayed packets storing in buffer for 3 cycle times (about 0.9 second), call SendProc to send delayed packet.
{
if(!FileBuf.empty)
{
wait_count++;
if(wait_count>=3)
{
SendProc();
wait_count=0;
}
}
}
} //end of try
catch(char *str) {cerr<<str<<":"<<dec<<WSAGetLastError()<<endl;}
}//end of while
};
//////////////////////////////////////////////////////////
//
// Router::SendProc
// Send delayed packets to the destinations.
//
//////////////////////////////////////////////////////////
void Router::SendProc()
{
try
{
if(FileBuf.destination==1)
{
if(sendto(Sock1, FileBuf.Buffer, FileBuf.len,0,(SOCKADDR*)&sa_in_peer1,sizeof(sa_in_peer1))==SOCKET_ERROR)
throw "Send packet error!";
}
else
{
if(sendto(Sock2, FileBuf.Buffer, FileBuf.len,0,(SOCKADDR*)&sa_in_peer2,sizeof(sa_in_peer2))==SOCKET_ERROR)
throw "Send packet error!";
}
if (TRACE)
{
fout<<"Router: Send delayed packet "<<FileBuf.count<<" received from peer host "<<(FileBuf.destination==1?2:1)<<" to host "<<FileBuf.destination<<endl;
cout<<"Router: Send delayed packet "<<FileBuf.count<<" received from peer host "<<(FileBuf.destination==1?2:1)<<" to host "<<FileBuf.destination<<endl;
}
}
catch(char *str){cerr<<str<<":"<<dec<<WSAGetLastError()<<endl;}
FileBuf.empty=true;
};
//////////////////////////////////////////////////////////
//
// Router Destructor
// arguements:
// fn: A string of log file name
//
//////////////////////////////////////////////////////////
Router :: ~Router()
{
closesocket(Sock1);
closesocket(Sock2);
/* When done, uninstall winsock.dll (WSACleanup()) and exit */
WSACleanup();
//close log file
fout.close();
};
//////////////////////////////////////////////////////////
//
// Main function
//
//////////////////////////////////////////////////////////
int main()
{
Router router;
router.Run();
return 0;
}