文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>C/S 传送文件的例子

C/S 传送文件的例子

时间:2009-04-19  来源:zhengwenwei_123

之前写了一个用jrtplib实现的C/S传送文件的例子,现在贴上来,免得以后丢失了。
服务器:


//SIGSEGV-SEGMENTATION FAULT

//BUT, WAIT, WHY? cause of so?

//3)

//funk! uint8_t is equal with char, 8 bits, well, obviously!

//4)

//when sending file_len, a SIGSEGV SIGNAL received

//an error is: use data_count as uint8_t

//5)

//NOTICE

//the add destination action, take care of it, I find something

//strange.

//I firstly guess it will add the source address automatically, but

//now it seems not, strangely, so I add it by my hand.

//6)

//if it's too fast to send the packet, the client will not

//receive the pakcets, so try to find how to wait

//but what if we bigger the packet size?

//this seem to work, bigger the packet size, longer the waiting

//time.

//7)

//sometime the EOF packet lost, the client keep sending RTCP packets, make sure

//he knows the EOF on RTCP received


//global value

static bool requ_received = false;
static bool file_name_received = false;
static bool receive_ready = false;
//say bye to the source

bool source_bye = false;
char *file_name;
uint8_t null_array[4];
char null_char[4];

//types of apppackets

typedef enum{
    REQU = 0, SERVER_OK, SERVER_BUSY, FILENAME, FILEINFO, RECEIVE_READY
}apppacketT;

//check error

void checkerror(int rtperr)
{
    if(rtperr < 0)
    {
        std::cout<<"ERROR:"<<RTPGetErrorString(rtperr)<<std::endl;
        exit(-1);
    }
}

//set rulers for apppackets

class MyRTPSession : public RTPSession
{
    protected:
#ifdef _DEBUG
        void OnNewSource(RTPSourceData *srcdat)
        {
            std::cout<<"test source"<<std::endl;
            if(srcdat->IsOwnSSRC())
            {
                return;
            }
            uint32_t ip;
            uint16_t port;
            if(srcdat->GetRTCPDataAddress() != 0)
            {
                const RTPIPv4Address *addr =
                    (const RTPIPv4Address *)
                    (srcdat->
                     GetRTCPDataAddress());
                ip = addr->GetIP();
                port = addr->GetPort()-1;
                RTPIPv4Address src_addr(ip, port);
                AddDestination(src_addr);
            }
            return;
        }
        void OnRTPPacket(RTPPacket *pack,
                const RTPTime &receivetime,
                const RTPAddress *senderaddress)
        {
            std::cout<<"test rtppacket"<<std::endl;
            RTPTime::Wait(RTPTime(1.0));
        }
#endif
        void OnRTCPCompoundPacket(RTCPCompoundPacket *pack,
                const RTPTime &receivetime,
                const RTPAddress *senderaddress)
        {
#ifdef _DEBUG
            //std::cout<<"test rtcp"<<std::endl;

#endif
            if(source_bye == true)
            {
                //send the EOF

                checkerror(SendPacket(NULL, 0));
            }
        }
        
        void OnAPPPacket(RTCPAPPPacket *apppacket,
                const RTPTime &receivetime,
                 const RTPAddress *senderaddress)
        {
            //get the subtype of apppacket

            apppacketT subtype = (apppacketT)(apppacket->GetSubType());
            switch(subtype)
            {
            case REQU:
                if(requ_received == true)
                {
                    //busy will be sent to every sourcem, also the serving

                    //one, but he can judge it's not his funk

                    SendRTCPAPPPacket((uint8_t)SERVER_BUSY, null_array, null_char, 4);
                }
                //the ok is sent in the main()

#ifdef _DEBUG
            std::cout<<"test requ"<<std::endl;
#endif
                requ_received = true;
                break;
            case FILENAME:
                if(file_name_received == true)
                {
                    break;
                }
#ifdef _DEBUG
            std::cout<<"test file_name"<<std::endl;
#endif
                file_name =(char *)
                    (apppacket->GetAPPData());
                file_name_received = true;
                break;
            case RECEIVE_READY:
                if(receive_ready == true)
                {
                    break;
                }
#ifdef _DEBUG
            std::cout<<"test received_ready"<<std::endl;
#endif
                receive_ready = true;
                break;
            default:
                break;
            }
        }
};

//wait for some seconds

void waiting(double seconds)
{
    RTPTime::Wait(RTPTime(seconds));
}

//notice here, global sess

MyRTPSession sess;

//print the situation of the network

void *print_situation(void *)
{
    RTPSourceData *source;
    while(1)
    {
        if(source_bye == true)
        {
            return(NULL);
        }
        sess.BeginDataAccess();
        sess.GotoFirstSource();
        source = sess.GetCurrentSourceInfo();
        //it's me

        if(source->IsOwnSSRC())
        {
            sess.GotoNextSource();
            source = sess.GetCurrentSourceInfo();
        }
        std::cout<<"FractionLost: "
            <<source->RR_GetFractionLost()<<std::endl;
        std::cout<<"PacketsLost: "
            <<source->RR_GetPacketsLost()<<std::endl;
        std::cout<<"Jitter: "
            <<source->RR_GetJitter()<<std::endl;
        sess.EndDataAccess();
        waiting(1.0);
        //sleep this thread

        sleep(1);
    }
    return(NULL);
}

int main()
{
    int status;

    //set params

    RTPSessionParams sessparams;
    sessparams.SetOwnTimestampUnit(1.0/8000.0);
    sessparams.SetAcceptOwnPackets(false);

    //set transparams

    RTPUDPv4TransmissionParams transparams;
#ifndef _DEBUG
    uint16_t localport;
    std::cout<<"Local Port: "<<std::endl;
    std::cin>>localport;
    transparams.SetPortbase(localport);
#else
    transparams.SetPortbase(8000);
#endif

    //create a session

    status = sess.Create(sessparams, &transparams);
    checkerror(status);

    //set packet attribute

    sess.SetDefaultPayloadType(96);
    sess.SetDefaultMark(false);
    sess.SetDefaultTimestampIncrement(160);
    sess.SetMaximumPacketSize
        ((size_t)((DATA_EACH_PACKET*1.1)));
#ifdef _DEBUG
//    uint8_t destip[]={192, 168, 0, 3};

//    RTPIPv4Address addr(destip, 8000);

//    status = sess.AddDestination(addr);

//    checkerror(status);

#endif

    //daemon

    while(1)
    {
        //got a request

        if(requ_received == true)
        {
            int fd;
            int file_len;
            //until we get the file name

            while(!file_name_received)
            {
                status =
                sess.SendRTCPAPPPacket((uint8_t)SERVER_OK,
                         null_array, null_char, 4);
                checkerror(status);
                waiting(1.0);
                //hey, regularly poll!

                sess.Poll();
                if(file_name_received ==false)
                {
                    continue;
                }
                //if it's a valid file name

                fd = open(file_name, O_RDONLY);
                //a valid name

                if(fd < 0)
                {
                    file_len = 0;
                    status =
                    sess.SendRTCPAPPPacket((uint8_t)FILEINFO,
                         (uint8_t*)&file_len, null_char, 4);
                    sess.Poll();
                    waiting(1.0);
                    file_name_received
                         = false;
                }
                else
                {
                    //get the stat of file

                    struct stat st;
                    if(stat(file_name, &st) < 0)
                    {
                        std::cout
                    <<"Cannot get the stat of file"<<std::endl;
                        exit(-1);
                    }
                    file_len = st.st_size;
                }
            }
            //open the file, get the information

            //until he's ready

            while(!receive_ready)
            {
                sess.SendRTCPAPPPacket((uint8_t)FILEINFO,
                         (uint8_t*)&file_len, null_char, 4);
                waiting(1.0);
                sess.Poll();
            }
            //now he's ok

            if(status < 0)
            {
                std::cout<<"Error Thread"
                    <<std::endl;
            }

            RTPSourceData *source;
            struct in_addr inaddr;
            uint16_t port;
            sess.BeginDataAccess();
            if(sess.GotoFirstSource())
            {
                source = sess.GetCurrentSourceInfo();
                //it's me

                if(source->IsOwnSSRC())
                {
                    sess.GotoNextSource();
                    source = sess.GetCurrentSourceInfo();
                }
                //get the client address

                uint32_t ip;
                const RTPIPv4Address *addr;
                if(source->GetRTCPDataAddress() != 0)
                {
                 addr = (const RTPIPv4Address *)
                        (source->GetRTCPDataAddress());
                    ip = addr->GetIP();
                    port = addr->GetPort()-1;
                    inaddr.s_addr = htonl(ip);
                    std::cout<<"Begin service for: "
                    << std::string(inet_ntoa(inaddr))
                        <<"-"<<port<<std::endl;
                    std::cout<<"File Length: "
                        <<file_len<<std::endl;
                }
            }
            sess.EndDataAccess();
            //create a thread for printing situation

            pthread_t thread_id;
            status = pthread_create(&thread_id, NULL,
                    &print_situation, NULL);
            //begin send data

            void *file_memory;
            char *index;
            file_memory =
                mmap(NULL, file_len, PROT_READ, MAP_SHARED,
                         fd, 0);
            if(file_memory == MAP_FAILED)
            {
                std::cout<<"FiLe Map failed"<<std::endl;
                exit(-1);
            }
            close(fd);
            index = (char *)file_memory;
            int data_count;
            for(data_count = 0;
                file_len > data_count + DATA_EACH_PACKET;
                    data_count += DATA_EACH_PACKET)
            {
#ifdef _DEBUG
            //    std::cout<<"data_count: "

            //        <<data_count<<std::endl;

#endif
                status = sess.SendPacket(index,
                        DATA_EACH_PACKET);
                checkerror(status);
                index += DATA_EACH_PACKET;
                sess.Poll();
                RTPTime::Wait(RTPTime(0, 800));
            }
            //send the reminded data

            status =
                sess.SendPacket(index, file_len-data_count);
            checkerror(status);
            //send the EOF

            status = sess.SendPacket(NULL, 0);
            checkerror(status);
            //the source bye now

            source_bye = true;
            //join the thread

            pthread_join(thread_id, NULL);
            //end send data

            munmap(file_memory, file_len);
            std::cout<<"End service for: "<<
                std::string(inet_ntoa(inaddr))
                <<"-"<<port<<std::endl;
            //wait for EOF received

            for(int i = 0; i < 5; i++)
            {
                sess.Poll();
                waiting(1.0);
            }
            //clear the last service

            requ_received = false;
            file_name_received = false;
            receive_ready = false;
            source_bye = false;
        }
        sess.Poll();
    }
    return(0);
}


客户端:

        }
        void OnRTPPacket(RTPPacket *pack,
                const RTPTime &receivetime,
                const RTPAddress *senderaddress)
        {
            //std::cout<<"test rtppacket"<<std::endl;

        }
#endif
        void OnAPPPacket(RTCPAPPPacket *apppacket,
                const RTPTime &receivetime,
                const RTPAddress *senderaddress)
        {
            //get the subtype of apppacket

            apppacketT subtype = (apppacketT)(apppacket->GetSubType());
            switch(subtype)
            {
            case SERVER_OK:
                if(ok == true)
                {
                    break;
                }
#ifdef _DEBUG
            std::cout<<"test ok"<<std::endl;
#endif
                ok = true;
                break;
            case SERVER_BUSY:
                if(ok == true || busy ==true)
                {
                    break;
                }
#ifdef _DEBUG
            std::cout<<"test busy"<<std::endl;
#endif
                busy = true;
                break;
            case FILEINFO:
                if(file_info == false)
                {
                    file_info = true;
#ifdef _DEBUG
            std::cout<<"test file_info"<<std::endl;
#endif
                    //take care!

                    //though you use file_len as a int, but in fact, the

                    //complier will make the uint8_t exapanded into a int

                    //but not the 4 ones

                    //file_len = *(apppacket->GetName());

                    //this not works

                    //file_len = (int)*(apppacket->GetName());

                    file_len = *(int *)(apppacket->GetName());
                }
                else
                {
                    //let he know we're ready

                    SendRTCPAPPPacket((uint8_t)RECEIVE_READY,
                            null_array, null_char, 4);
                }
                break;
            default:
                break;
            }
        }
};

//check error

void checkerror(int rtperr)
{
    if(rtperr < 0)
    {
        std::cout<<"ERROR:"<<RTPGetErrorString(rtperr)<<std::endl;
        exit(-1);
    }
}
//wait for some seconds

void waiting(double seconds)
{
    RTPTime::Wait(RTPTime(seconds));
}

int main()
{
    int status;

    //set params

    RTPSessionParams sessparams;
    sessparams.SetOwnTimestampUnit(1.0/8000.0);
    sessparams.SetAcceptOwnPackets(false);

    //set transparams

    RTPUDPv4TransmissionParams transparams;
#ifndef _DEBUG
    uint16_t localport;
    std::cout<<"Local Port: "<<std::endl;
    std::cin>>localport;
    transparams.SetPortbase(localport);
#else
    transparams.SetPortbase(8000);
#endif

    //create a session

    MyRTPSession sess;
    status = sess.Create(sessparams, &transparams);
    checkerror(status);
#ifndef _DEBUG
    //add destination

    std::string ipstr;
    uint32_t destip;
    uint16_t destport;
    std::cout<<"Destination IP: "<<std::endl;
    std::cin>>ipstr;
    destip = inet_addr(ipstr.c_str());
    if(destip == INADDR_NONE)
    {
        std::cerr<<"Bad IP"<<std::endl;
        return(-1);
    }
    destip = ntohl(destip);
    std::cout<<"Destination Port: "<<std::endl;
    std::cin>>destport;
#else
    uint8_t destip[] = {192, 168, 0, 2};
    uint16_t destport = 8000;
#endif
    RTPIPv4Address addr(destip, destport);
    status = sess.AddDestination(addr);
    checkerror(status);

    //until we know if we could get the service

    while(!ok & !busy)
    {
        status =
            sess.SendRTCPAPPPacket((uint8_t)REQU,
                null_array, null_char, 4);
        checkerror(status);
        //we should wait for sometime, otherwise we're too "worried"

        waiting(1.0);
        sess.Poll();
    }

    if(ok)
    {
        char name_char[16];
        memset((void *)name_char, 0, 16);
        std::string file_name;
        //until we get a valid file_name

        while(1)
        {
            //which file you want to get?

            std::cout<<"File Name: "<<std::endl;
            std::cin>>file_name;
            memcpy((void *)name_char, (void *)(file_name.c_str()),
                    file_name.length());
            //until we get the file information

            while(!file_info)
            {
                sess.SendRTCPAPPPacket((uint8_t)FILENAME,
                        null_array, name_char, 16);
                waiting(1.0);
                sess.Poll();
            }
            //if the file is valid?

            if(file_len == 0)
            {
                std::cout<<"Invalid File"<<std::endl;
                file_info = false;
                continue;
            }
            break;
        }
        //create the file

        int fd;
        void *file_memory;
        char *index;
        fd = open(file_name.c_str(), O_RDWR|O_CREAT);
        if(fd < 0)
        {
            std::cout<<"Cannot create file"<<std::endl;
            exit(-1);
        }
        lseek(fd, file_len-1, SEEK_SET);
        write(fd, "", 1);
        lseek(fd, 0, SEEK_SET);
        file_memory = mmap(NULL, file_len, PROT_WRITE, MAP_SHARED, fd, 0);
        if(file_memory == MAP_FAILED)
        {
            std::cout<<"Map failed"<<std::endl;
            exit(-1);
        }
        //we keep the index forward, but keep the file_memory at the start

        index = (char *)file_memory;
        //you can close fd now

        close(fd);
#ifdef _DEBUG
        std::cout<<"Send Packet"<<std::endl;
        sess.SendPacket(NULL, 0, 0, false, 0);
        waiting(1.0);
#endif
        //now we're ready to receive data

        sess.SendRTCPAPPPacket((uint8_t)RECEIVE_READY,
                null_array, null_char, 4);
        waiting(1.0);
        //begin receiving data

        bool done = false;
        RTPSourceData *source;
        RTPPacket *pack;
        uint8_t *payloaddata;
        size_t payloadlength;
#ifdef _DEBUG
        int data_count = 0;
#endif
        while(!done)
        {
            //we only have one server source

            sess.BeginDataAccess();
            if(sess.GotoFirstSourceWithData())
            {
             do
                {
#ifndef _DEBUG
//                    source = sess.GetCurrentSourceInfo();

//                    if(source->IsOwnSSRC())

//                    {

//                        //it's me

//                        sess.GotoNextSourceWithData();

//                    }

#endif
                    while((pack = sess.GetNextPacket()) != NULL)
                    {
#ifdef _DEBUG
                        //std::cout<<"Data Count: "

                        //    <<data_count<<std::endl;

#endif
                        payloaddata = pack->GetPayloadData();
                        payloadlength = pack->GetPayloadLength();
                        //if this is the end of data?

                        if(payloadlength == 0)
                        {
#ifdef _DEBUG
                            std::cout<<"Data Couunt: "
                                <<data_count
                                <<std::endl;
#endif
                            std::cout<<"EOF"<<std::endl;
                            done = true;
                            break;
                        }
                        //copy the data into file memory

                        memcpy(index, (const void *)payloaddata,
                                payloadlength);
#ifdef _DEBUG
                        data_count += payloadlength;
#endif
                        index += payloadlength;
                        sess.DeletePacket(pack);
                    }
                }while(sess.GotoNextSourceWithData());
            }
            sess.EndDataAccess();
            status = sess.Poll();
            checkerror(status);
            //why wait? I'm not sure if this wait is necessary?

            //waiting(1.0);

        }
        //end receiving data

        munmap(file_memory, file_len);
    }
    else//busy

    {
        std::cout<<"Server is busy now, choose another time"<<std::endl;
    }
    //BYE

    sess.BYEDestroy(RTPTime(10.0), 0, 0);
    return(0);
}

相关阅读 更多 +
排行榜 更多 +
兔子跳一跳游戏

兔子跳一跳游戏

休闲益智 下载
球球跳跃游戏

球球跳跃游戏

休闲益智 下载
森林之灵游戏

森林之灵游戏

休闲益智 下载