2

I have some problems with a server-client FTP simulation program. The program keeps giving me "undefined reference" errors. I use C::B 10.05 on windows, and tried including winsock.h, winsock2.h, and a lot more solutions i found on the internet, but it didn't worked. Here is the source-code. Any help is greatly apreciated. Thanks.

//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;
}

1 Answers1

0

The "undefined reference" errors are linker errors. Linker errors cannot be resolved by including additional header files. Conceptually, the header file contains the declaration of a function (the name of the function, the types of its parameters, the type of its return value). You include header files so that you can reference the functions declared in the header in your program. During linking, these references are resolved to point to the library containing the actual implementation of these function.

When you get an "undefined reference" error, that means the linker was unable to find the implementation of a function you referenced in your code in any of the libraries the linker was told to link against. To solve this, you have to find the library where the missing function is implemented and tell the compiler to link against this library.

When I compile your program, I get the following errors:

error LNK2019: unresolved external symbol "___WSAFDIsSet@8" referenced in function ""public: void __thiscall Router::Run(void)" (?Run@Router@@QAEXXZ)".
error LNK2019: unresolved external symbol "__imp__bind@12" referenced in function "__catch$??0Router@@QAE@PBD@Z$0".
error LNK2019: unresolved external symbol "__imp__closesocket@4" referenced in function ""public: __thiscall Router::~Router(void)" (??1Router@@QAE@XZ)".
error LNK2019: unresolved external symbol "__imp__htonl@4" referenced in function "__catch$??0Router@@QAE@PBD@Z$0".
error LNK2019: unresolved external symbol "__imp__htons@4" referenced in function "__catch$??0Router@@QAE@PBD@Z$0".
error LNK2019: unresolved external symbol "__imp__recvfrom@24" referenced in function ""public: void __thiscall Router::Run(void)" (?Run@Router@@QAEXXZ)".
error LNK2019: unresolved external symbol "__imp__select@20" referenced in function ""public: void __thiscall Router::Run(void)" (?Run@Router@@QAEXXZ)".
error LNK2019: unresolved external symbol "__imp__sendto@24" referenced in function ""public: void __thiscall Router::Run(void)" (?Run@Router@@QAEXXZ)".
error LNK2019: unresolved external symbol "__imp__socket@12" referenced in function "__catch$??0Router@@QAE@PBD@Z$0".
error LNK2019: unresolved external symbol "__imp__gethostbyname@4" referenced in function "__catch$??0Router@@QAE@PBD@Z$0".
error LNK2019: unresolved external symbol "__imp__gethostname@8" referenced in function "__catch$??0Router@@QAE@PBD@Z$0".
error LNK2019: unresolved external symbol "__imp__WSAStartup@8" referenced in function ""public: __thiscall Router::Router(char const *)" (??0Router@@QAE@PBD@Z)".
error LNK2019: unresolved external symbol "__imp__WSACleanup@0" referenced in function ""public: __thiscall Router::~Router(void)" (??1Router@@QAE@XZ)".
error LNK2019: unresolved external symbol "__imp__WSAGetLastError@0" referenced in function "__catch$??0Router@@QAE@PBD@Z$0".

We now have to identify the libraries that define these symbols. Putting their names into a search engine tells me that they are all part of the winsocket2 API. The examle given here tells us that the corresponding library is called Ws2_32.lib.

We now have to tell the compiler to link against this library. The precise steps depend on your compiler / IDE. You indicated that you are using Code::Blocks. Refer to the instructions given here on how to add the library in Code::Blocks (it seems Code::Blocks wants the library name without the .lib suffix, so the name would be Ws2_32, instead of Ws2_32.lib).

After linking against this library, your code compiles successfully.