epoll写的一段文件上传程序

来源:互联网 发布:基本块优化 编辑:程序博客网 时间:2024/06/08 04:49

FROM: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;
}

原创粉丝点击