View Full Version : socket programming, simple echo server and client

03-21-2014, 11:12 AM
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.


#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]));
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;


#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 ) {
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)
else if (n < 0){
fprintf(stderr, "server_echo: read error\n");

03-21-2014, 12:26 PM
Well, there's several problems:

You don't explain what exactly goes wrong, what error messages you see, etc.
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".
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.
Just at a glance, your fngets function has several problems (the next 3 items).
.....You use the wrong length parameter for fgets -- maxline is the size of s, not tmp
.....You don't check when you use strcat, so you may overflow s
.....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.
According to the man page (http://linux.die.net/man/3/bzero), bzero is deprecated. Prefer memset instead.
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.

03-21-2014, 01:20 PM
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.

/* 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

03-21-2014, 03:00 PM
You need to more fully describe what is supposed to happen. For example, I run the following:

[terminal 1] $ ./server 9876
[terminal 2] $ ./client 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?

03-21-2014, 04:45 PM
Should it keep getting 2 lines then echoing them back until i signal EOF?
This is the aim of the program.

03-21-2014, 05:33 PM
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

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.

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:

Add more debugging output -- it's okay to have tons of messages for now, giving you more info than you think you need.
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.
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.