The client side was shown in the example in section "Connection-oriented server for AF_INET / AF_INET6". You can clearly see the separate, asymmetric roles of the client and server in the program code. The server waits as a passive instance for connection requests from the client, whereas the client initiates a connection as the active instance.
The steps executed by the remote login client process are looked at more closely in the following sections. In the example programs, the client uses the following socket interface functions:
socket(): create socket
gethostbyname() / getipnodebyname(): get the host name entry
connect(): request a connection on the socket
send(): write data to the socket
soc_close(): close socket
Example: Connection-oriented client for AF_INET
#include <stdio.h> #include <sys.types.h> #include <sys.socket.h> #include <netinet.in.h> #include <netdb.h> #include <sys.uio.h> main(argc, argv) int argc; char *argv[]; { #define TESTPORT 2222 #define DATA "Here's the message ..." int sock, length; struct sockaddr_in client; struct hostent *hp; char buf[1024]; /* Create socket */ sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("Create stream socket"); exit(1); } /* Fill in the address structure */ client.sin_family = AF_INET; client.sin_port = htons(TESTPORT); hp = gethostbyname(argv[1]); if (hp == NULL) { fprintf(stderr,"%s: unknown host\n", argv[1]); exit(1); } memcpy((char *) &server.sin_addr, (char *)hp->h_addr, hp->h_length); /* Start the connection */ if ( connect(sock, &server, sizeof(client) ) < 0 ) { perror("Connect stream socket"); exit(1); } /* Write to the socket */ if ( send(sock, DATA, sizeof DATA, 0) < 0) { perror("Write on stream socket"); exit(1); } soc_close(sock); }
Example: Connection-oriented client for AF_INET6
#include <stdio.h> #include <sys.types.h> #include <sys.socket.h> #include <netinet.in.h> #include <netdb.h> #include <sys.uio.h> main(argc, argv) int argc; char *argv[]; { #define TESTPORT 2222 #define DATA "Here's the message ..." int sock, length; int error_num; struct sockaddr_in6 client; struct hostent *hp; char buf[1024]; /* Create socket */ sock = socket(AF_INET6, SOCK_STREAM, 0); if (sock < 0) { perror("Create stream socket"); exit(1); } /* Fill in the address structure */ client.sin6_family = AF_INET6; client.sin6_port = htons(TESTPORT); hp = getipnodebyname(argv[1], AF_INET6, 0, &error_num); if ((hp == NULL) || (error_num != NETDB_SUCCESS)) { fprintf(stderr,"%s: unknown host\n", argv[1]); exit(1); } memcpy((char *) &CLIENT.sin6_addr, (char *)hp->h_addr, hp->h_length); /* Release the dynamic memory of hostent */ freehostent (hp); /* Start connection */ if ( connect(sock, &client, sizeof(client) ) < 0 ) { perror("Connect stream socket"); exit(1); } /* Write to the socket */ if ( send(sock, DATA, sizeof DATA, 0) < 0) { perror("Write on stream socket"); exit(1); } soc_close(sock); }
The client creates a communications endpoint (socket) and the corresponding descriptor with the socket() function.The following steps are executed in the program examples for AF_INET and AF_INET6:
The client queries the address of the host with gethostbyname() (only for AF_INET).The host name is passed as a parameter.
The client determines the IPv6 address of the host name passed as a parameter with getipnodebyname(). This new function could also be used for the AF_INET example. A connection must then be set up to the server for the desired host. The client initializes the address structure for this purpose.The connection is set up with connect().
After connection setup, data is written to the socket with the send() function.
The created socket is closed with the soc_close() function.