Thread: Socket programming!

  1. #1
    Registered User
    Join Date
    Dec 2010
    Posts
    3

    Socket programming!

    hi, noob @ socket programming here. :P

    i'm trying to make client/server programs where:
    - the server waits for a number of connections, say four clients.
    - and then broadcasts data to the clients ONLY if the number of clients are reached. meaning it will wait until 4 clients are connected to the server.

    The programs i wrote are not working properly. the server reports: "bad file descriptor" as an error report for the send() function.

    can anybody help me, please?

    I hope some one will respond soon... X(


    here's my server code:

    Code:
    /*
    ** server.c -- a stream socket server demo
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <sys/wait.h>
    #include <signal.h>
    #define PORT "3490" // the port users will be connecting to
    #define BACKLOG 10 // how many pending connections queue will hold
    
    void sigchld_handler(int s)
    {
    	while(waitpid(-1, NULL, WNOHANG) > 0);
    }
    // get sockaddr, IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa)
    {
    	if (sa->sa_family == AF_INET) {
    		return &(((struct sockaddr_in*)sa)->sin_addr);
    	}
    	
    	return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }
    
    void report(char *str){ // prints the string str in console and in log file ***unfinished
    	printf("%s", str);
    }
    
    int main(int argc, char *argv[])
    {
    	char str[999];
    	int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
    	struct addrinfo hints, *servinfo, *p;
    	struct sockaddr_storage their_addr; // connector's address information
    	socklen_t sin_size;
    	struct sigaction sa;
    	int yes=1;
    	char s[INET6_ADDRSTRLEN];
    	int rv, PCs, i=0, q=0;
    
    	if (argc != 2) {
    		fprintf(stderr,"usage: serv number_of_PCs\n");
    		exit(1);
    	}
    	else{
    		PCs = atoi(argv[1]); // PCs = number of PCs to be used
    	}
    
    	int PC[PCs]; // PC IDs
    
    	memset(&hints, 0, sizeof hints);
    	
    	hints.ai_family = AF_UNSPEC;
    	hints.ai_socktype = SOCK_STREAM;
    	hints.ai_flags = AI_PASSIVE; // use my IP
    	
    	if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
    		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    		return 1;
    	}
    	
    	// loop through all the results and bind to the first we can
    	for(p = servinfo; p != NULL; p = p->ai_next) {
    		if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
    			perror("server: socket");
    		continue;
    		}
    	
    		if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
    			perror("setsockopt");
    			exit(1);
    		}
    		
    		if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
    			close(sockfd);
    			perror("server: bind");
    			continue;
    		}
    		break;
    	}
    	
    	if (p == NULL) {
    		fprintf(stderr, "server: failed to bind\n");
    		return 2;
    	}
    	
    	freeaddrinfo(servinfo); // all done with this structure
    	
    	if (listen(sockfd, BACKLOG) == -1) {
    		perror("listen");
    		exit(1);
    	}
    	
    	sa.sa_handler = sigchld_handler; // reap all dead processes
    	sigemptyset(&sa.sa_mask);
    	sa.sa_flags = SA_RESTART;
    	
    	if (sigaction(SIGCHLD, &sa, NULL) == -1) {
    		perror("sigaction");
    		exit(1);
    	}
    
    	sprintf(str,"server: waiting for connections...\n");
    	report(str);
    	
    	while(i<PCs) { // main accept() loop
    		sin_size = sizeof their_addr;
    
    		new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
    
    		if (new_fd == -1) {
    			perror("accept");
    			continue;
    		}
    		else{
    			PC[i] = new_fd;
    			i++;
    			inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
    			sprintf(str,"server: got connection from %s\n", s);
    			report(str);
    			close(new_fd); // parent doesn't need this
    		}
    	}
    
    	for(q=0; q<i; q++){
    		if (!fork()) { // this is the child process
    			close(sockfd); // child doesn't need the listener
    			if (send(PC[q], "Hello, world!", 13, 0) == -1)
    				perror("send");
    			else{
    				sprintf(str,"server: sent to %s\n", s);
    				report(str);
    			}
    			close(PC[q]);
    			exit(0);
    		}
    
    	}
    
    	return 0;
    }

    and here's my code for the client:

    Code:
    /*
    ** client.c -- a stream socket client demo
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <netdb.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #define PORT "3490" // the port client will be connecting to
    #define MAXDATASIZE 100 // max number of bytes we can get at once
    
    // get sockaddr, IPv4 or IPv6:
    void *get_in_addr(struct sockaddr *sa)
    {
    	if (sa->sa_family == AF_INET) {
    		return &(((struct sockaddr_in*)sa)->sin_addr);
    	}
    	return &(((struct sockaddr_in6*)sa)->sin6_addr);
    }
    
    void report(char *str){ // prints the string str in console and in log file ***unfinished
    	printf("%s", str);
    }
    
    int main(int argc, char *argv[])
    {
    	char str[999];
    	int sockfd, numbytes;
    	char buf[MAXDATASIZE];
    	struct addrinfo hints, *servinfo, *p;
    	int rv;
    	char s[INET6_ADDRSTRLEN];
    
    	if (argc != 2) {
    		fprintf(stderr,"usage: client hostname\n");
    		exit(1);
    	}
    
    	memset(&hints, 0, sizeof hints);
    
    	hints.ai_family = AF_UNSPEC;
    	hints.ai_socktype = SOCK_STREAM;
    
    	if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
    		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    		return 1;
    	}
    
    	// loop through all the results and connect to the first we can
    	for(p = servinfo; p != NULL; p = p->ai_next) {
    		if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
    			perror("client: socket");
    			continue;
    		}
    		if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
    			close(sockfd);
    			perror("client: connect");
    			continue;
    		}
    		break;
    	}
    
    	if (p == NULL) {
    		fprintf(stderr, "client: failed to connect\n");
    		return 2;
    	}
    
    	inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), s, sizeof s);
    
    	sprintf(str, "client: connecting to %s\n", s);
    	report(str);
    
    	freeaddrinfo(servinfo); // all done with this structure
    
    	if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
    		perror("recv");
    		exit(1);
    	}
    
    	buf[numbytes] = '\0';
    	sprintf(str,"client: received '%s'\n",buf);
    	report(str);
    	close(sockfd);
    	return 0;
    }

  2. #2
    Registered User
    Join Date
    Dec 2010
    Posts
    7
    Hey ayokilabot,

    If you comment line #130(close(new_fd)), it will work, I tried that:

    Code:
    //some code
    
    		if (new_fd == -1) {
    			perror("accept");
    			continue;
    		}
    		else{
    			PC[i] = new_fd;
    			i++;
    			inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), s, sizeof s);
    			sprintf(str,"server: got connection from %s\n", s);
    			report(str);
    			//close(new_fd); // parent doesn't need this
    		}
    
    //some code

  3. #3
    Registered User
    Join Date
    Dec 2010
    Posts
    3
    thanks haitiboy! it worked fine

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why the local socket program occur core dump?
    By chenayang in forum Linux Programming
    Replies: 16
    Last Post: 08-16-2010, 08:39 AM
  2. Function call from another .c module
    By Ali.B in forum C Programming
    Replies: 14
    Last Post: 08-03-2009, 11:45 AM
  3. Problem with socket descriptors
    By McKracken in forum C Programming
    Replies: 1
    Last Post: 07-22-2009, 08:51 AM
  4. socket programming question, closing sockets...
    By ursula in forum Networking/Device Communication
    Replies: 2
    Last Post: 05-31-2009, 05:17 PM
  5. socket newbie, losing a few chars from server to client
    By registering in forum Linux Programming
    Replies: 2
    Last Post: 06-07-2003, 11:48 AM