| Previous | Contents | Index |
Obtaining socket information is useful if your program has management
functions, or if you have a complex program that uses multiple
connections you need to track.
2.7.1 Getting Socket Information (Sockets API)
You can use any of the following Sockets API functions to get socket information:
Example 2-11 shows a TCP server using the getpeername() function to get the remote IP address and port number associated with a socket.
| Example 2-11 Getting Socket Information (Sockets API) |
|---|
#include <in.h> /* define internet related constants, */
/* functions, and structures */
#include <inet.h> /* define network address info */
#include <netdb.h> /* define network database library info */
#include <socket.h> /* define BSD socket api */
#include <stdio.h> /* define standard i/o functions */
#include <stdlib.h> /* define standard library functions */
#include <string.h> /* define string handling functions */
#define SERV_BACKLOG 1 /* server backlog */
#define SERV_PORTNUM 12345 /* server port number */
int main( void )
{
int conn_sockfd; /* connection socket descriptor */
int listen_sockfd; /* listen socket descriptor */
unsigned int cli_addrlen; /* returned length of client socket */
/* address structure */
struct sockaddr_in cli_addr; /* client socket address structure */
struct sockaddr_in serv_addr; /* server socket address structure */
/*
* initialize server's socket address structure
*/
memset( &serv_addr, 0, sizeof(serv_addr) );
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons( SERV_PORTNUM );
serv_addr.sin_addr.s_addr = INADDR_ANY;
/*
* create a listen socket
*/
if ( (listen_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
perror( "Failed to create socket" );
exit( EXIT_FAILURE );
}
/*
* bind server's ip address and port number to listen socket
*/
if ( bind(listen_sockfd,
(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
{
perror( "Failed to bind socket" );
exit( EXIT_FAILURE );
}
/*
* set socket as a listen socket
*/
if ( listen(listen_sockfd, SERV_BACKLOG) < 0 )
{
perror( "Failed to set socket passive" );
exit( EXIT_FAILURE );
}
/*
* accept connection from a client
*/
printf( "Waiting for a client connection on port: %d\n",
ntohs(serv_addr.sin_port)
);
conn_sockfd = accept( listen_sockfd, (struct sockaddr *) 0, 0 );
if ( conn_sockfd < 0 )
{
perror( "Failed to accept client connection" );
exit( EXIT_FAILURE );
}
/*
* log client connection request
*/
cli_addrlen = sizeof(cli_addr);
memset( &cli_addr, 0, sizeof(cli_addr) );
if ( getpeername(conn_sockfd (1),
(struct sockaddr * ) &cli_addr, (2) &cli_addrlen (3)) < 0 )
{
perror( "Failed to get client name" );
exit( EXIT_FAILURE );
}
printf( "Accepted connection from host: %s, port: %d\n",
inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port) (4)
);
exit( EXIT_SUCCESS );
}
|
To obtain information about the parts of a socket, use the $QIO system service with IO$_SENSEMODE to get socket information.
Example 2-12 shows a TCP client using the IO$_SENSEMODE function to get the client's IP address and port number.
| Example 2-12 Getting Socket Information (System Services) |
|---|
#include <descrip.h> /* define OpenVMS descriptors */
#include <efndef.h> /* define 'EFN$C_ENF' event flag */
#include <in.h> /* define internet related constants, */
<valid_break>
/* functions, and structures */
#include <inet.h> /* define network address info */
#include <iodef.h> /* define i/o function codes */
#include <netdb.h> /* define network database library info */
#include <ssdef.h> /* define system service status codes */
#include <starlet.h> /* define system service calls */
#include <stdio.h> /* define standard i/o functions */
#include <stdlib.h> /* define standard library functions */
#include <string.h> /* define string handling functions */
#include <stsdef.h> /* define condition value fields */
#include <tcpip$inetdef.h> /* define tcp/ip network constants, */
/* structures, and functions */
#define SERV_BACKLOG 1 /* server backlog */
#define SERV_PORTNUM 12345 /* server port number */
struct iosb
{ /* i/o status block */
unsigned short status; /* i/o completion status */
unsigned short bytcnt; /* bytes transferred if read/write */
void *details; /* address of buffer or parameter */
};
struct itemlst_2
{ /* item-list 2 descriptor/element */
unsigned short length; /* length */
unsigned short type; /* parameter type */
void *address; /* address of item list */
};
struct itemlst_3
{ /* item-list 3 descriptor/element */
unsigned short length; /* length */
unsigned short type; /* parameter type */
void *address; /* address of item list */
unsigned int *retlen; /* address of returned length */
};
struct sockchar
{ /* socket characteristics */
unsigned short prot; /* protocol */
unsigned char type; /* type */
unsigned char af; /* address format */
};
int main( void )
{
struct iosb iosb; /* i/o status block */
unsigned int status; /* system service return status */
unsigned short conn_channel; /* connect inet device i/o channel */
unsigned short listen_channel; /* listen inet device i/o channel */
struct sockchar listen_sockchar; /* listen socket characteristics */
unsigned int cli_addrlen; /* returned length of client socket */
/* address structure */
struct sockaddr_in cli_addr; /* client socket address structure */
struct itemlst_3 cli_itemlst; /* client socket address item-list */
struct sockaddr_in serv_addr; /* server socket address structure */
struct itemlst_2 serv_itemlst; /* server socket address item-list */
$DESCRIPTOR( inet_device, /* string descriptor with logical */
"TCPIP$DEVICE:" ); /* name of network pseudodevice */
/*
* initialize socket characteristics
*/
listen_sockchar.prot = TCPIP$C_TCP;
listen_sockchar.type = TCPIP$C_STREAM;
listen_sockchar.af = TCPIP$C_AF_INET;
/*
* initialize client's item-list descriptor
*/
cli_itemlst.length = sizeof( cli_addr );
cli_itemlst.type = TCPIP$C_SOCK_NAME;
cli_itemlst.address = &cli_addr;
cli_itemlst.retlen = &cli_addrlen;
/*
* initialize server's item-list descriptor
*/
serv_itemlst.length = sizeof( serv_addr );
serv_itemlst.type = TCPIP$C_SOCK_NAME;
serv_itemlst.address = &serv_addr;
/*
* initialize server's socket address structure
*/
memset( &serv_addr, 0, sizeof(serv_addr) );
serv_addr.sin_family = TCPIP$C_AF_INET;
serv_addr.sin_port = htons( SERV_PORTNUM );
serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY;
/*
* assign i/o channels to network device
*/
status = sys$assign( &inet_device, /* device name */
&listen_channel, /* i/o channel */
0, /* access mode */
0 /* not used */
);
if ( status & STS$M_SUCCESS )
status = sys$assign( &inet_device, /* device name */
&conn_channel, /* i/o channel */
0, /* access mode */
0 /* not used */
);
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to assign i/o channel(s)\n" );
exit( status );
}
/*
* create a listen socket
*/
status = sys$qiow( EFN$C_ENF, /* event flag */
listen_channel, /* i/o channel */
IO$_SETMODE, /* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
&listen_sockchar, /* p1 - socket characteristics */
0, /* p2 */
0, /* p3 */
0, /* p4 */
0, /* p5 */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to create socket\n" );
exit( status );
}
/*
* bind server's ip address and port number to listen socket
*/
status = sys$qiow( EFN$C_ENF, /* event flag */
listen_channel, /* i/o channel */
IO$_SETMODE, /* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
0, /* p1 */
0, /* p2 */
&serv_itemlst, /* p3 - local socket name */
0, /* p4 */
0, /* p5 */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to bind socket\n" );
exit( status );
}
/*
* set socket as a listen socket
*/
status = sys$qiow( EFN$C_ENF, /* event flag */
listen_channel, /* i/o channel */
IO$_SETMODE, /* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
0, /* p1 */
0, /* p2 */
0, /* p3 */
SERV_BACKLOG, /* p4 - connection backlog */
0, /* p5 */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to set socket passive\n" );
exit( status );
}
/*
* accept connection from a client
*/
printf( "Waiting for a client connection on port: %d\n",
ntohs(serv_addr.sin_port)
);
status = sys$qiow( EFN$C_ENF, /* event flag */
listen_channel, /* i/o channel */
IO$_ACCESS|IO$M_ACCEPT,
/* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
0, /* p1 */
0, /* p2 */
0, /* p3 */
&conn_channel, /* p4 - i/o channel for new */
/* connection */
0, /* p5 */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to accept client connection\n" );
exit( status );
}
/*
* log client connection request
*/
memset( &cli_addr, 0, sizeof(cli_addr) );
status = sys$qiow( EFN$C_ENF, /* event flag */
conn_channel, /* i/o channel */
IO$_SENSEMODE, /* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
0, /* p1 */
0, /* p2 */
0, /* p3 */
&cli_itemlst, /* p4 - peer socket name */
0, /* p5 */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to get client name\n" );
exit( status );
}
printf( "Accepted connection from host: %s, port: %d\n",
inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)
);
exit( EXIT_SUCCESS );
}
|
With TCP/IP Services, you use the
setsockopt()
function to set binary socket options and socket options that return a
value. Calls to
setsockopt()
specifying unsupported options return an error code of
ENOPROTOOPT
.
2.8.1 Setting Socket Options (Sockets API)
Example 2-13 shows a TCP server using the setsockopt () function to set the SO_REUSEADDR option.
| Example 2-13 Setting Socket Options (Sockets API) |
|---|
#include <in.h> /* define internet related constants, */
/* functions, and structures */
#include <inet.h> /* define network address info */
#include <netdb.h> /* define network database library info */
#include <socket.h> /* define BSD socket api */
#include <stdio.h> /* define standard i/o functions */
#include <stdlib.h> /* define standard library functions */
#include <string.h> /* define string handling functions */
#define SERV_BACKLOG 1 /* server backlog */
#define SERV_PORTNUM 12345 /* server port number */
int main( void )
{
int optval = 1; /* SO_REUSEADDR's option value (on) */
int conn_sockfd; /* connection socket descriptor */
int listen_sockfd; /* listen socket descriptor */
unsigned int cli_addrlen; /* returned length of client socket */
/* address structure */
struct sockaddr_in cli_addr; /* client socket address structure */
struct sockaddr_in serv_addr; /* server socket address structure */
/*
* initialize server's socket address structure
*/
memset( &serv_addr, 0, sizeof(serv_addr) );
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons( SERV_PORTNUM );
serv_addr.sin_addr.s_addr = INADDR_ANY;
/*
* create a listen socket
*/
if ( (listen_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
perror( "Failed to create socket" );
exit( EXIT_FAILURE );
}
/*
* bind server's ip address and port number to listen socket
*/
if ( setsockopt(listen_sockfd, (1)
SOL_SOCKET (2)
, SO_REUSEADDR (3)
, &optval (4)
, sizeof(optval) (5)
) < 0 )
{
perror( "Failed to set socket option" );
exit( EXIT_FAILURE );
}
if ( bind(listen_sockfd,
(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0 )
{
perror( "Failed to bind socket" );
exit( EXIT_FAILURE );
}
/*
* set socket as a listen socket
*/
if ( listen(listen_sockfd, SERV_BACKLOG) < 0 )
{
perror( "Failed to set socket passive" );
exit( EXIT_FAILURE );
}
/*
* accept connection from a client
*/
printf( "Waiting for a client connection on port: %d\n",
ntohs(serv_addr.sin_port)
);
conn_sockfd = accept( listen_sockfd, (struct sockaddr *) 0, 0 );
if ( conn_sockfd < 0 )
{
perror( "Failed to accept client connection" );
exit( EXIT_FAILURE );
}
/*
* log client connection request
*/
cli_addrlen = sizeof(cli_addr);
memset( &cli_addr, 0, sizeof(cli_addr) );
if ( getpeername(conn_sockfd,
(struct sockaddr *) &cli_addr, &cli_addrlen) < 0 )
{
perror( "Failed to get client name" );
exit( EXIT_FAILURE );
}
printf( "Accepted connection from host: %s, port: %d\n",
inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)
);
exit( EXIT_SUCCESS );
}
|
2.8.2 Setting Socket Options (System Services)
Example 2-14 shows how to set socket options using $QIO system
services.
| Example 2-14 Setting Socket Options (System Services) |
|---|
#include <descrip.h> /* define OpenVMS descriptors */
#include <efndef.h> /* define 'EFN$C_ENF' event flag */
#include <in.h> /* define internet related constants, */
/* functions, and structures */
#include <inet.h> /* define network address info */
#include <iodef.h> /* define i/o function codes */
#include <netdb.h> /* define network database library info */
#include <ssdef.h> /* define system service status codes */
#include <starlet.h> /* define system service calls */
#include <stdio.h> /* define standard i/o functions */
#include <stdlib.h> /* define standard library functions */
#include <string.h> /* define string handling functions */
#include <stsdef.h> /* define condition value fields */
#include <tcpip$inetdef.h> /* define tcp/ip network constants, */
/* structures, and functions */
#define SERV_BACKLOG 1 /* server backlog */
#define SERV_PORTNUM 12345 /* server port number */
struct iosb
{ /* i/o status block */
unsigned short status; /* i/o completion status */
unsigned short bytcnt; /* bytes transferred if read/write */
void *details; /* address of buffer or parameter */
};
struct itemlst_2
{ /* item-list 2 descriptor/element */
unsigned short length; /* length */
unsigned short type; /* parameter type */
void *address; /* address of item list */
};
struct itemlst_3
{ /* item-list 3 descriptor/element */
unsigned short length; /* length */
unsigned short type; /* parameter type */
void *address; /* address of item list */
unsigned int *retlen; /* address of returned length */
};
struct sockchar
{ /* socket characteristics */
unsigned short prot; /* protocol */
unsigned char type; /* type */
unsigned char af; /* address format */
};
int main( void )
{
int optval = 1; /* reuseaddr option value (on) */
struct iosb iosb; /* i/o status block */
unsigned int status; /* system service return status */
unsigned short conn_channel; /* connect inet device i/o channel */
unsigned short listen_channel; /* listen inet device i/o channel */
struct sockchar listen_sockchar; /* listen socket characteristics */
unsigned int cli_addrlen; /* returned length of client socket */
/* address structure */
struct sockaddr_in cli_addr; /* client socket address structure */
struct itemlst_3 cli_itemlst; /* client socket address item-list */
struct sockaddr_in serv_addr; /* server socket address structure */
struct itemlst_2 serv_itemlst; /* server socket address item-list */
struct itemlst_2 sockopt_itemlst; /* server socket option item-list */
struct itemlst_2 reuseaddr_itemlst; /* reuseaddr option item-list */
$DESCRIPTOR( inet_device, /* string descriptor with logical */
"TCPIP$DEVICE:" ); /* name of network pseudodevice */
/*
* initialize socket characteristics
*/
listen_sockchar.prot = TCPIP$C_TCP;
listen_sockchar.type = TCPIP$C_STREAM;
listen_sockchar.af = TCPIP$C_AF_INET;
/*
* initialize reuseaddr's item-list element
*/
reuseaddr_itemlst.length = sizeof( optval );
reuseaddr_itemlst.type = TCPIP$C_REUSEADDR;
reuseaddr_itemlst.address = &optval;
/*
* initialize setsockopt's item-list descriptor
*/
sockopt_itemlst.length = sizeof( reuseaddr_itemlst );
sockopt_itemlst.type = TCPIP$C_SOCKOPT;
sockopt_itemlst.address = &reuseaddr_itemlst;
/*
* initialize client's item-list descriptor
*/
cli_itemlst.length = sizeof( cli_addr );
cli_itemlst.type = TCPIP$C_SOCK_NAME;
cli_itemlst.address = &cli_addr;
cli_itemlst.retlen = &cli_addrlen;
/*
* initialize server's item-list descriptor
*/
serv_itemlst.length = sizeof( serv_addr );
serv_itemlst.type = TCPIP$C_SOCK_NAME;
serv_itemlst.address = &serv_addr;
/*
* initialize server's socket address structure
*/
memset( &serv_addr, 0, sizeof(serv_addr) );
serv_addr.sin_family = TCPIP$C_AF_INET;
serv_addr.sin_port = htons( SERV_PORTNUM );
serv_addr.sin_addr.s_addr = TCPIP$C_INADDR_ANY;
/*
* assign i/o channels to network device
*/
status = sys$assign( &inet_device, /* device name */
&listen_channel, /* i/o channel */
0, /* access mode */
0 /* not used */
);
if ( status & STS$M_SUCCESS )
status = sys$assign( &inet_device, /* device name */
&conn_channel, /* i/o channel */
0, /* access mode */
0 /* not used */
);
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to assign i/o channel(s)\n" );
exit( status );
}
/*
* create a listen socket
*/
status = sys$qiow( EFN$C_ENF, /* event flag */
listen_channel, /* i/o channel */
IO$_SETMODE, /* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
&listen_sockchar, /* p1 - socket characteristics */
0, /* p2 */
0, /* p3 */
0, /* p4 */
0, /* p5 */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to create socket\n" );
exit( status );
}
/*
* bind server's ip address and port number to listen socket
*/
status = sys$qiow( EFN$C_ENF, /* event flag */
listen_channel, /* i/o channel */
IO$_SETMODE, /* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
0, /* p1 */
0, /* p2 */
0, /* p3 */
0, /* p4 */
&sockopt_itemlst, /* p5 - socket options */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to set socket option\n" );
exit( status );
}
status = sys$qiow( EFN$C_ENF, /* event flag */
listen_channel, /* i/o channel */
IO$_SETMODE, /* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
0, /* p1 */
0, /* p2 */
&serv_itemlst, /* p3 - local socket name */
0, /* p4 */
0, /* p5 */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to bind socket\n" );
exit( status );
}
/*
* set socket as a listen socket
*/
status = sys$qiow( EFN$C_ENF, /* event flag */
listen_channel, /* i/o channel */
IO$_SETMODE, /* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
0, /* p1 */
0, /* p2 */
0, /* p3 */
SERV_BACKLOG, /* p4 - connection backlog */
0, /* p5 */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to set socket passive\n" );
exit( status );
}
/*
* accept connection from a client
*/
printf( "Waiting for a client connection on port: %d\n",
ntohs(serv_addr.sin_port)
);
status = sys$qiow( EFN$C_ENF, /* event flag */
listen_channel, /* i/o channel */
IO$_ACCESS|IO$M_ACCEPT,
/* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
0, /* p1 */
0, /* p2 */
0, /* p3 */
&conn_channel, /* p4 - i/o channel for new */
/* connection */
0, /* p5 */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to accept client connection\n" );
exit( status );
}
/*
* log client connection request
*/
memset( &cli_addr, 0, sizeof(cli_addr) );
status = sys$qiow( EFN$C_ENF, /* event flag */
conn_channel, /* i/o channel */
IO$_SENSEMODE, /* i/o function code */
&iosb, /* i/o status block */
0, /* ast service routine */
0, /* ast parameter */
0, /* p1 */
0, /* p2 */
0, /* p3 */
&cli_itemlst, /* p4 - peer socket name */
0, /* p5 */
0 /* p6 */
);
if ( status & STS$M_SUCCESS )
status = iosb.status;
if ( !(status & STS$M_SUCCESS) )
{
printf( "Failed to get client name\n" );
exit( status );
}
printf( "Accepted connection from host: %s, port: %d\n",
inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)
);
exit( EXIT_SUCCESS );
}
|
| Previous | Next | Contents | Index |