• epoll写的一段文件上传程序

    日期:2008-01-19 | 分类:网络编程

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://scudong.blogbus.com/logs/14124525.html

    // 服务端程序
    #include "common.h"
    #include <sys/epoll.h>
    // 读操作
    int read_task( int fd )
    {
        if ( fd <= 0 )
            return FAIL;
        char *mem = NULL;
        try
        {
            int msg_size = sizeof(msg_item);
            mem = (char *)malloc( msg_size );
            memset( mem, 0, msg_size );        
            char *p = mem;
            int ret = Receive( fd, mem, msg_size );
            if ( ret <= 0 )
            {
                free( mem );
                mem = NULL;
                return FAIL;
            }
            msg_item item;
            memset( &item, 0, msg_size );
            // filelen(int) + content_len(int) + cmd(int) + filename + content
            int filename_len = 0, content_len = 0;
            memmove( &filename_len,  p, 4);        p += 4;
            memmove( &content_len,   p, 4);        p += 4;
            memmove( &item.m_cmd,    p, 4);        p += 4;
            memmove( &item.m_file,   p, filename_len );    p += filename_len;
            memmove( &item.m_content, p, content_len );
       
         string upload_file = config[UPLOAD_FILE_DIR] + item.m_file;
            switch( item.m_cmd )
            {
                case 0: // got file size
                {
                    char f_size[16];
                    memset( f_size, 0, 16 );               
                    long size = file_size( upload_file );
                    sprintf( f_size, "%ld", size );
                    Send( fd, f_size, 16 );
                    break;
                }
                case 1: // write file
                {
                     FILE *fp = fopen( upload_file.c_str(), "ab+" );
                     if ( fp == NULL )
                         THROW( "File open error! %s", upload_file.c_str() );

                     fseek( fp, 0, SEEK_END );
                     ret = fwrite( item.m_content, 1, content_len, fp );
                     if ( ret != content_len )
                     {
                        fclose( fp );
                        THROW( "File write error! %s", upload_file.c_str() );
                     }
                     // close
                     fclose( fp );
                     break;
                }
             }
            
    // clean
            free( mem );
            mem = NULL;
            return OK;
        }
        catch ( CExcept &e )
        {
            if ( mem != NULL )
            {
                free( mem );
                mem = NULL;
            }
            loging( "%s:%s", e.where().c_str(), e.detail().c_str() );
        }
        return FAIL;
    }
    // 添加新的事件文件描述符
    void epoll_add( int &epfd, int newfd )
    {
        struct epoll_event ev;
        ev.data.fd = newfd;
        ev.events = EPOLLIN|EPOLLET|EPOLLERR | EPOLLHUP;
        epoll_ctl( epfd, EPOLL_CTL_ADD, newfd, &ev );
    }
    // 创建epoll

    int epoll_create( int sockfd, int poll_size )
    {
        int epfd = epoll_create( poll_size );
        epoll_add( epfd, sockfd );
        return epfd;
    }
    // 主程序
    int main( int argc, char *argv[] )
    {   
        // 读取配置文件
        int ret = parse_ini( GLOBAL_INI, config );
        if ( ret == FAIL )
        {
            cout << "读取配置文件出错!" << endl;
            return 1;
        }
        int sockfd = SocketServer( stoi(config[UPLOAD_SERVER_PORT]), LISTENQ );
        if ( sockfd == INVALID_SOCKET )
        {
            cout << "INVALID_SOCKET!" << endl;
            return 1;
        }
        int epfd = epoll_create( sockfd, POLL_SIZE ), new_fd;
        struct sockaddr_in client_addr;
        int sin_size = sizeof( struct sockaddr_in );
        struct epoll_event events[MAX_EVENTS];
        while ( 1 )
        {   
            // 等待epoll事件的发生
            int nfds = epoll_wait( epfd, events, MAX_EVENTS, -1 );
            // 处理所发生的所有事件
            for ( int i = 0; i < nfds; ++i )              
            {
                 if ( events[i].data.fd == sockfd )// 新连接
                {
                     new_fd = accept( sockfd, (struct sockaddr *)&client_addr,
                                    (socklen_t *)&sin_size );
                    if ( new_fd == -1 )
                    {
                        perror( "accept" );
                        continue;
                    }
                    SetNoBlock( new_fd );
                    printf( "server: got connection from %s\n",
                            inet_ntoa( client_addr.sin_addr ) );
                    epoll_add( epfd, new_fd );               
                }
                else if ( events[i].events & EPOLLIN ) // 读事件发生
                {
                    new_fd = events[i].data.fd;
                    if ( new_fd < 0 )
                    {
                        cout << "new_fd is null " << endl;
                        continue;
                    }
                     cout << "-------------start read-------------------" << endl;
                    int cmd = read_task( new_fd );
                    if ( cmd == FAIL )
                    {
                        cout << "read fail" << endl;
                        close( new_fd );
                        events[i].data.fd = -1;
                        continue;
                    }
                }
             }
         }
        // close
        close( sockfd );
        return 0;
    }


    // 上传客户端程序
    #include "common.h"
    // 发送文件内容
    int send_content( int sock, const msg_item *item, int nRead )
    {
        if ( sock <= 0 )
            return FAIL;
         
        char *mem = (char *) malloc( sizeof(msg_item) );
        char *p = mem;
        int filename_len = strlen( item->m_file );
        // filelen(int) + content_len(int) + cmd(int) + filename + content
        memmove( p, &filename_len,  4 );        p += 4;        
        memmove( p, &nRead,         4 );        p += 4;
        memmove( p, &item->m_cmd,   4 );        p += 4;
        memmove( p, &item->m_file,  filename_len ); p += filename_len;
        if ( nRead > 0 )
        {
            memmove( p, &item->m_content, nRead );
        }
        cout << " cmd=" <<item->m_cmd << endl;
        int size = sizeof(msg_item);
    // 3*INT_SIZE+filename_len+nRead;

        cout << "size=" << size << endl;
        int nWrite = Send( sock, mem, size );
         if ( nWrite <= 0 )
        {
            cout << "write error !" << endl;
            free( mem );
            mem = NULL;
            return FAIL;
        }
        cout << "write = " << nWrite << endl;
         free( mem );
        mem = NULL;
        usleep( 1000 );
         return SUCC;
    }

    int main(int argc, char *argv[])
    {
        if ( argc < 2 )
        {
            cerr << "命令格式: " << argv[0]
                 << " <文件>" << endl;
            exit( 1 );
        }

        string src_file( argv[1] );
        unsigned int pos = src_file.find_last_of( "/" );
        string file_name = src_file.substr( pos + 1 );
        cout << file_name << endl;
        // start upload
        for ( int i = 0; i < 1; i++ )
        {
            cout << "===>i=" << i << endl;
            int sockfd = NonbSocket( "192.168.1.200", 3000 );
       
            if ( sockfd == INVALID_SOCKET )
            {
                cout << "===>INVALID_SOCKET!" << endl;
                return 1;
            }
            
    // step 1: got file size from server for seek

            int nRead = 0;
            msg_item item;
            memset( &item, 0, sizeof(msg_item) );
            item.m_cmd = 0;
            strcpy( item.m_file, file_name.c_str() );
            printf( "item.m_file=%s \n", item.m_file );
            // send request
            int ret = send_content( sockfd, &item, nRead );
            if ( ret == FAIL )
                 break;
             // receive return
            char f_size[16];
            Receive( sockfd, f_size, 16 );
            printf( "f_size=%s atol=%ld\n", f_size, atol(f_size) );
            // seek last pos
            int nTotalRead = atol( f_size );
            if ( nTotalRead < 0 )
                nTotalRead = 0;
            FILE *fp = fopen( src_file.c_str(), "rb" );
            if ( fp == NULL )
            {
                cout << "===>Error open file " << endl;
                return 1;
            }
            //fseek( fp, nTotalRead, SEEK_SET );
            long size = file_size(src_file);
            while ( 1 )
            {
                msg_item *msg = (msg_item *)malloc( sizeof(msg_item) );
                memset( msg, 0, sizeof(msg_item) );
                msg->m_cmd = 1;
                strcpy( msg->m_file, file_name.c_str() );
                nRead = fread( msg->m_content, 1, CONTENT_LEN, fp );
                cout << "===>nRead=" << nRead << endl;
                if ( nRead <= 0 )
                {
                     msg->m_cmd = 2;
                     
    /*int ret =send( sockfd, msg, sizeof(msg_item), 0 );
                    cout << "send ret=" << ret << endl;*/

                     send_content( sockfd, msg, nRead );
                     cout << "nRead is 0 " << endl;

                     free( msg );
                    msg = NULL;
                    break;
                }
                ret = send_content( sockfd, msg, nRead );
                if ( ret == FAIL )
                {
                     printf( "send error! \n" );
                    free( msg );
                    msg = NULL;
                    break;
                }
      
                nTotalRead += nRead;
                cout << "nTotalRead=" << nTotalRead << endl;
                int pos = (int)( ((0.001*nTotalRead)/(size*0.001) ) * 100 );
                fprintf( stderr, "========total send:%d%%========\n", pos );
                
                free( msg );
                msg = NULL;
               }
    // while

              cout << "===>Close file" << endl;
             fclose( fp );
              close( sockfd );
         }
    // for

        return 0;
    }


    收藏到:Del.icio.us




    评论

  • 兄弟,代码里的头文件都看不到啊。。。。。
    "common.h"怎么没贴出来,libpcap编程入门里的头文件也没有只有个include.