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