[comp.unix.questions] Sockets and buffering

petey@umbc5.umbc.ed (08/20/90)

Hello everyone.  I have a problem and have included some code with
questions in it.  Our system is running Ultrix on a Decstation 5400.

What im trying to do is set up a small server that allows multiple
users to telnet into and echo back to them anything they type.

Only problem is, when I do reads and writes, there are extremely bad
delays on the echo.  Ive been attempting to use FD_SET, FD_ISSET
to determine if a socket is ready to be read from or written to.
I dont know if im on the right track.  Basically my problem is
I dont have the documentation explaining how to use
select, FD_ISSET, FD_SET together to accomplish this.

Also, when you set up a socket, everytime you wish to check for new
connections, it seems you have to select on the first available
unused file descriptor.  ex: select(sock+1, etc etc )
When you set up a port number, and someone attempts to connect,
does unix automatically route them to the next available file descriptor?

What if you have 10 fd's used in a row and #5 disconnects,
will unix route the next call to #5, or to #11???

Thanx in advance for the help!!!
Send email to me please...

						Petey

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>

#define TRUE 1
#define FALSE 0
#define MAXHOSTNAME 50
#define BUFSIZE 128

main(argc,argv)  /* argv[1] = port number */
char *argv[];
int argc;
{
        int lastsock; /* accept connect with lastsock */
        int x,y;      /* all purpose counter */
	int sock, length;
	struct sockaddr_in server;
	char buf[BUFSIZE];
	int rval;             /* read return values */
	/****************************************************/
	fd_set in, out;    /* fuzzy on how to CORRECTLY use */
	/****************************************************/
	struct timeval to;
	char myhostname[MAXHOSTNAME+1];
        int temp;

	for(x=0;x<64;x++) close(x);        /* close everything */
	signal(SIGPIPE, SIG_IGN); 
	sock = socket(AF_INET, SOCK_STREAM, 0); /* Create socket */
	if (sock < 0) {
		printf("opening stream socket\n");
		exit(1);
	}
        setsockopt(sock,SOL_SOCKET,SO_REUSEADDR, (char *)&temp,sizeof(temp));
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY; 
	server.sin_port = htons(atoi(argv[1]));
        fcntl(sock,F_SETFL, FNDELAY) == -1;
	if (bind(sock, &server, sizeof(server))) {
		perror("binding stream socket");
		exit(1);
	}
	printf("Socket has port #%d\n", ntohs(server.sin_port));
/*********************** Socket Intialization compelete *******************/
	listen(sock, 5);

	do {    /* main DO loop */
	/*** so when do i use this FD stuff??? */
		FD_ZERO(&in);
		FD_ZERO(&out);
		FD_SET(sock, &in);
		to.tv_sec = 0;
                to.tv_usec =1;
		if (select(sock + 1 , &in, &out,0, &to) < 0) {
			perror("select");
			continue;
		}
		if (FD_ISSET(sock, &in)) {  /* if phone ringing */
                   lastsock = accept(sock, (struct sockaddr *)0, (int *)0);
			if (lastsock == -1)
			     printf("error on accept\n");
                        else {
			     /* non=blocking i/o */
			     fcntl(lastsock,F_SETFL, FNDELAY);
			     fcntl(lastsock,F_SETFD,1);
			     }
		} 
/******************* READ Data from the sockets *****************************/

/**** THE BIG QUESTION !!!! */
     bzero(buf, sizeof(buf));
/* How do I tell when the socket is ready for reading? */
     rval = read(lastsock,buf,sizeof(buf)); 
     if (rval == 0 )   /* If 0, SHUTDOWN THE SOCKET! */ 
       close(lastsock);   /* error reading, close the socket */  
     else 
/* How do i tell when it ready for writing?!!!! */
       rval =  write(lastsock, buf, sizeof(buf));
} while (TRUE);  /* end do loop */
} /* end main */

swfc@ulysses.att.com (Shu-Wie F Chen) (08/20/90)

In article <3791@umbc3.UMBC.EDU>, petey@umbc5.umbc.ed writes:
|>
|>Hello everyone.  I have a problem and have included some code with
|>questions in it.  Our system is running Ultrix on a Decstation 5400.
|>
|>What im trying to do is set up a small server that allows multiple
|>users to telnet into and echo back to them anything they type.
|>
|>Only problem is, when I do reads and writes, there are extremely bad
|>delays on the echo.  Ive been attempting to use FD_SET, FD_ISSET
|>to determine if a socket is ready to be read from or written to.
|>I dont know if im on the right track.  Basically my problem is
|>I dont have the documentation explaining how to use
|>select, FD_ISSET, FD_SET together to accomplish this.

The Ultrix manuals have a section on Intro to Interprocess Communication
or something like that...

|>
|>Also, when you set up a socket, everytime you wish to check for new
|>connections, it seems you have to select on the first available
|>unused file descriptor.  ex: select(sock+1, etc etc )
|>When you set up a port number, and someone attempts to connect,
|>does unix automatically route them to the next available file descriptor?

The first argument to select is the "number of file descriptors to be
checked." For instance, if you specify 32, select will check file
descriptors 0 through 31.

|>
|>What if you have 10 fd's used in a row and #5 disconnects,
|>will unix route the next call to #5, or to #11???

I believe the man pages state that unix will return the lowest available
file descriptor.

|>
|>Thanx in advance for the help!!!
|>Send email to me please...
|>
|>						Petey
|>
|>#include <sys/types.h>
|>#include <sys/socket.h>
|>#include <sys/time.h>
|>#include <netinet/in.h>
|>#include <netdb.h>
|>#include <stdio.h>
|>#include <fcntl.h>
|>#include <signal.h>
|>
|>#define TRUE 1
|>#define FALSE 0
|>#define MAXHOSTNAME 50
|>#define BUFSIZE 128
|>
|>main(argc,argv)  /* argv[1] = port number */
|>char *argv[];
|>int argc;
|>{
|>        int lastsock; /* accept connect with lastsock */
|>        int x,y;      /* all purpose counter */
|>	int sock, length;
|>	struct sockaddr_in server;
|>	char buf[BUFSIZE];
|>	int rval;             /* read return values */
|>	/****************************************************/
|>	fd_set in, out;    /* fuzzy on how to CORRECTLY use */
|>	/****************************************************/
|>	struct timeval to;
|>	char myhostname[MAXHOSTNAME+1];
|>        int temp;
|>
|>	for(x=0;x<64;x++) close(x);        /* close everything */
|>	signal(SIGPIPE, SIG_IGN); 
|>	sock = socket(AF_INET, SOCK_STREAM, 0); /* Create socket */
|>	if (sock < 0) {
|>		printf("opening stream socket\n");
|>		exit(1);
|>	}
|>        setsockopt(sock,SOL_SOCKET,SO_REUSEADDR, (char *)&temp,sizeof(temp));
|>	server.sin_family = AF_INET;
|>	server.sin_addr.s_addr = INADDR_ANY; 
|>	server.sin_port = htons(atoi(argv[1]));
|>        fcntl(sock,F_SETFL, FNDELAY) == -1;
|>	if (bind(sock, &server, sizeof(server))) {
|>		perror("binding stream socket");
|>		exit(1);
|>	}
|>	printf("Socket has port #%d\n", ntohs(server.sin_port));
|>/*********************** Socket Intialization compelete *******************/
|>	listen(sock, 5);
|>


I assume everything above here is correct....

|>	do {    /* main DO loop */
|>	/*** so when do i use this FD stuff??? */
|>		FD_ZERO(&in);
|>		FD_ZERO(&out);
|>		FD_SET(sock, &in);

You also want to FD_SET lastsock, since that is the socket you are
reading data from.  But you can't do that until lastsock has been
opened...  This requires some thinking on your part.

|>		to.tv_sec = 0;
|>                to.tv_usec =1;
|>		if (select(sock + 1 , &in, &out,0, &to) < 0) {

Earlier, you closed 64 file descriptors (no comment on the overkill
there).  You should then select(64,....) or whatever the maximum number
of sockets you plan to read from (this is an approximate description of
how things work).

|>			perror("select");
|>			continue;
|>		}
|>		if (FD_ISSET(sock, &in)) {  /* if phone ringing */
|>                   lastsock = accept(sock, (struct sockaddr *)0, (int *)0);
|>			if (lastsock == -1)
|>			     printf("error on accept\n");
|>                        else {
|>			     /* non=blocking i/o */
|>			     fcntl(lastsock,F_SETFL, FNDELAY);
|>			     fcntl(lastsock,F_SETFD,1);
|>			     }
|>		} 
|>/******************* READ Data from the sockets
*****************************/
|>
|>/**** THE BIG QUESTION !!!! */
|>     bzero(buf, sizeof(buf));
|>/* How do I tell when the socket is ready for reading? */

See above and also do a FD_ISSET(lastsock).


|>     rval = read(lastsock,buf,sizeof(buf)); 
|>     if (rval == 0 )   /* If 0, SHUTDOWN THE SOCKET! */ 
|>       close(lastsock);   /* error reading, close the socket */  
|>     else 
|>/* How do i tell when it ready for writing?!!!! */

Just write to the socket.  And check the return value.

|>       rval =  write(lastsock, buf, sizeof(buf));
|>} while (TRUE);  /* end do loop */
|>} /* end main */
                                                                        
Hope this helps.

*swfc