buffer problem? in send/recv

Hi:
 i wrote these 2 very simple programs (client and server) that simply send/receive data.
   When the buffer (the send/receive data) is 30000 everything works OK.  
   When the buffer is 60000 it hangs after a couple of sends/receives.
   Even more strange, if i suspend the client (CTRL-z) and then continue it (fg) it send/receive for a while and then it hangs again.
   When the client/server are in different machines, it doesn't hangs.
   Any idea? Why it is hanging? How can i make it work without unnecessary sleep()s?
   thanks,
    rafa

 BTW: I'm using Linux, Red-Hat 7.2.

 ------------ cliserv.h -------------
 #ifndef _cliserv_h_
 #define _cliserv_h_

 #define LEN 60000
 char sendBuf[LEN];
 char recvBuf[LEN];
 #define LOOP 100000
 #define SLEEP 0

 #endif
 ------------ EOF cliserv.h -------------


 ----------- client.c -------------
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <string.h>
 #include <netinet/in.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <arpa/inet.h>
 #include "cliserv.h"
 #include <unistd.h>


 void fillIt(char *arr){
   int i;
   for (i=0; i<LEN; i++)
     arr[i]= i;
 }

 void printIt(char* arr){
   int i;
   return;
   for (i=0; i<LEN; i+=1000)
     printf("Carr[%d]=%d - ",i, arr[i]) ;
   printf("\n");
 }


 void usage (int argc, char** argv){
   fprintf(stderr,"%s <port> <ip>\n", argv[0]);
   exit(__LINE__);
 }

 int linkIt(int port, char* ip){
   struct sockaddr_in serv_addr;
   int err;
   int sockd;
   sockd= socket (AF_INET, SOCK_STREAM, 0);
   if (sockd == -1) {
     perror("opening socket");
     exit(1);
   }
   serv_addr.sin_family= AF_INET; //address_family_internet
   serv_addr.sin_port= htons(port); //host to network short
   serv_addr.sin_addr.s_addr= inet_addr(ip);
   memset(&(serv_addr.sin_zero),'\0',8);
   err= connect(sockd, (struct sockaddr*) &serv_addr, sizeof(struct sockaddr));
   if (err == -1) {
     perror("In connect");
     exit (2);
   }
   printf("Connected to server\n");
   return sockd;
 }

 void mySend(int servSock){
   fillIt(sendBuf);
   //  printf("****C:sending\n");
   //  printIt(sendBuf);
   send(servSock, sendBuf, LEN, 0);
 }

 void myRecv(int servSock){
   //  printf("****C: Before rcv\n");
   //  printIt(recvBuf);
   recv(servSock, recvBuf, LEN, 0);
   //  printf("*****C: After rcv\n");
   //  printIt(recvBuf);
 }

 int main(int argc, char** argv){
   int i;
   int servSock;
   int servPort;
   char* servIp;
   if (argc != 3) usage(argc,argv);
   servPort=atoi(argv[1]);
   servIp=argv[2];
   servSock= linkIt(servPort, servIp);
   for (i=0; i<LOOP; i++){
     fprintf(stderr,"C%d- ",i);
     myRecv(servSock);
 #if (SLEEP)
     if (i%10 == 0) sleep (SLEEP);
 #endif
     mySend(servSock);
   }
   printf ("C:END\n");
   //  shutdown(servSock,2);
   return 0;
 }


 ------ EOF client.c ---------


 ------ server.c ---------
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <string.h>
 #include <netinet/in.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <arpa/inet.h>
 #include "cliserv.h"
 #include <unistd.h>


 int linkIt(int port, char* ip){
   int sockfd, clieSock;
   struct sockaddr_in my_addr, their_addr;
   int err;
   int sin_size;

   sockfd= socket (AF_INET, SOCK_STREAM, 0);
   if (sockfd == -1) fprintf(stderr,"error opening socket\n");

   my_addr.sin_family= AF_INET; //address_family_internet
   my_addr.sin_port= htons(port); //host to network short
   if (ip)
     my_addr.sin_addr.s_addr= inet_addr(ip);
   else my_addr.sin_addr.s_addr= INADDR_ANY;
   memset(&(my_addr.sin_zero),'\0',8);

   err= bind (sockfd, (struct sockaddr*) &my_addr, sizeof(struct sockaddr));
   if (err){ perror("In bind"); exit (1);}

   err= listen(sockfd, 5);// how many connections to queue
   if (err){ perror("In listen"); exit (2); }

   sin_size= sizeof(struct sockaddr_in);
   clieSock= accept(sockfd, (struct sockaddr *) &their_addr, &sin_size);
   if (clieSock == -1){ perror("In accpet"); exit (3); }

   return clieSock;
 }


 void fillIt(char *arr){
   int i;
   for (i=0; i<LEN; i++)
     arr[i]= i;
 }

 void printIt(char* arr){
   int i;
   return;
   for (i=0; i<LEN; i+=1000)
     printf("Sarr[%d]=%d - ",i, arr[i]) ;
   printf("\n");
 }


 void usage (int argc, char** argv){
   fprintf(stderr,"%s <port>\n", argv[0]);
   exit(__LINE__);
 }


 void mySend(int clieSock){
   fillIt(sendBuf);
   //  printf("@@@@@@@S:sending\n");
   //  printIt(sendBuf);
   send(clieSock, sendBuf, LEN, 0);
 }

 void myRecv(int clieSock){
   //  printf("@@@@@@@S: Before rcv\n");
   //  printIt(recvBuf);
   recv(clieSock, recvBuf, LEN, 0);
   //  printf("@@@@@@@S: After rcv\n");
   //  printIt(recvBuf);
 }

 int main(int argc, char** argv){
   int i;
   int cliSock;
   int cliPort;
   char* cliIp;
   if (argc != 2) usage(argc,argv);
   cliPort=atoi(argv[1]);
   cliIp=INADDR_ANY;
   cliSock= linkIt(cliPort, cliIp);
   for (i=0; i<LOOP; i++){
        fprintf(stderr,"S%d- ",i);
 #if (SLEEP)
     if (i%10 == 0) sleep (SLEEP);
 #endif
     
     mySend(cliSock);
     myRecv(cliSock);
   }
   shutdown(cliSock,2);
   return 0;
 }

 ------ EOF server.c ---------




 Compile with:
 gcc -Wall -o client  client.c
 gcc -Wall -o server server.c

 Run with:
 /server 7778
 /client 7778 127.0.0.1


rafahoroAsked:
Who is Participating?
 
The--CaptainCommented:
As far as I've ever seen, problems like this will plague you endlessly until you start using fork() to spawn a seperate thread of execution for the sender and the receiver.  Trying to make the same thread do both *never* works for long, except in the most simplistic of situations.  Currently you are relying on alternating reads and writes, whose success in the end is reliant upon arbitrary network transport times, which you cannot control.  Basically, your problem is a symptom of blocking on a read/recv when you're not supposed to, which can be avoided with fork().

You *do* have a copy of "Unix Network Programming" by Stevens, right?  AFAIK, it's more or less the de facto standard in programming unix sockets in C.  It's a weighty tome, and not inexpensive, but well worth posessing.

Cheers,
-Jon

BTW, if you know perl netowrk prograqmming better than C (I know I do), you can cheat by just writing it in perl and then using perlcc - it always compiles my socket stuff just fine, and forking is a breeze in perl (especially since the nice folks at O'Reilly give explicit code examples on exactly how to write a forking perl program).

0
 
CleanupPingCommented:
rafahoro:
This old question needs to be finalized -- accept an answer, split points, or get a refund.  For information on your options, please click here-> http:/help/closing.jsp#1 
EXPERTS:
Post your closing recommendations!  No comment means you don't care.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.