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