Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Oct 2000 23:06:14 -0700
From:      "Justin C. Walker" <justin@apple.com>
To:        "'freebsd-net@freebsd.org'" <freebsd-net@freebsd.org>
Subject:   Re: Socket programming, strange recv reaction
Message-ID:  <200010240606.XAA03131@scv1.apple.com>

next in thread | raw e-mail | index | archive | help
A quick check shows that you're sending 128 bytes each time around the =
server loop, but only reading 100 bytes around the receiver loop.  =
Therefore, you fall behind by 28 bytes each time.  Since the "non =
message" bytes are likely to be zero, you appear to be reading no bytes =
(when you print the string in 'buf', the first character is 'nul').

If you examine the received buffer with gdb, you'll see that your =
message arrives, but it is offset because of the difference between =
bytes sent and bytes read.

Regards,

Justin

On Monday, October 23, 2000, at 05:10 PM, TAZ Gravel, Emmanuel wrote:

> I'm trying to write a small client-server pair using TCP sockets.=20
> I'm not changing the default blocking mechanisms for recv().=20
> The client connects to the server, which sends it a welcome=20
> message. Then, the client sends ASCII "commands" that are=20
> interpreted by the server (recv'ed, strcmp'ed and answered to).=20
> If the command is "unknown" it echoes it back to the client=20
> using send(). The client, on the other end, is "waiting" with a=20
> recv().=20
> =20
> Appart from the first message sent by the client, most others=20
> were never echoed back to the client, and when one arrived, it=20
> was from a previous message, anywhere between 2 and 8 iterations=20
> previous to the one that was just sent. Using ethereal to analyze=20
> the traffic, and blocking the server with a 5 second sleep, showed=20
> that the recv in the client was accepting a simple ACK message=20
> as an acceptable message. The "conversation" is all [PSH, ACK]=20
> or [ACK]. Ethereal was set to look at the loopback interface to=20
> see this happening, and for some reason all packets were=20
> "duplicated" (same time frame, same exact packet, always in=20
> pairs). Don't know if this has anything to do with it or not=20
> though.=20
> =20
> I know the problem centers around the recv in the client, however=20
> I don't know where to look. Just starting to look at socket=20
> programming, and using tutorials and newbie code found online=20
> (using Beej's Guide to Network Programming right now).=20
> =20
> Read the man page for recv() also, and since it's supposed to=20
> be blocking until something is recieved, I don't know what to=20
> make of this.=20
> =20
> Inlining my code since I'm using Outlook right now...=20
> =20
> Thanks for your help!=20
> =20
> Emmanuel=20
> =20
> <server code>=20
> #include <stdio.h>=20
> #include <stdlib.h>=20
> #include <errno.h>=20
> #include <signal.h>=20
> #include <string.h>=20
> #include <unistd.h>=20
> #include <sys/types.h>=20
> #include <netinet/in.h>=20
> #include <sys/socket.h>=20
> #include <sys/wait.h>=20
> #include <arpa/inet.h>=20
> =20
> #define MYPORT 4039    /* the port users will be connecting to */=20
> =20
> #define MAXBUFLEN 128=20
> =20
> #define BACKLOG 10     /* how many pending connections queue will hold =
*/=20
> #define MAXCHILD 5=20
> =20
> /* Global variables */=20
> =20
> int sockfd; /* listen on sock_fd */=20
> int child[MAXCHILD];=20
> =20
> =20
> void usage(newfd)=20
>      int newfd;=20
> {=20
>   char *msg;=20
>   int numbytes;=20
>   printf("Sending usage information.\n");=20
>   msg =3D "Usage:\n\thello: returns a message.\n\tquit: exits the =
session.\n";=20
>   if ((numbytes =3D send(newfd, msg, MAXBUFLEN, 0)) =3D=3D -1) {=20
>     perror("send");=20
>     exit(1);    =20
>   }=20
>   printf("Sent [%i] bytes.\nMessage sent is %s\n",numbytes,msg);=20
> }=20
> =20
> void hello(newfd,buf)=20
>      int newfd;=20
>      char *buf;=20
> {=20
>   char msg[128] =3D "You said: ";=20
>   int numbytes;=20
>   printf("Entering hello \n");=20
>   printf("Replying to [%s].\n",buf);=20
>   strcat(msg,buf);=20
>   printf("first strcat\n");=20
>   strcat(msg,"\n");=20
>   printf("sending message now\n");=20
>   sleep(5);=20
>   if ((numbytes =3D send(newfd, msg, MAXBUFLEN, 0)) =3D=3D -1) {=20
>     perror("send");=20
>     close(newfd);=20
>     exit(1);=20
>   }=20
>   printf("Sent [%i] bytes.\nMessage sent is [%s]\n",numbytes,msg);=20
> }=20
> =20
> void bye(newfd)=20
>      int newfd;=20
> {=20
>   /* signal(SIGINT, finalize); */=20
>   /* Only usefull in programs not exiting after signal trap */=20
>   char *msg;=20
>   msg =3D "Closing connection. Goodbye!\n";=20
>   printf("in bye\n");=20
>   if (send(newfd, msg, sizeof(msg), 0) =3D=3D -1) {=20
>     printf("error in sending\n");=20
>     perror("send");=20
>     close(newfd);=20
>     exit(1);=20
>   }=20
>   printf("closing now\n");=20
>   close(newfd);=20
>   printf("Closing connection. Child PID is [%i]. \n",getpid());=20
>   exit(0);=20
> }=20
> =20
> void finalize()=20
> {  =20
>   printf("Closing all connections\n");=20
>   while(waitpid(-1,NULL,0) > 0); /* clean up all child processes */=20
>   close(sockfd);=20
>   exit(0);=20
> }=20
> =20
> =20
> int main()=20
> {=20
>     int new_fd;  /* new connection on new_fd */=20
>     int sin_size;=20
>     struct sockaddr_in my_addr;    /* my address information */=20
>     struct sockaddr_in their_addr; /* connector's address information =
*/=20
>     int numberbytes;=20
>     /*    int i, addre_len; */=20
>     char buf[MAXBUFLEN];=20
>     unsigned short int children;=20
> =20
>     if ((sockfd =3D socket(AF_INET, SOCK_STREAM, 0)) =3D=3D -1) {=20
>         perror("socket");=20
>         exit(1);=20
>     }=20
> =20
>     signal(SIGINT, finalize);=20
> =20
>     my_addr.sin_family =3D AF_INET;         /* host byte order */=20
>     my_addr.sin_port =3D htons(MYPORT);     /* short, network byte =
order */=20
>     my_addr.sin_addr.s_addr =3D INADDR_ANY; /* automatically fill with =
my IP=20
> */=20
>     bzero(&(my_addr.sin_zero), 8);        /* zero the rest of the =
struct */=20
> =20
>     if (bind(sockfd, (struct sockaddr *)&my_addr,=20
>              sizeof(struct sockaddr)) =3D=3D -1) {=20
>         perror("bind");=20
>         exit(1);=20
>     }=20
> =20
>     if (listen(sockfd, BACKLOG) =3D=3D -1) {=20
>         perror("listen");=20
>         exit(1);=20
>     }=20
> =20
>     children =3D 0;=20
> =20
>     while(1) {  /* main accept() loop */=20
>         sin_size =3D sizeof(struct sockaddr_in);=20
> 	=20
> 	if (children < MAXCHILD) {=20
> 	  if ((new_fd =3D accept(sockfd,=20
>                                (struct sockaddr *)&their_addr,=20
>                                &sin_size)) =3D=3D -1) {=20
> 	    perror("accept");=20
> 	    continue;=20
> 	  }=20
> 	  printf("server: got connection from [%s]\n",=20
>                   inet_ntoa(their_addr.sin_addr));=20
> 	  if (!fork()) { /* this is the child process */=20
> 	    /* Anything that happens here is only executed by the child,=20=

> 	     * and that's the only thing that the child executes. */=20
>             if (send(new_fd,=20
>                      "Welcome to my world!\nWhat is your pleasure?\n",=20=

>                      44, 0) =3D=3D -1) {=20
> 	      perror("send");=20
> 	      close(new_fd);=20
> 	      exit(1);=20
> 	    }=20
> 	    =20
> 	    while(1) {=20
> 	      =20
> 	      if ((numberbytes =3D recv(new_fd,buf,MAXBUFLEN,0)) =3D=3D =
-1) {=20
> 		perror("recv");=20
> 		continue;=20
> 	      }=20
> 	      =20
> 	      buf[numberbytes] =3D '\0';=20
> =20
> 	      printf("numberbytes =3D [%i]\nbuffer =3D =
[%s]\n",numberbytes,buf);=20
> 	      =20
> 	      if(!strcmp(buf, "")) {=20
> 		printf("printing usage\n");=20
> 		usage(new_fd);=20
> 	      }=20
> 	      else if(!strncmp(buf, "quit", 4)) {=20
> 		printf("calling bye\n");=20
> 		bye(new_fd);=20
> 	      }=20
> 	      else {=20
> 		printf("calling hello\n");=20
> 		hello(new_fd,buf);=20
> 	      }=20
> 	    }=20
> 	  }=20
> 	}=20
>         /* clean up all child processes */=20
>         while(waitpid(-1,NULL,WNOHANG) > 0);=20
>     }=20
> }=20
> =20
> <client code>=20
> #include <stdio.h>=20
> #include <stdlib.h>=20
> #include <errno.h>=20
> #include <string.h>=20
> #include <netdb.h>=20
> #include <unistd.h>=20
> #include <sys/types.h>=20
> #include <netinet/in.h>=20
> #include <sys/socket.h>=20
> #include <sys/wait.h>=20
> #include <arpa/inet.h>=20
> =20
> #define PORT 4039    /* the port client will be connecting to */=20
> =20
> #define MAXDATASIZE 100 /* max number of bytes we can get at once */=20=

> =20
> int main(int argc, char *argv[])=20
> {=20
>   int sockfd, numbytes;  =20
>   char buf[MAXDATASIZE],msg[MAXDATASIZE] =3D "sta";=20
>   struct hostent *he;=20
>   struct sockaddr_in their_addr; /* connector's address information */=20=

> =20
>   /*  printf("Before init\n");=20
>    */=20
>   if (argc !=3D 2) {=20
>     fprintf(stderr,"usage: manuclient hostname\n"); /* put actual =
error=20
> message here */=20
>     exit(1);=20
>   }=20
>   =20
>   /*printf("Before gethostbyname\n");=20
>    */=20
>   if ((he=3Dgethostbyname(argv[1])) =3D=3D NULL) {  /* get the host =
info */=20
>     perror("gethostbyname");=20
>     exit(1);=20
>   }=20
>   =20
>   /*printf("Host is %s\nBeofre socket creation\n", *((struct in_addr=20=

> *)he->h_addr));=20
>    */=20
>   if ((sockfd =3D socket(AF_INET, SOCK_STREAM, 0)) =3D=3D -1) {=20
>     perror("socket");=20
>     exit(1);=20
>   }=20
>   =20
>   /* printf("Socket created. Before socket connection.\n");=20
>    */=20
>   their_addr.sin_family =3D AF_INET;         /* host byte order */=20
>   their_addr.sin_port =3D htons(PORT);     /* short, network byte =
order */=20
>   their_addr.sin_addr =3D *((struct in_addr *)he->h_addr);=20
>   bzero(&(their_addr.sin_zero), 8);        /* zero the rest of the =
struct */=20
> =20
>   if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct=20
> sockaddr)) =3D=3D -1) {=20
>     perror("connect");=20
>     exit(1);=20
>   }=20
>   =20
>   /*printf("Socket connected. Before while loop, value is=20
> %i\n",strcmp(msg,"quit"));=20
>    */=20
>   while(strcmp(msg,"quit")) {   /* Begin chat routine with the server =
*/=20
> =20
>     printf("Before recv\n");=20
>     /*sleep(5);*/=20
> =20
>     if ((numbytes=3Drecv(sockfd, buf, MAXDATASIZE, 0)) =3D=3D -1) {=20
>       perror("recv");=20
>       exit(1);=20
>     }=20
> =20
>     printf("After recv\n");=20
> =20
>     buf[numbytes] =3D '\0';=20
>     =20
>     printf("Received: %s\n",buf);=20
>     =20
>     printf("Command > ");=20
>     =20
>     scanf("%s",msg);=20
> =20
>     /*   if (sizeof(msg) >=3D MAXDATASIZE)=20
>       msg[MAXDATASIZE] =3D '\0';=20
>     */=20
>     printf("Size of message is %i\n",sizeof(msg));=20
> =20
>     if ((numbytes =3D send(sockfd, msg, MAXDATASIZE, 0)) =3D=3D -1) {=20=

>       perror("send");=20
>       exit(1);=20
>     }=20
>     =20
>     printf("sent message %s to %s\nNumber of bytes sent is=20
> %i\n",msg,inet_ntoa(their_addr.sin_addr),numbytes);=20
>     =20
>     if(!strcmp(msg,"quit"))=20
>       printf("Recieved quit command, exiting!\n");=20
>     =20
>   }=20
> =20
>   close(sockfd);=20
>   =20
>   return 0;=20
> }=20
> =20

Justin C. Walker, Curmudgeon-At-Large   *
Institute for General Semantics         |
Manager, CoreOS Networking              |   When LuteFiske is outlawed
Apple Computer, Inc.                    |   Only outlaws will have
2 Infinite Loop                         |       LuteFiske
Cupertino, CA 95014                     |
=
*---------------------------------------*-------------------------------*


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200010240606.XAA03131>