Unix Programming - Select() and Beejs Network Programming Tutorial

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > January 2004 > Select() and Beejs Network Programming Tutorial





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Select() and Beejs Network Programming Tutorial
Materialised

2004-01-24, 11:34 am

Hi everyone, today I started reading Beejs Guide to Network programming,
however I am having a issue with select().
I have compiled the code sample he gives on select() (listed below) and
for some reason I get errors when running.
I even tired it on 2 different machines, a Freebsd 5.1 x86 system and a
redhat 8.0 alpha system just to double check.

Here is the code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 9034 // port were listening on

int main(void)
{
fd_set master; //master file descriptor list
fd_set read_fds; //temp file descriptor list for select()
struct sockaddr_in myaddr; //server address
struct sockaddr_in remoteaddr; //client address
int fdmax; //max file descriptor number
int listener; //listening socket descriptor
int newfd; //newly accept()ed socket descriptor
char buf[256]; //buffer for client data
int nbytes;
int yes=1; //for setsocketopt() SO_REUSEADDR, below
int addrlen;
int i, j;

FD_ZERO(&master);
FD_ZERO(&read_fds);

//get the listener
if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}

//loose the pesky "address in use" error message
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) ==
-1) {
perror("setsockopt");
exit(1);
}

//bind
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY;
myaddr.sin_port = htons(PORT);
memset(&(myaddr.sin_zero), '\0', 8);
if(bind(listener, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
perror("bind");
exit(1);
}

//listen
if(listen(listener, 10) == -1) {
perror("listen");
exit(1);
}

//add the listener to the master set
FD_SET(listener, &master);

//keep track of the biggest file descriptor
fdmax = listener; //so far its this one

//main loop
for(;;) {
read_fds = master; //copy it
if(select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
perror("select");
exit(1);
}

//run through the existing connections looking for data to send
for(i=0; i <= fdmax; i++) {
if(FD_ISSET(i, &read_fds)) { //we got one!!!
if(i == listener) {
//handle new connections
addrlen = sizeof(remoteaddr);
if((newfd = accept(listener, (struct sockaddr *)&remoteaddr,
&addrlen)) == -1) {
perror("accept");
} else {
//handle data from the client
if((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) {
//got error or the conenction was close by the client
if(nbytes == 0) {
//connection closed
printf("selectserver: socket %d hung up\n", i);
}else{
perror("recv");
}
close(i); //bye
FD_CLR(i, &master); //remove from master set
} else {
// we got some data from the client
for(j = 0; j <= fdmax; j++) {
//send to everyone
if(FD_ISSET(j, &master)) {
//except the listener and ourselves
if(j != listener && j != i) {
if(send(j, buf, nbytes, 0) == -1) {
perror("send");
}
}
}
}
}
} //its so ugly
}
}
}
}
return 0;

And here are the error messages I recieve, for some reason the server
will only allow one client to connect.

######### F'BSD Machine
recv: Socket is not connected

######### RedHat Machine
recv: Transport endpoint is not connected

I have no idea what is wrong here, is it the code provided in the
tutorial? my systems, or have I simply errored somewhere in typing it
out? (I did check for the later, but I couldnt see anything apparent.)

Thanks for your help
Mick

--
Materialised
frmb@kent.ac.uk

2004-01-24, 3:34 pm

Materialised <materialised@privacy.net> usenetted:
quote:

>[snip code]
> if((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) {



Looks like it should be "newfd" instead of "i", at a guess.


Hope that helps,

--
Fred
Gianni Mariani

2004-01-24, 4:34 pm

Materialised wrote:
quote:

> Hi everyone, today I started reading Beejs Guide to Network programming,
> however I am having a issue with select().
> I have compiled the code sample he gives on select() (listed below) and
> for some reason I get errors when running.
> I even tired it on 2 different machines, a Freebsd 5.1 x86 system and a
> redhat 8.0 alpha system just to double check.
>
> Here is the code


.... snip...
quote:

>
> //run through the existing connections looking for data to send
> for(i=0; i <= fdmax; i++) {
> if(FD_ISSET(i, &read_fds)) { //we got one!!!
> if(i == listener) {
> //handle new connections
> addrlen = sizeof(remoteaddr);
> if((newfd = accept(listener, (struct sockaddr
> *)&remoteaddr,
> &addrlen)) == -1) {
> perror("accept");



.... newfd is the magic fd that needs to be read and written to
but it's dropped on the floor.

It seems like the "if(i == listener)" else is messed up with the
"if((newfd = ..." else but there is somthing else (like an FD_SET) missing.
quote:

> } else {
> //handle data from the client
> if((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) {
> //got error or the conenction was close by
> the client



.....
quote:

> I have no idea what is wrong here, is it the code provided in the
> tutorial? my systems, or have I simply errored somewhere in typing it
> out? (I did check for the later, but I couldnt see anything apparent.)



You probably have a few missing lines.

Barry Margolin

2004-01-24, 6:34 pm

In article <amfvub.ako.ln@teddy.frmb.org>, frmb@kent.ac.uk wrote:
quote:

> Materialised <materialised@privacy.net> usenetted:
>
> Looks like it should be "newfd" instead of "i", at a guess.



No, i is the fd that was just checked with FD_ISSET(). newfd is from a
previous iteration when the listening fd was ready.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
frmb@kent.ac.uk

2004-01-25, 2:34 am

Barry Margolin <barmar@alum.mit.edu> usenetted:
quote:

>
> No, i is the fd that was just checked with FD_ISSET(). newfd is from a
> previous iteration when the listening fd was ready.



So it is.. that'll teach me to read code at 4am.. ;)


--
Fred


Materialised

2004-01-25, 4:35 am

Gianni Mariani wrote:
<snip>
quote:

> You probably have a few missing lines.
>


Yeah that was the problem, fool on me

--
Materialised
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com