Previous | Contents | Index |
The recv() function receives data from a connected socket and places it in a buffer, as follows:
To peek at data that is next in the socket receive queue, use the
IO$_READVBLK function of the $QIO system service and use the
TCPIP$C_MSG_PEEK flag. This allows you to use multiple read operations
on the same data.
2.13 Writing Data
For programs that use TCP, data writing occurs after a client program initiates a connection and after the server program accepts the connection. When using UDP, you also have the option of establishing a default peer address with a specific socket, but this is not required for data transfer.
2.13.1 Writing Data (Sockets API)
Example 2-20 shows a TCP server using the
send()
function to transmit data.
Example 2-20 Writing Data (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 */ char buf[] = "Hello, world!"; /* data buffer */ /* * 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, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 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) ); /* * write data to connection */ if ( send(conn_sockfd, (1) buf, (2) sizeof(buf),(3) 0 (4)) < 0 ) { perror( "Failed to write data to connection" ); exit( EXIT_FAILURE ); } printf( "Data sent: %s\n", buf ); exit( EXIT_SUCCESS ); } |
The IO$_WRITEVBLK function of the $QIO system service copies data from the address space of the user's process to system dynamic memory and then transfers the data to an internet host or port.
Example 2-21 shows a TCP server using the IO$_WRITEVBLK function to transmit a single data buffer. The $QIO(IO$_ACCESS|IO$M_ACCEPT) function was previously executed to establish the connection with the client.
Example 2-21 Writing Data (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 */ char buf[] = "Hello, world!"; /* data buffer */ int buflen = sizeof( buf ); /* length of data buffer */ $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) ); /* * write data to connection */ status = sys$qiow( EFN$C_ENF, /* event flag */ conn_channel, /* i/o channel */ IO$_WRITEVBLK, /* i/o function code */ &iosb, /* i/o status block */ 0, /* ast service routine */ 0, /* ast parameter */ buf, /* p1 - buffer address */ buflen, /* p2 - buffer length */ 0, /* p3 */ 0, /* p4 */ 0, /* p5 */ 0 /* p6 */ ); if ( status & STS$M_SUCCESS ) status = iosb.status; if ( !(status & STS$M_SUCCESS) ) { printf( "Failed to write data to connection\n" ); exit( status ); } printf( "Data sent: %s\n", buf ); exit( EXIT_SUCCESS ); } |
You can also specify a list of write buffers by omitting the
p1 and p2 parameters and instead
passing the list of buffers as the p5 parameter. Note
that, when writing a list of buffers, the p5 parameter
is used; when reading a list, the p6 parameter is
used. For more information, see Section 5.5.1.
2.14 Writing OOB Data (TCP Protocol)
If your application uses TCP, you can send OOB data to a remote
process. At the remote process, the message is delivered to the user
through either the data receive or the out-of-band data receive
mechanism. You can write only 1 byte of OOB data at a time.
2.14.1 Writing OOB Data (Sockets API)
To send OOB data to a remote process, use the MSG_OOB flag with the send() , sendmsg() , and sendto() functions.
Example 2-22 shows a TCP server using the MSG_OOB flag with the send() function.
Example 2-22 Writing OOB Data (Sockets API) |
---|
/* This program accepts a connection on TCP port 1234, sends the string, "Hello, world!", waits two seconds, sends an urgent BEL (^G), waits another two seconds, repeats the Hello message, and terminates. */ #include <types.h> #include <in.h> #include <socket.h> #include <unixio.h> #define PORTNUM 123 main() { struct sockaddr_in lcladdr; int r, s, one = 1; char *message = "Hello, world!\r\n", *oob_message = "\007"; memset() lcladdr.sin_family = AF_INET; lcladdr.sin_addr.s_addr = INADDR_ANY; lcladdr.sin_port = htons(PORTNUM); if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) perror("socket"); if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) perror("setsockopt"); if (bind(s, &lcladdr, sizeof(lcladdr))) perror("bind"); if (listen(s, 1)) perror("listen"); if ((r = accept(s, 0, 0)) < 0) perror("accept"); if (send(r, message, strlen(message), 0) != strlen(message)) perror("send"); sleep(2); if (send(r,(1) oob_message,(2) strlen(oob_message),(3) MSG_OOB (4)) != strlen(oob_message)) perror("send"); sleep(2); if (send(r, message, strlen(message), 0) != strlen(message)) perror("send"); sleep(2); if (close(r)) perror("close"); if (close(s)) perror("close"); } |
The send() function is used to send OOB data to a remote socket, as follows:
Previous | Next | Contents | Index |