Hi everyone!
I'm doing my project related to socket programming. The send and receive part I got problem.
The code is below :
Server side:

printf("Handling client %s\n",inet_ntoa(their_addr.sin_addr));
if (send(new_fd, "Menu\n", 5, 0) == -1)     //(1)                          
	perror("send");
if(send(new_fd, "1. A.mp3, 2. B.mp3, C.mp3\n", 26,0) == -1)  //(2)
	perror("send");
if(send(new_fd, "Which file to play?\n", 20, 0) == -1)     //(3)
	perror("send");

Client side :

buf[numbytes] = '\0';
printf("%s",buf);
printf("Enter your song number : ");  //(4)
fflush(stdin);
gets(choice);

I mark the 4 lines for shorter writing.
Sometimes when server sends messages, the client can receive full of them(mean in the order (1) to (4) ). But sometimes it just receive the (1) line, then (4) and after that is (2) and (3). When this happens, I must close the server and client, run again, then it works.
My teacher said that this is caused by buffer. But exactly what I should do to make sure everytime the client will receive (1) to (4) respectively?
Thank for your help.

> fflush(stdin);
> gets(choice);
Nevermind the network stuff, how about getting the basics right?
fflush(stdin);
gets()

> send(new_fd, "Menu\n", 5, 0)
0, 1, 2, 3, 4 are also valid return results. You can't just assume that if it wasn't an error (-1), that the only other possible result must have been 5. If it wasn't 5, then it's YOUR job to call send() again with the remaining data.

> buf[numbytes] = '\0';
Show us how you declared buff, and how you called recv() to fill that buffer.

Ok...I show you the full code of client.

#define PORT 3490 // 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, rcvSize;  
	char buf[MAXDATASIZE];
	char choice[10];
	struct hostent *he;
	struct sockaddr_in their_addr; // connector's address information 

	if (argc != 2) {
	    fprintf(stderr,"usage: client hostname\n");
	    exit(1);
	}

	if ((he=gethostbyname(argv[1])) == NULL) {  // get the host info 
	    perror("gethostbyname");
	    exit(1);
	}

	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
	    perror("socket");
	    exit(1);
	}

	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);
	memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);

	if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof their_addr) == -1) {
	    perror("connect");
	    exit(1);
	}

	if ((numbytes=recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
	    perror("recv");
	    exit(1);
	}

	buf[numbytes] = '\0';

	printf("%s",buf);
	
	printf("Enter your song number : ");
	fflush(stdin);
	gets(choice);
	if(send(sockfd, choice, 7, 0) == -1)
		perror("send");

        return 0;
}

Also, I can't get you at this point :

send(new_fd, "Menu\n", 5, 0)
0, 1, 2, 3, 4 are also valid return results. You can't just assume that if it wasn't an error (-1), that the only other possible result must have been 5. If it wasn't 5, then it's YOUR job to call send() again with the remaining data.

Function send() is send(new_socket,buffer,bufsize,0);, so the third parameter is the length of the buffer, is it? Since the buffer is a string, so count the length and put it into the function.
It's not correct?

If you have

char buf[] = "hello";
int len = strlen( buff );

And you do n = send ( fd, buff, len, 0 ); You also need to do

if ( n < len ) {
  n = send( fd, buff[n], len-n, 0 );
}

Actually, use a while loop, as in

char buf[] = "hello";
int len = strlen( buf );
char *bp = buf;
while ( len > 0 ) {
  n = send( fd, bp, len, 0 );
  if ( n > 0 ) {
    // at least partly successful, advance through the buffer
    len -= n;
    bp += n;
  } else if ( n == 0 ) {
    // connection closed
  } else {
    // an error
  }
}

Over the loopback, or just over your LAN, you're unlikely to see this happen with small packets. But generally speaking, it's something you need to take care of.

The same is true of the recv(). The message may become fragmented, and it's up to you to reassemble it (say by looking for a \n).

Ok..Thank for your instruction. However, still one more thing, can you let me know the reason why, the client do not always receive full of messages from the server? (I need the messages come out in the below order :

Menu :
1. A.mp3    2.B.mp3       3.C.mp3
Which file to play?

and the last will be the client's line : "Enter your song number..."

But sometimes the 1st line come, then last line, and the middle lines come.

Do I need to do anything here?

I've no idea.
Being a stream, you either get stuff in the order you sent it, or you don't get it at all.

Like I said, make sure you're actually sending all the data with each send() call.

This article has been dead for over six months. Start a new discussion instead.