[net.unix-wizards] a problem with sockets

moi%brandeis.csnet@CSNET-RELAY.arpa (07/20/86)

	I was interested in writing a server that would collect messages
	from processes running on several machines connected via
	Ethernet.  I wrote both the server and a simple client process
	that would attemp to send a message to the server.  The problem
	I've been unable to solve is this: when both the server and the
	client are on the same machine, the client is able to reach the
	server and send its message.  When the client is on a different
	machine from the server, the client call to "connect()" fails
	with a "connection refused" error.  I tried running both
	processes with root privileges (in case there was some protection
	problem I wasn't aware of), and I checked the "/etc/hosts" file
	to make sure each machine knew about the other.  Any ideas?
	
	Our network consists of 2 VAX 780s running UNIX 4.2BSD and 4
	SUNs running SUN UNIX 3.0.  I should mention that the problem
	seems to occur only when one of the machines is a SUN and the
	other a VAX; when both processes are on VAXes only, or on SUNs
	only, they work just fine.

	Any help would be greatly appreciated.

					Moises Lejter
					CSnet: moi%brandeis@csnet-relay

P.S.	The two programs I wrote are:

----- server -----

/*
 * server:
 */

#include <sys/types.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/errno.h>

#define MAX_QUEUE_SIZE	5		/* max # entries in socket queue*/
#define MAX_HOST_NAME	16		/* max # chars in host name	*/

#define INET_PORT	2052		/* internet port number		*/
#define ERROR		-1		/* return value on error	*/
#define LOOP		while (1)	/* loop forever			*/
#define BUFFER_SIZE	1024		/* Internet buffer size		*/


char host[ MAX_HOST_NAME ];		/* host name			*/
struct sockaddr_in inet_host;		/* Internet address of host	*/
struct sockaddr_in client;		/* Internet address of client	*/
struct hostent *host_data;		/* network data on host		*/
int server_socket;			/* server listener socket	*/
int conn_socket;			/* server connection socket	*/
int errno;				/* global system error code	*/
char buffer[ BUFFER_SIZE ];		/* i/o buffer			*/


void sys_error( msg )
    char *msg;
    {
	perror( msg );
	exit( -1 );
    }


void accept_client()
    {
	int client_size = sizeof( client );
	struct hostent *client_name;

	conn_socket = accept( server_socket, & client,
			      & client_size );
	if (conn_socket < 0) sys_error("server: accept");
	read( conn_socket, buffer, sizeof( buffer ));
	printf( "server: read: %s\n", buffer );
	close( conn_socket );
    }


main( argc, argv )
    int argc;
    char *argv[];
    {
	gethostname( host, MAX_HOST_NAME );
	host_data = gethostbyname( host );
	bzero( & inet_host, sizeof( inet_host ));
	bcopy( host_data->h_addr, &inet_host.sin_addr, host_data->h_length );
	inet_host.sin_family = AF_INET;
	inet_host.sin_port = INET_PORT;

	if ((server_socket = socket( AF_INET, SOCK_STREAM, 0 )) < 0)
	    sys_error( "server: socket" );
	else if (bind( server_socket, & inet_host, sizeof( inet_host )) < 0)
	    sys_error( "server: bind" );
	else if (listen( server_socket, MAX_QUEUE_SIZE ) < 0)
	    sys_error( "server: listen" );

	LOOP accept_client();
    }

-----end of server-----
-----client-----
/*
 * client process
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define INET_PORT	2052		/* internet port number		*/

struct sockaddr_in inet_name;		/* Internet address of host	*/
struct hostent *remote_host;		/* info about remote host	*/
int connection;				/* communications socket	*/

void sys_error( msg )
    char *msg;
    {
	perror( msg );
	exit( -1 );
    }


main( argc, argv )
    int argc;
    char *argv[];
    {
	remote_host = gethostbyname( argv[ 1 ] );
	bzero( & inet_name, sizeof( inet_name ));
	bcopy( remote_host->h_addr, & inet_name.sin_addr,
	       remote_host->h_length );
	inet_name.sin_family = remote_host->h_addrtype;
	inet_name.sin_port = INET_PORT;

	connection = socket( AF_INET, SOCK_STREAM, 0 );
	if (connect( connection, & inet_name, sizeof( inet_name )) < 0)
	    sys_error( "client: connect" );
	else {
		write( connection, "hello there", 12 );
		shutdown( connection );
		close( connection );
	}
    }
-----end of client-----

bzs@BU-CS.BU.EDU (07/20/86)

>From: Moises Lejter
>...When the client is on a different
>machine from the server, the client call to "connect()" fails
>with a "connection refused" error...
>...I should mention that the problem
>seems to occur only when one of the machines is a SUN and the
>other a VAX; when both processes are on VAXes only, or on SUNs
>only, they work just fine.

In the server and client's main()s change:

	inet_host.sin_port = INET_PORT;
to
	inet_host.sin_port = htons(INET_PORT);

Remember that a VAX is byte-swapped relative to the network,
the above macro fixes it on the VAX (and leaves it alone
on the SUN, it's a no-op.) You got "connection refused" because
you were trying to rendezvous on the wrong socket number (you
get that message if there is noone listening on the requested
remote socket.) See 'man byteorder' for further details.

	-Barry Shein, Boston University