linux socket编程示例
#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...\n");
} static void handle_int(int sig) // ctrl+c; will triggle this signal
{
printf("signal SIGINT catched...\n");
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\n", 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...\n"); //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...\n"); 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\n", 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...\n"); ret = listen( sock, 5 );
assert( ret != -1 );
printf("AFTER listen...\n"); //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...\n"); if ( connfd < 0 )
{
printf( "errno is: %d\n", 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\n",
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\n", 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...\n"); struct sockaddr_in client;
socklen_t client_addrlength = sizeof( client );
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
printf("after accept...\n");
if ( connfd < 0 )
{
printf( "errno is: %d\n", errno );
}
else
{
char buffer[ BUF_SIZE ]; memset( buffer, '\0', BUF_SIZE );
ret = recv( connfd, buffer, BUF_SIZE-1, 0 );
printf( "got %d bytes of normal data '%s'\n", ret, buffer ); memset( buffer, '\0', 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'\n", ret, buffer ); memset( buffer, '\0', BUF_SIZE );
ret = recv( connfd, buffer, BUF_SIZE-1, 0 );
printf( "got %d bytes of normal data '%s'\n", 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\n", 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\n", sendbuf ); if ( connect( sock, ( struct sockaddr* )&server_address, sizeof( server_address ) ) != -1 )
{
//
printf("call getsockname ...\n");
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\n",
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\n", 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...\n"); ret = listen( sock, 5 );
assert( ret != -1 );
printf("AFTER listen...\n"); //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...\n"); if ( connfd < 0 )
{
printf( "errno is: %d\n", 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\n",
inet_ntop( AF_INET, &client.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( client.sin_port ) ); //
printf("call getsockname ...\n");
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\n", inet_ntop( AF_INET, &local_address.sin_addr, local, INET_ADDRSTRLEN ), ntohs( local_address.sin_port ) );
}
else
printf("getsockname on connfd fail...\n"); 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\n", inet_ntop( AF_INET, &local_address.sin_addr, local1, INET_ADDRSTRLEN ), ntohs( local_address.sin_port ) ); }
else
printf("getpeername on connfd fail...\n"); 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\n", 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\n", 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\n", 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\n", recvbuf); /////!!!
int len = sizeof( recvbuf );
printf("len is %d\n", 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\n", 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\n", errno );
}
else
{
char buffer[ BUFFER_SIZE ];
memset( buffer, '\0', BUFFER_SIZE );
while( recv( connfd, buffer, BUFFER_SIZE-1, 0 ) > 0 )
{
printf("%s\n", 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\n");
return -1;
}
printf("hostName: %s\n" , 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\n", 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\n",
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\n", errno );
perror("connect error:");
assert( result != -1 ); char buffer[128];
result = read( sockfd, buffer, sizeof( buffer ) );
assert( result > 0 );
buffer[ result ] = '\0';
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\n", 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\n", errno );
}
else
{
close( STDOUT_FILENO );
dup( connfd );
printf( "abcd\n" ); //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\n", 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\n", errno );
}
else
{
char header_buf[ BUFFER_SIZE ];
memset( header_buf, '\0', 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, '\0', 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\r\n", "HTTP/1.1", status_line[0] );
len += ret;
ret = snprintf( header_buf + len, BUFFER_SIZE-1-len,
"Content-Length: %d\r\n", (int)file_stat.st_size );
len += ret;
ret = snprintf( header_buf + len, BUFFER_SIZE-1-len, "%s", "\r\n" );
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\r\n", "HTTP/1.1", status_line[1] );
len += ret;
ret = snprintf( header_buf + len, BUFFER_SIZE-1-len, "%s", "\r\n" );
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\n", 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\n", 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\n", 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\n", 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>\n", 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\n", 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\n", basename( argv[0] ) );
return 1;
}
const char* ip = argv[1];
int port = atoi( argv[2] );
printf( "ip is %s and port is %d\n", 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\n", errno );
close( listenfd );
} char remote_addr[INET_ADDRSTRLEN];
printf( "connected with ip: %s and port: %d\n", 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, '\0', 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\n" );
if ( ret < 0 )
{
printf( "selection failure\n" );
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\n", 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\n", 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\n" );
memset( buf, '\0', BUFFER_SIZE );
int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );
if( ret <= 0 )
{
close( sockfd );
continue;
}
printf( "get %d bytes of content: %s\n", ret, buf );
}
else
{
printf( "something else happened \n" );
}
}
} 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\n" );
while( 1 )
{
memset( buf, '\0', BUFFER_SIZE );
int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );
if( ret < 0 )
{
if( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) )
{
printf( "read later\n" );
break;
}
close( sockfd );
break;
}
else if( ret == 0 )
{
close( sockfd );
}
else
{
printf( "get %d bytes of content: %s\n", ret, buf );
}
}
}
else
{
printf( "something else happened \n" );
}
}
} int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number\n", 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\n" );
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\n", sockfd );
char buf[ BUFFER_SIZE ];
memset( buf, '\0', 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\n" );
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\n" );
break;
}
}
else
{
printf( "get content: %s\n", buf );
sleep( 5 );
}
}
printf( "end thread receiving data on fd: %d\n", sockfd );
} int main( int argc, char* argv[] )
{
if( argc <= 2 )
{
printf( "usage: %s ip_address port_number\n", 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\n" );
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 \n" );
}
}
} close( listenfd );
return 0;
}
linux socket编程示例的更多相关文章
- Linux socket编程示例(最简单的TCP和UDP两个例子)
一.socket编程 网络功能是Uinux/Linux的一个重要特点,有着悠久的历史,因此有一个非常固定的编程套路. 基于TCP的网络编程: 基于连接, 在交互过程中, 服务器和客户端要保持连接, 不 ...
- Linux Socket 编程简介
在 TCP/IP 协议中,"IP地址 + TCP或UDP端口号" 可以唯一标识网络通讯中的一个进程,"IP地址+端口号" 就称为 socket.本文以一个简单的 ...
- 多线程Java Socket编程示例
package org.merit.test.socket; import java.io.BufferedReader; import java.io.IOException; import jav ...
- Linux socket 编程中存在的五个隐患
前言: Socket API 是网络应用程序开发中实际应用的标准 API.尽管该 API 简单,但是 开发新手可能会经历一些常见的问题.本文识别一些最常见的隐患并向您显示如何避免它 ...
- Linux Socket编程
“一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...
- Linux Socket编程(不限Linux)【转】
转自:http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html “一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几 ...
- Linux Socket编程(不限Linux)
"一切皆Socket!" 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. --有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信 ...
- Socket详解-Linux Socket编程(不限Linux)
“一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...
- Windows Socket和Linux Socket编程的区别 ZZ
socket相关程序从Windows移植到Linux下需要注意的: 1)头文件 Windows下winsock.h/winsock2.h Linux下sys/socket.h 错误处理:errno.h ...
随机推荐
- shell-拷贝指定目录外其他全部目录
shopt -s extglob if [ ! -d "desdir" ]; then mkdir desdir fi cp -r Oozie/!(.svn*) desdir/
- MySQL binlog导入失败
一个同事问我,说他用innobackupex恢复数据后用mysqlbinlog导入增量数据时,发现数据没有导入进去并且也没有报错. mysqlbinlog /u01/mysql_py/database ...
- MVC 控制器中传递dynamic(对象) 给视图
有时候不想重新定义一个实体,则使用 dynamic 来定义匿名类型. //匿名类型 传递到前台 Model dynamic viewModel = new { UserID = 5016 }; ret ...
- IDEA配置文件的配置文件配置
IDEA配置文件的配置文件配置: 路径 /Applications/IntelliJ IDEA 3.app/Contents/bin/idea.vmoptions (/IntelliJ IDEA 3. ...
- docker 构建带健康检查的redis镜像
=============================================== 2018/11/5_第1次修改 ccb_warlock == ...
- [整理] mysql操作
0.启动mysql(在windows中MySql以服务形式存在,在使用前应确保此服务已经启动) net start mysql 0.5获取版本信息 select version(); 1.root 登 ...
- java 多态缺陷
一,会覆盖私有方法 package object; class Derive extends Polymorphism{ public void f1() { System.out.println(& ...
- Java编程的逻辑 (2) - 赋值
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- 一步一步学习IdentityServer3 (4)
其实上述例子 很多都很找到 但是在实际生态环境中给例子有很多不一样的地方 比如自定已登录界面怎么做? 怎么访问自己的用户数据库实现登录? 怎么在接口中使用,在接口中又怎么实现与Idr3结合授权? 等等 ...
- Java第三阶段学习(十一、Servlet基础、servlet中的方法、servlet的配置、ServletContext对象)
一.Servlet简介 1.什么是servlet: sun公司提供的一套规范(接口),用来处理客户端请求.响应给浏览器的动态资源.但servlet的实质就是java代码,通过java的API动态的向 ...