#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
static bool stop = false;
static void handle_term( int sig ) // kill pid; in another tty will triggle this signal
{
stop = true;
printf("signal SIGTERM catched...
");
}
static void handle_int(int sig) // ctrl+c; will triggle this signal
{
printf("signal SIGINT catched...
");
stop = true;
}
//./listen 127.0.0.1 8888 100
int main( int argc, char* argv[] )
{
signal( SIGTERM, handle_term );
signal(SIGINT, handle_int);
if( argc <= 3 )
{
printf( "usage: %s ip_address port_number backlog
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
int backlog = atoi( argv[3] );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
printf("after bind...
");
//backlog is the max number of waitting connect in wait queue
ret = listen( sock, backlog ); //listen is a none-block function
assert( ret != -1 );
printf("after listen...
");
while ( ! stop )
{
sleep( 1 );
}
close( sock );
return 0;
}
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
int reuse = 1;
setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
printf("AFTER bind...
");
ret = listen( sock, 5 );
assert( ret != -1 );
printf("AFTER listen...
");
//the returned client is client's address
struct sockaddr_in client;
socklen_t client_addrlength = sizeof( client );
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); //accept is a block function
printf("AFTER accept...
");
if ( connfd < 0 )
{
printf( "errno is: %d
", errno );
}
else
{
//#define INET_ADDRSTRLEN 16 , IPV4 address char array length, <netinet/in.h>
char remote[INET_ADDRSTRLEN ];
printf( "connected with ip: %s and port: %d
",
inet_ntop( AF_INET, &client.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( client.sin_port ) );
close( connfd );
}
close( sock );
return 0;
}
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define BUF_SIZE 1024
int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
ret = listen( sock, 5 );
assert( ret != -1 );
printf("after listen...
");
struct sockaddr_in client;
socklen_t client_addrlength = sizeof( client );
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
printf("after accept...
");
if ( connfd < 0 )
{
printf( "errno is: %d
", errno );
}
else
{
char buffer[ BUF_SIZE ];
memset( buffer, ' ', BUF_SIZE );
ret = recv( connfd, buffer, BUF_SIZE-1, 0 );
printf( "got %d bytes of normal data '%s'
", ret, buffer );
memset( buffer, ' ', BUF_SIZE );
//MSG_OOB: support recv out-of-band data
//Only TCP support oob data
//TCP only 1 byte oob data
//use MSG_OOB flag when call send to send oob data
ret = recv( connfd, buffer, BUF_SIZE-1, MSG_OOB );
printf( "got %d bytes of oob data '%s'
", ret, buffer );
memset( buffer, ' ', BUF_SIZE );
ret = recv( connfd, buffer, BUF_SIZE-1, 0 );
printf( "got %d bytes of normal data '%s'
", ret, buffer );
close( connfd );
}
close( sock );
return 0;
}
connect
#include <sys/socket.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define BUFFER_SIZE 512
int main( int argc, char* argv[] )
{
if( argc <= 3 )
{
printf( "usage: %s ip_address port_number send_bufer_size
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
struct sockaddr_in server_address;
bzero( &server_address, sizeof( server_address ) );
server_address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &server_address.sin_addr );
server_address.sin_port = htons( port );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
int sendbuf = atoi( argv[3] );
int len = sizeof( sendbuf );
setsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf ) );
getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len );
printf( "the tcp send buffer size after setting is %d
", sendbuf );
if ( connect( sock, ( struct sockaddr* )&server_address, sizeof( server_address ) ) != -1 )
{
//
printf("call getsockname ...
");
struct sockaddr_in local_address;
socklen_t length;
int ret = getpeername(sock, ( struct sockaddr* )&local_address, &length);
assert(ret == 0);
char local[INET_ADDRSTRLEN ];
printf( "local with ip: %s and port: %d
",
inet_ntop( AF_INET, &local_address.sin_addr, local, INET_ADDRSTRLEN ), ntohs( local_address.sin_port ) );
//
char buffer[ BUFFER_SIZE ];
memset( buffer, 'a', BUFFER_SIZE );
send( sock, buffer, BUFFER_SIZE, 0 );
}
close( sock );
return 0;
}
accept:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
int reuse = 1;
setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
printf("AFTER bind...
");
ret = listen( sock, 5 );
assert( ret != -1 );
printf("AFTER listen...
");
//the returned client is client's address
struct sockaddr_in client;
socklen_t client_addrlength = sizeof( client );
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); //accept is a block function
printf("AFTER accept...
");
if ( connfd < 0 )
{
printf( "errno is: %d
", errno );
}
else
{
//#define INET_ADDRSTRLEN 16 , IPV4 address char array length, <netinet/in.h>
char remote[INET_ADDRSTRLEN ];
printf( "connected with ip: %s and port: %d
",
inet_ntop( AF_INET, &client.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( client.sin_port ) );
//
printf("call getsockname ...
");
struct sockaddr_in local_address;
socklen_t length;
int ret = getsockname(connfd, ( struct sockaddr* )&local_address, &length);
if (ret == 0)
{
char local[INET_ADDRSTRLEN ];
printf( "local connfd ip: %s and port: %d
", inet_ntop( AF_INET, &local_address.sin_addr, local, INET_ADDRSTRLEN ), ntohs( local_address.sin_port ) );
}
else
printf("getsockname on connfd fail...
");
bzero( &local_address, sizeof( local_address ) );
ret = getpeername(connfd, ( struct sockaddr* )&local_address, &length);
if (ret == 0)
{
char local1[INET_ADDRSTRLEN ];
printf( "remote ip: %s and port: %d
", inet_ntop( AF_INET, &local_address.sin_addr, local1, INET_ADDRSTRLEN ), ntohs( local_address.sin_port ) );
}
else
printf("getpeername on connfd fail...
");
close( connfd );
}
close( sock );
return 0;
}
setsendbuffer:
#include <sys/socket.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define BUFFER_SIZE 512
int main( int argc, char* argv[] )
{
if( argc <= 3 )
{
printf( "usage: %s ip_address port_number send_bufer_size
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
struct sockaddr_in server_address;
bzero( &server_address, sizeof( server_address ) );
server_address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &server_address.sin_addr );
server_address.sin_port = htons( port );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
int sendbuf = atoi( argv[3] );
int len = sizeof( sendbuf );
setsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf ) );
getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len );
printf( "the tcp send buffer size after setting is %d
", sendbuf );
if ( connect( sock, ( struct sockaddr* )&server_address, sizeof( server_address ) ) != -1 )
{
char buffer[ BUFFER_SIZE ];
memset( buffer, 'a', BUFFER_SIZE );
send( sock, buffer, BUFFER_SIZE, 0 );
}
close( sock );
return 0;
}
setrecvbuffer:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define BUFFER_SIZE 1024
int main( int argc, char* argv[] )
{
if( argc <= 3 )
{
printf( "usage: %s ip_address port_number receive_buffer_size
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
int recvbuf = atoi( argv[3] );
printf("recvbuf is %d
", recvbuf); /////!!!
int len = sizeof( recvbuf );
printf("len is %d
", len); /////!!!
setsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf ) );
getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len );
printf( "the receive buffer size after settting is %d
", recvbuf );
int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
ret = listen( sock, 5 );
assert( ret != -1 );
struct sockaddr_in client;
socklen_t client_addrlength = sizeof( client );
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
if ( connfd < 0 )
{
printf( "errno is: %d
", errno );
}
else
{
char buffer[ BUFFER_SIZE ];
memset( buffer, ' ', BUFFER_SIZE );
while( recv( connfd, buffer, BUFFER_SIZE-1, 0 ) > 0 )
{
printf("%s
", buffer);
}
close( connfd );
}
close( sock );
return 0;
}
daytime:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
int main( int argc, char *argv[] )
{
//assert( argc == 2 );
//char *host = argv[1];
struct hostent *host; //存放主机信息
//char addr_p[NET_ADDR_STR_LEN]; //用于存放点分十进制IP地址的字符串
if((host = gethostent()) == NULL)
{
perror("fail to get host's information
");
return -1;
}
printf("hostName: %s
" , host->h_name);
//用域名或主机名获取IP地址
struct hostent* hostinfo = gethostbyname( host->h_name );
assert( hostinfo );
struct servent* servinfo = getservbyname( "daytime", "tcp" );
assert( servinfo );
printf( "daytime port is %d
", ntohs( servinfo->s_port ) );
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = servinfo->s_port;
address.sin_addr = *( struct in_addr* )*hostinfo->h_addr_list;
char remote[INET_ADDRSTRLEN ];
printf( "connected with ip: %s and port: %d
",
inet_ntop( AF_INET, &address.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( address.sin_port ) );
int sockfd = socket( AF_INET, SOCK_STREAM, 0 );
//int reuse = 1;
//setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
int result = connect( sockfd, (struct sockaddr* )&address, sizeof( address ) );
printf( "errno is: %d
", errno );
perror("connect error:");
assert( result != -1 );
char buffer[128];
result = read( sockfd, buffer, sizeof( buffer ) );
assert( result > 0 );
buffer[ result ] = ' ';
printf( "the day tiem is: %s", buffer );
close( sockfd );
return 0;
}
testdup:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
ret = listen( sock, 5 );
assert( ret != -1 );
struct sockaddr_in client;
socklen_t client_addrlength = sizeof( client );
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
if ( connfd < 0 )
{
printf( "errno is: %d
", errno );
}
else
{
close( STDOUT_FILENO );
dup( connfd );
printf( "abcd
" ); //the same as write/send data in connfd
close( connfd );
}
close( sock );
return 0;
}
writev:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#define BUFFER_SIZE 1024
static const char* status_line[2] = { "200 OK", "500 Internal server error" };
int main( int argc, char* argv[] )
{
if( argc <= 3 )
{
printf( "usage: %s ip_address port_number filename
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
const char* file_name = argv[3];
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
ret = listen( sock, 5 );
assert( ret != -1 );
struct sockaddr_in client;
socklen_t client_addrlength = sizeof( client );
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
if ( connfd < 0 )
{
printf( "errno is: %d
", errno );
}
else
{
char header_buf[ BUFFER_SIZE ];
memset( header_buf, ' ', BUFFER_SIZE );
char* file_buf;
struct stat file_stat;
bool valid = true;
int len = 0;
if( stat( file_name, &file_stat ) < 0 )
{
valid = false;
}
else
{
if( S_ISDIR( file_stat.st_mode ) )
{
valid = false;
}
else if( file_stat.st_mode & S_IROTH )
{
int fd = open( file_name, O_RDONLY );
file_buf = new char[ file_stat.st_size + 1 ];
memset( file_buf, ' ', file_stat.st_size + 1 );
if ( read( fd, file_buf, file_stat.st_size ) < 0 )
{
valid = false;
}
}
else
{
valid = false;
}
}
if( valid )
{
ret = snprintf( header_buf, BUFFER_SIZE-1, "%s %s
", "HTTP/1.1", status_line[0] );
len += ret;
ret = snprintf( header_buf + len, BUFFER_SIZE-1-len,
"Content-Length: %d
", (int)file_stat.st_size );
len += ret;
ret = snprintf( header_buf + len, BUFFER_SIZE-1-len, "%s", "
" );
struct iovec iv[2];
iv[ 0 ].iov_base = header_buf;
iv[ 0 ].iov_len = strlen( header_buf );
iv[ 1 ].iov_base = file_buf;
iv[ 1 ].iov_len = file_stat.st_size;
ret = writev( connfd, iv, 2 );
}
else
{
ret = snprintf( header_buf, BUFFER_SIZE-1, "%s %s
", "HTTP/1.1", status_line[1] );
len += ret;
ret = snprintf( header_buf + len, BUFFER_SIZE-1-len, "%s", "
" );
send( connfd, header_buf, strlen( header_buf ), 0 );
}
close( connfd );
delete [] file_buf;
}
close( sock );
return 0;
}
sendfile:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sendfile.h>
int main( int argc, char* argv[] )
{
if( argc <= 3 )
{
printf( "usage: %s ip_address port_number filename
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
const char* file_name = argv[3];
int filefd = open( file_name, O_RDONLY );
assert( filefd > 0 );
struct stat stat_buf;
fstat( filefd, &stat_buf );
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
ret = listen( sock, 5 );
assert( ret != -1 );
struct sockaddr_in client;
socklen_t client_addrlength = sizeof( client );
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
if ( connfd < 0 )
{
printf( "errno is: %d
", errno );
}
else
{
//linux, not GNU. high performance send a file, 'zero copy'
sendfile( connfd, filefd, NULL, stat_buf.st_size );
close( connfd );
}
close( sock );
return 0;
}
splice:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int sock = socket( PF_INET, SOCK_STREAM, 0 );
assert( sock >= 0 );
int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
ret = listen( sock, 5 );
assert( ret != -1 );
struct sockaddr_in client;
socklen_t client_addrlength = sizeof( client );
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
if ( connfd < 0 )
{
printf( "errno is: %d
", errno );
}
else
{
int pipefd[2];
assert( ret != -1 );
ret = pipe( pipefd ); //pipe, pipefd[0] is opened for read, pipefd[1] is opened for write.
//splice用于在两个文件描述符之间移动数据, 也是零拷贝。使用splice时, fd_in和fd_out中必须至少有一个是管道文件描述符。
//sendfile只适用于将数据从文件拷贝到套接字上,限定了它的使用范围。Linux在2.6.17版本引入splice系统调用,
//用于在两个文件描述符中移动数据.
//an ECHO implement use splice.
//copy data from connfd(recv from client) to pipefd[1]
ret = splice( connfd, NULL, pipefd[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
assert( ret != -1 );
//copy data from pipefd[1] -->pipefd[0] --> connfd, send to client.
ret = splice( pipefd[0], NULL, connfd, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
assert( ret != -1 );
close( connfd );
}
close( sock );
return 0;
}
tee:
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
int main( int argc, char* argv[] )
{
if ( argc != 2 )
{
printf( "usage: %s <file>
", argv[0] );
return 1;
}
int filefd = open( argv[1], O_CREAT | O_WRONLY | O_TRUNC, 0666 );
assert( filefd > 0 );
int pipefd_stdout[2];
int ret = pipe( pipefd_stdout );
assert( ret != -1 );
int pipefd_file[2];
ret = pipe( pipefd_file );
assert( ret != -1 );
//close( STDIN_FILENO );
// dup2( pipefd_stdout[1], STDIN_FILENO );
//write( pipefd_stdout[1], "abc
", 4 );
//copy data: stdin --> pipefd_stdout[1]
ret = splice( STDIN_FILENO, NULL, pipefd_stdout[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
assert( ret != -1 );
//tee在两个管道文件描述符之间复制数据,同是零拷贝。但它不消耗数据,数据被操作之后,仍然可以用于后续操作。
//copy data: pipefd_stdout[0] --> pipefd_file[1]
ret = tee( pipefd_stdout[0], pipefd_file[1], 32768, SPLICE_F_NONBLOCK );
assert( ret != -1 );
//copy data: pipefd_file[0] --> filefd
ret = splice( pipefd_file[0], NULL, filefd, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
assert( ret != -1 );
//copy data: pipefd_stdout[0] --> stdout
ret = splice( pipefd_stdout[0], NULL, STDOUT_FILENO, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
assert( ret != -1 );
close( filefd );
close( pipefd_stdout[0] );
close( pipefd_stdout[1] );
close( pipefd_file[0] );
close( pipefd_file[1] );
return 0;
}
select:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
printf( "ip is %s and port is %d
", ip, port );
int ret = 0;
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int listenfd = socket( PF_INET, SOCK_STREAM, 0 );
assert( listenfd >= 0 );
ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
ret = listen( listenfd, 5 );
assert( ret != -1 );
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof( client_address );
int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
if ( connfd < 0 )
{
printf( "errno is: %d
", errno );
close( listenfd );
}
char remote_addr[INET_ADDRSTRLEN];
printf( "connected with ip: %s and port: %d
", inet_ntop( AF_INET, &client_address.sin_addr, remote_addr, INET_ADDRSTRLEN ), ntohs( client_address.sin_port ) );
char buf[1024];
fd_set read_fds;
fd_set exception_fds;
FD_ZERO( &read_fds );
FD_ZERO( &exception_fds );
// option:SO_OOBINLINE, value:1 --- put out of band data into normal data.
int nReuseAddr = 1;
setsockopt( connfd, SOL_SOCKET, SO_OOBINLINE, &nReuseAddr, sizeof( nReuseAddr ) );
while( 1 )
{
memset( buf, ' ', sizeof( buf ) );
FD_SET( connfd, &read_fds );
FD_SET( connfd, &exception_fds );
ret = select( connfd + 1, &read_fds, NULL, &exception_fds, NULL );
printf( "select one
" );
if ( ret < 0 )
{
printf( "selection failure
" );
break;
}
if ( FD_ISSET( connfd, &read_fds ) )
{
ret = recv( connfd, buf, sizeof( buf )-1, 0 );
if( ret <= 0 )
{
break;
}
printf( "get %d bytes of normal data: %s
", ret, buf );
}
else if( FD_ISSET( connfd, &exception_fds ) )
{
ret = recv( connfd, buf, sizeof( buf )-1, MSG_OOB );
if( ret <= 0 )
{
break;
}
printf( "get %d bytes of oob data: %s
", ret, buf );
}
}
close( connfd );
close( listenfd );
return 0;
}
epoll:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <pthread.h>
#define MAX_EVENT_NUMBER 1024
#define BUFFER_SIZE 10
int setnonblocking( int fd )
{
int old_option = fcntl( fd, F_GETFL );
int new_option = old_option | O_NONBLOCK;
fcntl( fd, F_SETFL, new_option );
return old_option;
}
void addfd( int epollfd, int fd, bool enable_et )
{
epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN; //表示对应的文件描述符可以读(包括对端SOCKET正常关闭)
if( enable_et )
{
//EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
event.events |= EPOLLET;
}
epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); //register to epoll
setnonblocking( fd );
}
void lt( epoll_event* events, int number, int epollfd, int listenfd )
{
char buf[ BUFFER_SIZE ];
for ( int i = 0; i < number; i++ )
{
int sockfd = events[i].data.fd;
if ( sockfd == listenfd )
{
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof( client_address );
int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
addfd( epollfd, connfd, false );
}
else if ( events[i].events & EPOLLIN )
{
printf( "event trigger once
" );
memset( buf, ' ', BUFFER_SIZE );
int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );
if( ret <= 0 )
{
close( sockfd );
continue;
}
printf( "get %d bytes of content: %s
", ret, buf );
}
else
{
printf( "something else happened
" );
}
}
}
void et( epoll_event* events, int number, int epollfd, int listenfd )
{
char buf[ BUFFER_SIZE ];
for ( int i = 0; i < number; i++ )
{
int sockfd = events[i].data.fd;
if ( sockfd == listenfd )
{
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof( client_address );
int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
addfd( epollfd, connfd, true );
}
else if ( events[i].events & EPOLLIN )
{
printf( "event trigger once
" );
while( 1 )
{
memset( buf, ' ', BUFFER_SIZE );
int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );
if( ret < 0 )
{
if( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) )
{
printf( "read later
" );
break;
}
close( sockfd );
break;
}
else if( ret == 0 )
{
close( sockfd );
}
else
{
printf( "get %d bytes of content: %s
", ret, buf );
}
}
}
else
{
printf( "something else happened
" );
}
}
}
int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
int ret = 0;
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int listenfd = socket( PF_INET, SOCK_STREAM, 0 );
assert( listenfd >= 0 );
ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
ret = listen( listenfd, 5 );
assert( ret != -1 );
epoll_event events[ MAX_EVENT_NUMBER ];
int epollfd = epoll_create( 5 ); //tell epoll the listen number is 5
assert( epollfd != -1 );
addfd( epollfd, listenfd, true );
while( 1 )
{
//参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,
//这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间
//该函数返回需要处理的事件数目,如返回0表示已超时。
int ret = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );
if ( ret < 0 )
{
printf( "epoll failure
" );
break;
}
lt( events, ret, epollfd, listenfd );
//et( events, ret, epollfd, listenfd );
}
close( listenfd );
return 0;
}
oneshot:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <pthread.h>
#define MAX_EVENT_NUMBER 1024
#define BUFFER_SIZE 1024
struct fds
{
int epollfd;
int sockfd;
};
int setnonblocking( int fd )
{
int old_option = fcntl( fd, F_GETFL );
int new_option = old_option | O_NONBLOCK;
fcntl( fd, F_SETFL, new_option );
return old_option;
}
void addfd( int epollfd, int fd, bool oneshot )
{
epoll_event event;
event.data.fd = fd;
//EPOLLIN表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
//EPOLLET将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
event.events = EPOLLIN | EPOLLET; //
if( oneshot )
{
//EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,
//需要再次把这个socket加入到EPOLL队列里
event.events |= EPOLLONESHOT;
}
//EPOLL_CTL_ADD:注册新的fd到epfd中;
epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event );
setnonblocking( fd );
}
void reset_oneshot( int epollfd, int fd )
{
epoll_event event;
event.data.fd = fd;
event.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
//EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
epoll_ctl( epollfd, EPOLL_CTL_MOD, fd, &event );
}
void* worker( void* arg )
{
int sockfd = ( (fds*)arg )->sockfd;
int epollfd = ( (fds*)arg )->epollfd;
printf( "start new thread to receive data on fd: %d
", sockfd );
char buf[ BUFFER_SIZE ];
memset( buf, ' ', BUFFER_SIZE );
while( 1 )
{
int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );
//ret=0 -- 这里表示对端的socket已正常关闭.
if( ret == 0 )
{
close( sockfd );
printf( "foreiner closed the connection
" );
break;
}
else if( ret < 0 )
{
//sockfd is NONBLOCK, EAGAIN -- no more data to read, so reset sockfd again
if( errno == EAGAIN )
{
reset_oneshot( epollfd, sockfd );
printf( "read later
" );
break;
}
}
else
{
printf( "get content: %s
", buf );
sleep( 5 );
}
}
printf( "end thread receiving data on fd: %d
", sockfd );
}
int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number
", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
int ret = 0;
struct sockaddr_in address;
bzero( &address, sizeof( address ) );
address.sin_family = AF_INET;
inet_pton( AF_INET, ip, &address.sin_addr );
address.sin_port = htons( port );
int listenfd = socket( PF_INET, SOCK_STREAM, 0 );
assert( listenfd >= 0 );
ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );
assert( ret != -1 );
ret = listen( listenfd, 5 );
assert( ret != -1 );
epoll_event events[ MAX_EVENT_NUMBER ];
int epollfd = epoll_create( 5 );
assert( epollfd != -1 );
addfd( epollfd, listenfd, false );
while( 1 )
{
int ret = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );
if ( ret < 0 )
{
printf( "epoll failure
" );
break;
}
for ( int i = 0; i < ret; i++ )
{
int sockfd = events[i].data.fd;
if ( sockfd == listenfd )
{
struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof( client_address );
int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
addfd( epollfd, connfd, true );
}
else if ( events[i].events & EPOLLIN )
{
pthread_t thread;
fds fds_for_new_worker;
fds_for_new_worker.epollfd = epollfd;
fds_for_new_worker.sockfd = sockfd;
pthread_create( &thread, NULL, worker, ( void* )&fds_for_new_worker );
}
else
{
printf( "something else happened
" );
}
}
}
close( listenfd );
return 0;
}