Solved

buffer problem? in send/recv

Posted on 2002-04-06
4
489 Views
Last Modified: 2008-02-01
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


0
Comment
Question by:rafahoro
4 Comments
 
LVL 16

Accepted Solution

by:
The--Captain earned 100 total points
Comment Utility
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
 

Expert Comment

by:CleanupPing
Comment Utility
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

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

I have seen several blogs and forum entries elsewhere state that because NTFS volumes do not support linux ownership or permissions, they cannot be used for anonymous ftp upload through the vsftpd program.   IT can be done and here's how to get i…
Note: for this to work properly you need to use a Cross-Over network cable. 1. Connect both servers S1 and S2 on the second network slots respectively. Note that you can use the 1st slots but usually these would be occupied by the Service Provide…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now