Thread: socket programming, simple echo server and client

  1. #1
    Registered User blob84's Avatar
    Join Date
    Jun 2010
    Posts
    46

    socket programming, simple echo server and client

    Hello i have a problem with this program, the client should send a string of two lines from standard input to the server and the server should receive the string of two lines and send back to the client.

    Code:
    /
    //client 
    
    #include	"basic.h"
    
    void client_echo(FILE *fp, int sockfd, int nlines); 
    char *fngets(char *s, int maxline, FILE *fp, int nlines);
    int main(int argc, char **argv) {
    	int			sockfd, n;
    	struct sockaddr_in	servaddr;
    
    	if (argc != 4)
    			{ printf("usage: echocli <IPaddress> <PORT> <number of lines>\n"); exit(1); }
    
    	if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    		{ printf("socket error\n"); exit(1); }
    
    	bzero(&servaddr, sizeof(servaddr));
    	servaddr.sin_family = AF_INET;
    	servaddr.sin_port   = htons(atoi(argv[2]));	/* echo server port */
    	if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
    		{ printf("inet_pton error for %s", argv[1]); exit(1);}
    
    	if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
    		{ printf("connect error\n"); exit(1);}
    
            client_echo(stdin, sockfd, atoi(argv[3]));	
    	exit(0);
    }
    void client_echo(FILE *fp, int sockfd, int nlines) {
            char sendline[MAXLINE], recvline[MAXLINE];
    		int n;
    		int i = 0;
    
            while (fngets(sendline, MAXLINE, fp, nlines) != NULL) {
            	reti_writen(sockfd, sendline, strlen(sendline));	
    			while ((n = read(sockfd, recvline, MAXLINE)) > 0) { 
    	                      write(1, recvline, n);	
    			}
    			printf("fine client\n"); 
            }
    }
    char *fngets(char *s, int maxline, FILE *fp, int nlines)
    {
    	char tmp[MAXLINE];
    
    	bzero(s, sizeof(s));
    	while (nlines-- > 0 && fgets(tmp, maxline, fp) != NULL)	
    		strcat(s, tmp);
    	if (nlines > 0)
    		s = NULL;		
    	return s;
    }
    Code:
    //server
    
    #include	"basic.h"
    
    void server_echo(int sockfd);
    int main(int argc, char **argv) {
            pid_t			childpid;
    	int			listenfd, connfd;
    	struct sockaddr_in	servaddr, cliaddr;
    	socklen_t		cliaddr_len;
    
            if( argc != 2){
               printf("Usage: echosrv <PORT> \n"); exit(1); 
    }
    
    	if( (listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    		{ printf("socket error\n"); exit(1); }
    
    	bzero(&servaddr, sizeof(servaddr));
    	servaddr.sin_family      = AF_INET;
    	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);  /* wildcard address */
    	servaddr.sin_port        = htons(atoi(argv[1]));	/* echo server */
    
    	if( (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr))) < 0)
    		 { printf("bind error\n"); exit(1); }
    
    	if( listen(listenfd, BACKLOG) < 0 )
    		{ printf("listen error\n"); exit(1);}
    
    	for ( ; ; ) {
    		cliaddr_len = sizeof(cliaddr);
    		if( (connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &cliaddr_len)) < 0)
    			{ printf("accept error\n"); exit(1); }
            if( (childpid = fork()) == 0 ) {
    		    close(listenfd);
    		    server_echo(connfd);     
    		    exit(0);
    		}
    		close(connfd);
    	}
    }
    void server_echo(int sockfd) {
            ssize_t n;
            char line[MAXLINE];
    
    		while ((n = read(sockfd, line, MAXLINE)) > 0)  
    			write(sockfd, line, n);
    		if (n == 0)	
    			return;	
    		else if (n < 0){
    			fprintf(stderr, "server_echo: read error\n");
    			return;
    		}
    }
    Last edited by blob84; 03-21-2014 at 11:22 AM.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Well, there's several problems:

    1. You don't explain what exactly goes wrong, what error messages you see, etc.
    2. You don't provide enough code for us to compile and test this ourselves, for example: reti_writen and what's in basic.h and what other headers are used? I don't want to play "guess all the headers I used in my code".
    3. Your formatting/indentation is inconsistent and a bit messy, making your code a bit hard to read. I'm guessing it mostly has to do with whether you use tabs or spaces. For forums like this, using spaces for indent ensures that the code you post comes across clean. Preview your post and make sure it looks good, or go back and edit the post to fix it.
    4. Just at a glance, your fngets function has several problems (the next 3 items).
    5. .....You use the wrong length parameter for fgets -- maxline is the size of s, not tmp
    6. .....You don't check when you use strcat, so you may overflow s
    7. .....Not a real problem, but there's no need to bzero the whole of s. Just set the first char to '\0'. strcat will append starting at the first char that way.
    8. According to the man page, bzero is deprecated. Prefer memset instead.
    9. Your server echo function can be simplified. You don't need the n == 0 case, or either of the returns. The function will return automatically after the last line of code. Just if (n < 0) fprintf....


    Probably more errors, but I can't compile/test it myself.

  3. #3
    Registered User blob84's Avatar
    Join Date
    Jun 2010
    Posts
    46
    Thank you for your reply and suggestions about the fnget function.
    The reti_writen function can be replaced with the write function.
    basic.h have the headers used for linux network programming.
    I suppose the problem is in the client_echo or in the server_echo functions.
    The while loop of read in the client_echo function doesn't end.

    Code:
    /* include basic.h*/
    /* Our own header.  Tabs are set for 4 spaces, not 8 */
    
    /* If anything changes in the following list of #includes, must change
       acsite.m4 also, for configure's tests. */
    
    #include	<sys/types.h>	/* basic system data types */
    #include	<sys/socket.h>	/* basic socket definitions */
    #include	<sys/time.h>	/* timeval{} for select() */
    #include	<time.h>		/* timespec{} for pselect() */
    #include	<netinet/in.h>	/* sockaddr_in{} and other Internet defns */
    #include	<arpa/inet.h>	/* inet(3) functions */
    #include	<errno.h>
    #include	<fcntl.h>		/* for nonblocking */
    #include	<netdb.h>
    #include	<signal.h>
    #include	<stdio.h>
    #include	<stdlib.h>
    #include	<string.h>
    #include	<sys/stat.h>	/* for S_xxx file mode constants */
    #include	<sys/uio.h>		/* for iovec{} and readv/writev */
    #include	<unistd.h>
    #include	<sys/wait.h>
    #include	<sys/un.h>		/* for Unix domain sockets */
    
    #define MAXLINE 4096
    Last edited by blob84; 03-21-2014 at 01:29 PM.

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You need to more fully describe what is supposed to happen. For example, I run the following:
    Code:
    [terminal 1] $ ./server 9876
    [terminal 2] $ ./client 127.0.0.1 9876 2 # 2 lines
    I can type in two lines and get them echoed back. Should the program then quit after one echo? Should it keep getting 2 lines then echoing them back until i signal EOF?

    If you can not fully describe, in English (or your native language), in excruciating detail, what it is you want your program to do, you stand very little chance of successfully writing the program. How can you tell a computer how to solve a problem if you don't know what that problem is, or how to solve it yourself?

  5. #5
    Registered User blob84's Avatar
    Join Date
    Jun 2010
    Posts
    46
    Should it keep getting 2 lines then echoing them back until i signal EOF?
    This is the aim of the program.

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Start with a high-level design/description (e.g. in English/pseudo code), then turn that into real code. Work in small steps, building as you go. Remember, a function should do one thing and do it well. Name it appropriately
    Code:
    while I haven't received EOF
        get N lines of input
        send them to server
        receive back echo
        print echoed text
    The get N lines of input would be your fngets function -- perhaps better called get_n_lines_from_user.

    From there, create a get_server_echo() function that literally just sends the text and reads the echo back. Test it with some static text, like "Hello world!". Note, do not call printf in this function, it's only job is to send the message and receive the echo. Next, test that in a loop, make sure you can repeatedly send/receive a message. Again, test with static text, but try several different messages, of different lengths, and make sure you get it back correctly by comparing with strcmp the original message and the echo back. That allows you to test the echo code without worrying whether you got proper input.

    Then, work on your input loop. Make sure you can get two lines of input, and "echo" them back with a basic printf them back, stopping when it gets EOF. That way, you can perfect your input reading without worrying about whether you are talking to the server correctly.
    Code:
    while I haven't received EOF
        get N lines of input
        print "I got the following N lines of input"
        print input received
    print "All done!"
    When they're all done, combine them. Replace the "I got the following..." statement with get_server_echo, and your client code is all done.

    Other notes:

    1. Add more debugging output -- it's okay to have tons of messages for now, giving you more info than you think you need.
    2. Also, give better error messages. Use the perror function, which gives a message based on the value of errno, that tells you why a certain function failed.
    3. read() and write() will not necessarily read/write all the data you asked for at once. For small messages you should be okay. But if you want to handle longer messages, make sure you cover the cases where they only send/receive part of the message. Check their documentation for details on their return value.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 03-04-2013, 01:06 AM
  2. Simple c++ socket server game needs client
    By bakri in forum C++ Programming
    Replies: 2
    Last Post: 05-28-2012, 08:27 AM
  3. Replies: 2
    Last Post: 06-30-2010, 06:52 PM
  4. Problem with simple socket client/server program
    By spencer88 in forum C Programming
    Replies: 6
    Last Post: 05-05-2009, 11:05 PM
  5. TCP/IP client & echo server
    By Jordban in forum C++ Programming
    Replies: 2
    Last Post: 06-06-2005, 06:39 PM