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>