I wrote some code in C for a TCP Server that echoes whatever it gets. The problem is when I send data first time it echoes it and next times the server sends back the first packet I sent. The log looks like:
Client Send : Packet1
Server reply : Packet1
Client Send : Packet2
server reply : Packet1
The server code is as follows:
int main(int argc, char** argv) {
int listenfd,connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in servaddr,cliaddr;
listenfd = socket(AF_INET,SOCK_STREAM,0);
printf("Socket listenfd : %d with %d And %d\n",listenfd,AF_INET,SOCK_STREAM);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);
printf("Server address: %d\n",servaddr.sin_addr.s_addr);
bind(listenfd, (SA*) &servaddr, sizeof(servaddr));
printf("Listened: %d\n",listenfd);
listen(listenfd,LISTENQ);
printf("After Listening: %d\n",listenfd);
int num=0;
for( ; ; ){
clilen=sizeof(cliaddr);
connfd = accept(listenfd, (SA*) &cliaddr,&clilen);
printf("Client no. %d connected\n",++num);
if( (childpid=fork())==0){
close(listenfd);
echo(connfd);
exit(0);
printf("Client no. %d Terminated\n",++num);
}
close(connfd);
}
return (EXIT_SUCCESS);
}
And my echo function:
void echo(int sockfd) {
ssize_t n;
char buf[MAXLINE];
again:
while ( (n = read(sockfd, buf, MAXLINE)) > 0)
writen(sockfd, buf, n);
if (n < 0 && errno == EINTR)
goto again;
else if (n < 0)
printf("read error");
}
the client code main :
int main(int argc, char** argv) {
int sockfd;
struct sockaddr_in servaddr;
sockfd= socket(AF_INET,SOCK_STREAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port= htons(SERV_PORT);
inet_pton(AF_INET,"0.0.0.0",&servaddr.sin_addr);
printf("%d , %d \n",sockfd,servaddr.sin_addr.s_addr);
connect(sockfd, (SA*) &servaddr,sizeof(servaddr));
printf("%d\n",sockfd);
replyBack(stdin,sockfd);
printf("RETURN\n");
return (EXIT_SUCCESS);
}
the replyBack function:
void replyBack(FILE *fp, int sockfd) {
char sendline[MAXLINE], recvline[MAXLINE];
printf("ENTER YOUR ECHOED: \n");
while (fgets(sendline, MAXLINE, stdin) != NULL) {
write(sockfd, sendline, sizeof(sendline));
if (read(sockfd, recvline, MAXLINE) == 0)
{
printf("str_cli: server terminated prematurely");
exit(-1);
}
fputs(recvline, stdout);
}
}
Well, let’s look at this section of your code:
Calling
exitexits your application, so theprintffollowing it will never get executed. Minor, but worth pointing out.Also, in the “child” process, you should not close your listening socket. The only socket it should work with is the client connection, so you should have something more along the lines of:
Now let’s look at your echo code:
Have to remember that the calls to
readandwritemay block (since I don’t see you setting the socket to non-blocking IO), andwritemay not send the entire buffer when called, so you need to check a few more things here.Once your
echofunction exits, the socket will be closed back in the calling function. Generally, I would suggest closing the socket in theechofunction, unless you need it afterwards. I almost certainly would suggest closing it when an error occurs, but, again, that is up to you.Just as an aside, stay away from
goto… it has its purposes, but for the most part, well-written code rarely ever uses it.