Networking Forums

Networking Forums > Computer Networking > Linux Networking > Help with Select

Reply
Thread Tools Display Modes

Help with Select

 
 
Marcia Hon
Guest
Posts: n/a

 
      02-14-2004, 02:42 PM
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
 
 
 
 
Marcia Hon
Guest
Posts: n/a

 
      02-14-2004, 03:11 PM
Hi,

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

Thanks for your help.
Marcia


 
Reply With Quote
 
Fernando Gont
Guest
Posts: n/a

 
      02-14-2004, 05:30 PM
On Sat, 14 Feb 2004 15:42:52 GMT, "Marcia Hon" <(E-Mail Removed)>
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: (E-Mail Removed)

[To send a personal reply, please remove the ANTISPAM tag]
 
Reply With Quote
 
James Carlson
Guest
Posts: n/a

 
      02-20-2004, 05:50 PM
"Marcia Hon" <(E-Mail Removed)> 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 <(E-Mail Removed)>
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
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 On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Select Specific MAC Address Skier7667 Wireless Networks 11 10-07-2008 08:00 PM
select() woes Generic Usenet Account Linux Networking 1 10-17-2006 10:50 PM
AF_PACKET and select Gisle Vanem Linux Networking 0 12-15-2004 01:08 PM
Regarding behaviour of select() all Rajat Linux Networking 1 10-09-2004 08:54 PM
FH starvation on busy select Yuri Victorovich Linux Networking 1 08-30-2004 04:25 PM



1 2 3 4 5 6 7 8 9 10 11