Originally Published:
Tuesday, 30 November 1999 |
Author:
Daniel Drown |
Published to:
develop_articles_tutorials/Development Tutorials |
Page:
1/1 - [Std View]
|
A Simple Internet Client Application
Daniel Drown shows how to open a connection to a network services. The following article requires basic C knowledge, and file I/O experience.
|
Simple Internet client program - by
Dan Drown
Required programming experience: compiling a program, basic C experience, file I/O experience.
Summary: An introduction to opening a connection to a network service.
Functions used:
socket(2) - create an endpoint for communication
connect(2) - initiate a connection on a socket
read(2) - read from a file descriptor
write(2) - write to a file descriptor
perror(3) - print a system error message
gethostbyname(3) - get the IP for a host
herror(3) - print a resolver error message (marked as obsolete???)
exit(3) - cause normal program termination
memcpy(3) - copy a memory area
htons(3) - convert a short integer from host byte order to network
byte order.
close(2) - closes a file descriptor
see also:
ip(4)
/* Simple Internet client program - by Dan Drown <abob@linux.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* LINUX.COM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h> /* for socket,connect */
#include <sys/socket.h> /* for socket,connect */
#include <netinet/in.h> /* for htons */
#include <netdb.h> /* for gethostbyname */
#include <string.h> /* for memcpy */
#include <stdio.h> /* for perror */
#include <stdlib.h> /* for exit */
#include <unistd.h> /* for read,write */
void build_inet_addr(struct sockaddr_in *addr, const char *hostname, unsigned short int port);
int connect_inet_addr(const char *hostname, unsigned short int port);
int main()
{
int socket_descriptor, returnval;
char str[80];
socket_descriptor=connect_inet_addr("localhost", 80);
strcpy(str, "HEAD / HTTP/1.0\r\n\r\n");
returnval = write(socket_descriptor, str, strlen(str));
if(returnval < 0)
{
/* write returns -1 on error */
perror("write(..) error");
exit(1);
}
if(returnval < strlen(str))
{
/* I'm not dealing with this error, regular programs should. */
fprintf(stderr, "the write was short\n");
exit(1);
}
while((returnval = read(socket_descriptor, str, 80)) > 0)
/* write everything to stdout. */
write(STDOUT_FILENO, str, returnval);
/* it will be closed anyway when we exit */
close(socket_descriptor);
/* just to be pedantic... */
return;
}
/* IN: hostname, port
* OUT: socket descriptor
* connects to the hostname:port specified. upon error, it prints a message
* and calls exit(2).
*/
int connect_inet_addr(const char *hostname, unsigned short int port)
{
int inet_socket; /* socket descriptor */
struct sockaddr_in inet_address; /* IP/port of the remote host to connect to */
build_inet_addr(&inet_address, hostname, port);
/* socket(domain, type, protocol) */
inet_socket = socket(PF_INET, SOCK_STREAM, 0);
/* domain is PF_INET(internet/IPv4 domain) *
* type is SOCK_STREAM(tcp) *
* protocol is 0(only one SOCK_STREAM type in the PF_INET domain
*/
if (inet_socket < 0)
{
/* socket returns -1 on error */
perror("socket(PF_INET, SOCK_STREAM, 0) error");
exit(2);
}
/* connect(sockfd, serv_addr, addrlen) */
if(connect(inet_socket, (struct sockaddr *)&inet_address, sizeof(struct sockaddr_in)) < 0)
{
/* connect returns -1 on error */
perror("connect(...) error");
exit(2);
}
return inet_socket;
}
/* IN: hostname, port
* OUT: struct sockaddr_in is setup
* sets up the sockaddr_in structure. upon error, it prints a message and
* calls exit(3).
*/
void build_inet_addr(struct sockaddr_in *addr, const char *hostname, unsigned short int port)
{
struct hostent *host_entry;
/* gethostbyname(name) */
host_entry = gethostbyname(hostname);
if(host_entry == NULL)
{
/* gethostbyname returns NULL on error */
herror("gethostbyname failed");
exit(3);
}
/* memcpy(dest, src, length) */
memcpy(&addr->sin_addr.s_addr, host_entry->h_addr_list[0], host_entry->h_length);
/* copy the address to the sockaddr_in struct. */
/* set the family type (PF_INET) */
addr->sin_family = host_entry->h_addrtype;
/* addr->sin_port = port won't work because they are different byte
* orders
*/
addr->sin_port = htons(port);
/* just to be pedantic... */
return;
}