Help with Select

This is a discussion on Help with Select within the Linux Networking forums, part of the Linux Forums category; Hi, I am trying to use the select() socket programming command to select between stdin and a connection. Currently, I ...


Go Back   Usenet Forums > Linux Forums > Linux Networking

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-14-2004
Marcia Hon
 
Posts: n/a
Default Help with Select

Hi,

I am trying to use the select() socket programming command to select between
stdin and a connection. Currently, I have a listening stream and stdin that
I insert into the fd_set. The problem is that when I recognize FD_ISSET from
stdin, I am stuck there. The loop does not return me to select() between
stdin and listening socket. Similarly, when I accept a client, the loop does
not return me to select between stdin and listeing socket. I don't know what
to do. I want to be able to select continuously between stdin and the
listening port after I have either accepted from a port or from stdin.

I have pasted the codes that I am using for the listening to port and stdin
and the code for the client.

Please help.

Thank you,

Marcia Hon

#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 max(a, b) ((a) > (b) ? a: b)

int flushToEndOfLine();

int main(int argc, char *argv[])

{

fd_set master;


struct sockaddr_in myaddr;

struct sockaddr_in remoteaddr;


int fdmax;

int listenerSocket;

int newfd;

char buf[256];

int yes = 1;

int addrlen;

int i, j;


if(argc != 2)

{

fprintf(stderr, "Usage: %s <listen_port>\n", argv[0]);

exit(1);

}


FD_ZERO(&master); //clear master set


// get listenerSocket

if((listenerSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

perror("socket");

exit(1);

}


// lose socket already in use error message

if(setsockopt(listenerSocket, 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(atoi(argv[1]));

memset(&(myaddr.sin_zero), '\0', 8);

if(bind(listenerSocket, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1)
{

perror("bind");

exit(1);

}


// listen

if(listen(listenerSocket, 5) == -1) {

perror("listen");

exit(1);

}


FD_SET(listenerSocket, &master);

FD_SET(0, &master);


fdmax = max(listenerSocket, 0);


while(1){

printf("select\n");

if(select(fdmax+1, &master, NULL, NULL, NULL) == -1){

perror("select");

exit(1);

}


if(FD_ISSET(listenerSocket, &master)){

addrlen = sizeof(remoteaddr);

if((newfd = accept(listenerSocket, (struct

sockaddr *)&remoteaddr, &addrlen)) == -1) {

perror("accept");

}

printf("new connection from client\n");

close(newfd);

}

else

{

if(FD_ISSET(0, &master))

{

printf("user entered data \n");

flushToEndOfLine();

}

}

}


return 0;

}

int flushToEndOfLine()

{

int c;

while ( (c=getchar()) != EOF && c != '\n' );

return;

}



client:

//WHAT IF SHORT IS NOT 2 BYTES?!?!?!?

#include <stdio.h>

#include <stdlib.h>

#include <sys/socket.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <netdb.h>

#define FILE_TBYTES 4 //bytes at the beginning of file that specify how many
bytes are in this block being sent

#define MAX_BYTES 1000 //breaks up file into this many bytes and sends this
many bytes at a time

#define MAX_BSEND_RETRY 3 //how many times to retry sending a block of
MAX_BYTES before fail

#define DEBUG

//prototypes

int establish_connection (const char * name, unsigned short port);

int send_stream (int sockfd, const char * data, int len);

unsigned long getFileSize(char *fileName);

//check ip or dns

int main(int argc, char *argv[])

{

FILE *fp;

int j; //loop counters

short int i; //this better be 2 bytes

char * buffer;

unsigned long *tmp;

unsigned short port;

int sockfd;

unsigned long fileSize;


if ((buffer = (char *) malloc (MAX_BYTES)) == NULL)

{

fprintf(stderr, "Not enough memory for a file input buffer of %d\n",
MAX_BYTES);

exit(1);

}


//Check if 3 arguments passed

if (argc !=4)

{

fprintf(stderr, "Usage: %s <ip> <port> <file>\n", argv[0]);

exit(1);

}


//no check!

port = atoi(argv[2]);


#ifdef DEFINE

printf("Arguments Passed:\n");

printf("IP: %s\n", argv[1]);

printf("PORT: %d\n", port);

printf("FILE: %s\n", argv[3]);

printf("\n");

#endif



//open file

if ((fp = fopen(argv[3],"r")) == NULL)

{

fprintf(stderr, "Error: Could not open %s\n", argv[3]);

exit(1);

}


if ((sockfd = establish_connection (argv[1], port)) == -1)

{

fprintf(stderr, "Error establishing connection\n");

fclose(fp);

exit(1);

}


//buffer = "Hello World";

//send_stream(sockfd, buffer, 11);


//send file size

fileSize = getFileSize(argv[3]);

tmp = (unsigned long *) &buffer[0];

*tmp = (unsigned long) htonl(fileSize);

send_stream(sockfd, buffer, 4);

printf("File Size: %d\n", fileSize);


while (!feof(fp))

{

//read some bytes

for (i = 0; i<MAX_BYTES; i++)

{

buffer[i] = fgetc(fp);

if (feof(fp)) //end of file true

break;

}



//echo bytes to screen

for (j=0; j<i; j++)

{

//put send function here

//printf("%c", buffer[j]);

}


if (!send_stream(sockfd, buffer, i))

{

fprintf(stderr, "Error sending a block\n");

exit(1);

}

}


//close file

fclose(fp);

close(sockfd);


return 0; //exited succesfully

}



//pass name of the host and port number only!

//-1 fail, sockfd success

int establish_connection (const char * name, unsigned short port)

{

struct sockaddr_in their_addr;

int sockfd;

int r; //returned from functions

struct hostent * h;

sockfd = socket(AF_INET, SOCK_STREAM, 0);


//set up the structure

their_addr.sin_family = AF_INET;

their_addr.sin_port = htons(port); // short, network byte order

memset(&(their_addr.sin_zero), '\0', 8); // zero the rest of the struct


h=gethostbyname(name);

if (h == NULL)

return -1;


//1. make *h_addr_list[0] be a in_addr *

//2. dereference this pointer and assign it to their_addr.sin_addr

their_addr.sin_addr = *((struct in_addr *)h->h_addr);


printf("IP Address : %s\n", inet_ntoa(*((struct in_addr *)h->h_addr)));

printf("IP Address : %s\n", inet_ntoa(their_addr.sin_addr));

printf("Port: %d \n", ntohs(their_addr.sin_port));


if((connect(sockfd, (struct sockaddr *) &their_addr, sizeof(struct
sockaddr))) == -1)

return -1;


return sockfd;

}

//sends data

//connect may return that it sent less, this function sends the rest

//return 0 on fail, 1 on success

int send_stream (int sockfd, const char * data, int len)

{

int bytes_sent, newlen;

const void * newdata;


bytes_sent = send(sockfd, data, len,0);

if (bytes_sent < 0)

return 0;

while (bytes_sent < len - 1)

{

//if we sent 10 bytes, we sent bytes 0...9

//need to send byte 10...

newdata = &data[bytes_sent];

bytes_sent = send(sockfd, newdata, len - bytes_sent, 0);

if (bytes_sent < 0)

return 0;

}

return 1;

}

unsigned long getFileSize(char *fileName)

{

unsigned long fileSize;

FILE *f=fopen(fileName, "rb");

if(f==NULL)

{

fprintf(stderr, "Cannot open file.\n");

exit(EXIT_FAILURE);

}

else

{

if(fseek(f, 0, SEEK_END)!=0)

{

fprintf(stderr, "Cannot use file.\n");

exit(EXIT_FAILURE);

}

fileSize=ftell(f);

}

if(fclose(f)!=0)

{

fprintf(stderr, "Cannot close file.\n");

exit(EXIT_FAILURE);

}

return fileSize;

}


Reply With Quote
  #2 (permalink)  
Old 02-14-2004
Marcia Hon
 
Posts: n/a
Default Re: Help with Select

Hi,

Problem fixed! I put FD_SET, FD_CLR, select, FD_ISSET all inside the loop.

Thanks for your help.
Marcia


Reply With Quote
  #3 (permalink)  
Old 02-14-2004
Fernando Gont
 
Posts: n/a
Default Re: Help with Select

On Sat, 14 Feb 2004 15:42:52 GMT, "Marcia Hon" <honm@rogers.com>
wrote:

This has nothing to do with ANSI C, so I've removed it from the
Followup-To field. (I should probably have removed
comp.os.linux.networking, too.)


>while(1){
>
>printf("select\n");
>
>if(select(fdmax+1, &master, NULL, NULL, NULL) == -1){
>
>perror("select");
>
>exit(1);
>
>}


select() will destroy the "master" parameter each time you call it. So
your code should look like this:


saved_master = master;

while(1){
printf("select\n");

master = saved_master;

if(select(fdmax+1, &master, NULL, NULL, NULL) == -1){
perror("select");
exit(1);
}


BTW, your code is ugly indented. If the bug in your code hadn't been
easy to spot, probably none would have taken the time to have a look
at it.

--
Fernando Gont
e-mail: fernando@ANTISPAM.gont.com.ar

[To send a personal reply, please remove the ANTISPAM tag]
Reply With Quote
  #4 (permalink)  
Old 02-20-2004
James Carlson
 
Posts: n/a
Default Re: Help with Select

"Marcia Hon" <honm@rogers.com> writes:
> I am trying to use the select() socket programming command to select between
> stdin and a connection. Currently, I have a listening stream and stdin that
> I insert into the fd_set. The problem is that when I recognize FD_ISSET from
> stdin, I am stuck there. The loop does not return me to select() between
> stdin and listening socket. Similarly, when I accept a client, the loop does
> not return me to select between stdin and listeing socket. I don't know what
> to do. I want to be able to select continuously between stdin and the
> listening port after I have either accepted from a port or from stdin.


Select modifies its arguments. You need to put the FD_SET invocations
*inside* the loop, or save a copy of 'master' somewhere.

--
James Carlson, IP Systems Group <james.d.carlson@sun.com>
Sun Microsystems / 1 Network Drive 71.234W Vox +1 781 442 2084
MS UBUR02-212 / Burlington MA 01803-2757 42.497N Fax +1 781 442 1677
Reply With Quote
Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On




All times are GMT +1. The time now is 12:22 AM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.0.0