When does recv() return? - c

I have made a server and a client using sockets. My server is written in c and runs on my raspberry pi and my client is written in Swift and is running on my Mac/iPhone.
What i don't get is when my servers recv() function execute what i have sent from my client? If i send like 0-10 bytes it doesn't return from recv() function before i close the connection. But if I send 100+ bytes it executes immediately.
I would like my server to return from recv() every time i write a message from my client.
Here is my servers recv() function:
//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
printf("%s", client_message);
}
Here is my Clients write method:
func SendMsg(msg:String) -> Int{
return outputStream!.write(msg, maxLength: countElements(msg))
}
Everything works fine beside I'm not in control of when my server executes my messages.

Output to stdout is by default line buffered, so when using printf, make sure there is a newline character ('\n') at the end. If the message itself doesn't already contain a newline, then :
printf("%s\n", client_message);
As a side note : also make sure that client_message is properly null terminated before passing it to printf, or you might run into undefined behavior (ref. #JoachimPileborg's comment). If you can't ensure null termination, this would do the trick too :
printf("%.*s\n", read_size, client_message);

The server doesn't get the message because the client hasn't sent it.
You need to fflush the outputStream on the client side!

Related

Recv() (on client app) not receiving all messages sent from server . (IP/TCP)

enter image description hereI'm hoping to send messages of different lengths to a client while conserving messages' borders. To do that , the server sends a special message whenever the next message he's sending is of a different size.
Client Side , a realloc call on the receptive entity is made, which seems to be working alright.
the messages are sending correctly from the server (the return value of send() is not -1) , however, the recv on client side only reads a (random) number of letter , usually not receiving the last messages (up to 8 un-read but sent messages), but other times seem to be working perfectly. This doesn't always happen, and there is not particular pattern.
I've tried some tests, and found that recv (..., msg_peek) return value is -1 , while messages are being sent to the buffer.
I have used the flag MSG_PEEK on the receiving loop (while) .
while (recv(sock,message_rec,lg_attendue,MSG_PEEK)>0)
{
if (!Bal_Detection_Lettre(message_rec)) //detects a message containing info about the size of the next one
{
expected= Bal_Detection_Longueur_Message(message_rec, 30) ;
message_rec=(char *) realloc(message_rec , expected *sizeof(char));
printf("expected : %d\n" , expected);
recv(sock,message_rec,lg_attendue,0);
}
else {
recv(sock,message_rec,expected,0);
display_message(message_recu,expected) ; //function displaying the message
}
}
printf("expected : %d\n",expected) ;
}
the server side code is nothing special, and uses send() to send messages before closing the connexion.

Server TCP stuck on read()

I'm trying to get a server to receive messages from a client in TCP.
The problem is, I only receive the messages on the server side once I close the socket on the client side.
Here is the read function on the server side:
char *read_socket(int fd){
int bytesRcvd, aux;
char *buffer=(char*)malloc(BUFFSIZE*sizeof(char));
bytesRcvd=read(fd, buffer , BUFFSIZE);
aux=bytesRcvd;
while(bytesRcvd>0){
if((bytesRcvd = read(fd, &buffer[aux], BUFFSIZE))<0){
printf("read() failed!: %s\n", strerror(errno));
exit(1);
}
aux+=bytesRcvd;
}
return &buffer[0];
}
I know (by printfs) that it gets stuck on the line:
bytesRcvd = read(fd, &buffer[aux], BUFFSIZE)
Any help will be greatly appreciated.
Your program is reading the data in the line:
bytesRcvd = read(fd, &buffer[aux], BUFFSIZE)
Your while loop receives the data that the client sends. If the client doesn't have data to send read will block until the connection is closed where read will return 0 and you will exit from while loop.
This is the reason that you think that the data are send in the end (when connection is closed). This is not right, if you print the data you read in the while loop you will see them immediately and not all of them in the end.
Though you can't return the data before the connection is closed due to read() blocking.
For one client your program may seems ok if you don't have the problem of getting data at the end (as I said you could just print them inside while loop) but imagine have two or more clients then you would firstly close connection with first client to go on and read data from second and so on.
One solution(to both problems) is to use select() system call, this will go on to read only if there are data.( Though select() is not safe when using fork()- doesn't guarantee that a parent of child process will not block in read() ).

String comparison after transfer through TCP socket in C

I am sending a file through TCP, and have the server sending a message containing "END_OF_MESSAGE" to alert the client that they have received the whole file and can close the socket. The file is being sent, and the client receives the "END_OF_MESSAGE" string, however, when I use strcmp to compare the received information to "END_OF_MESSAGE", it never says that they match. I have tried strncmp and memcmp but am confused as to why strcmp does not tell me the strings match.
Code snippets:
Server:
char endMessage[MESSAGESIZE] = "END_OF_MESSAGE";
if ((send(clntSocket, endMessage, sizeof endMessage, 0))!= sizeof endMessage) DieWithError("Sending failed");
The above code snippet does get sent.
Client:
if ((bytesRcvd = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)
DieWithError("recv() failed or connection closed prematurely");
totalBytesRcvd += bytesRcvd; /* Keep tally of total bytes */
echoBuffer[bytesRcvd] = '\0'; /* Terminate the string! */
if (!(strcmp(echoBuffer, "END_OF_MESSAGE")==0)){
printf(echoBuffer); /* Print the echo buffer */
printf("\n");
}else{
break; //break out of while loop
}
the strcmp of the echoBuffer and "END_OF_MESSAGE" never returns 0, even though "END_OF_MESSAGE" is what I am sending from the server..I have tried strncmp to compare the first 3 characters ("END") to no avail.
Note: when I print out the echoBuffer, the very last one does print out END_OF_MESSAGE which is just adding to my confusion.
Does anyone have any insights into what I am doing wrong?
Thank you.
am sending a file through TCP, and have the server sending a message containing "END_OF_MESSAGE" to alert the client that they have received the whole file and can close the socket.
Why? Just close the socket. That will tell the client exactly the same thing..
What you're attempting is fraught with difficulty. What happens if the file contains END_OF_MESSAGE? You're going to need an escape convention, and an escape for the escape, and inspect all the data when both sending and receiving.
The actual problem that you're seeing is that END_OF_MESSAGE can arrive along with the last bit of the file, so it isn't at the start of the buffer.
But it's all pointless. Just close the socket.

Two way socket communication

I'm trying to write a simple two way socket communication using C. So far, the main while loop for my client.c file looks like this:
while ( gets(str) != NULL ) {
sSize = send(s, str, strlen(str), 0);
if ( len != strlen(str) ) {
exit(1);
}
else {
rSize = recv(s, buffer, 64, 0);
buf[rSize] = '\0';
printf("%s\n", buffer);
}
}
while loop in sever.c looks like this:
while ( 1 ) {
gets(str);
send(p, str, strlen(str), 0);
rSize = recv(p, buffer, 32, 0);
if ( rSize < 0 ) {
exit(1);
}
buf[len] = '\0';
else{
printf("%s\n", buffer);
}
}
The program compiles normally and I can establish connection between both machines, but when I send message either from client or server, I get an anomaly:
Sending message 'hi' from client
client -------------------------- server
hi
If I go to server to send 'you' message, I get:
client -------------------------- server
hi
you
you hi
Not sure exactly how this is, but what I'm trying to achieve is that, whenever message is sent from either client or server, it should display immediately on the other side.
Please note that gets() is a blocking function. Initially both client and server are blocked in gets() waiting for input. When you type 'hi' on client, it sends this to the server which is still blocked on gets.
After sending hi, the client blocks on recv() call, waiting for message from server. On the other side, server hasn't still received the 'hi' message send by the client.
When you type 'you' on the server, it comes out of gets() and sends 'you' to client. After that the server calls recv() and reads the 'hi' sent by the client. Since the client is already waiting in recv(), it reads 'you' sent by the server.
Thus the program is working absolutely the way it has been implemented. Please mention your object, not sure what do you want to achieve.

Sending data to and from using sockets in c

I am working on an program for school and having some issues with sockets. I have pasted the write and read commands from my program below since I think these are the problem. The program should take the plaintext file and encrypt it using the key provided.
MY PROBLEM: When I execute the program using "client [plaintext] [key] [port]" the program returns "Reading data from client -- 140 bytes" and then just hangs. I can hit ctrl-c and the program prints the correct output for ptext and ktext and that 37 bytes were sent back to the client (which is the correct number of bytes). I feel like the encrypted text should print as well but it does not.
TWO QUESTIONS:
1) Why does the program hang?
2) Why does it seem like data is written from the server to the client but the client does not read any of the data?
Thank you in advance for any help you can offer.
CLIENT
n = write(sockfd,ptext,strlen(ptext));
bzero(crypt_text, BUF_MAX);
bzero(buffer, BUF_MAX);
while((n = read(sockfd,buffer,BUF_MAX))>0){
printf("Reading data from Server -- %d bytes\n",n);
strcat(crypt_text, buffer);
bzero(buffer,BUF_MAX);
}
if (n < 0){
error("ERROR reading from socket");
}
printf("%s", crypt_text);
SERVER
while((n = read(newsockfd,buffer,512))>0){
printf("Reading data from client -- %d bytes\n",n);
strcat(full_text, buffer);
bzero(buffer,BUF_MAX);
}
if (n < 0){
error("ERROR reading from socket");
}
bzero (ptext,BUF_MAX);
bzero (ktext, BUF_MAX);
strcpy(ptext, strtok(full_text,"["));
strcpy(ktext, strtok(NULL, "["));
printf("ptext length ==%s %d\n\n",ptext,strlen(ptext)); //Prints the correct plain text
printf("ktext length ==%s %d\n\n",ktext,strlen(ktext)); //prints the correct key
crypt_text = encrypt(ptext, ktext);
n = write(newsockfd,crypt_text,strlen(crypt_text));
printf("WRITE TO CILENT ==== %d",n); //This returns the correct number of bytes that should be sent back to client
if (n < 0){
error("ERROR writing to socket");
}
As is, your client and server will always hang waiting for each other. This is because read() blocks by default until new data is available to fetch from the file (in this case, a socket).
Look carefully at the code:
The client writes once into the socket before entering the read loop
The server only reads from the socket (well, further down there is a write(), but it will never reach it). The first time the loop runs on the server, it will read the data that the client initially wrote into the socket.
The server processes the data it just read and concatenates it to full_text. Then it goes back to the loop condition, where it calls read() again. read() blocks because there is nothing else to read from the socket at this point.
The client enters a similar loop where it attempts to read from the socket, expecting messages from the server.
At this point, both the server and the client are blocked waiting for messages from each other, which will never happen.
Tu put it another way: you only wrote to the socket once, and somehow you expect to read it multiple times.
You have to rethink your design. Go back to the problem description, work your way through a simple protocol, dry run it on paper, and then implement it - that's how it's done in the real world :)
There are other bugs in your code. For example you write this:
strcat(full_text, buffer);
But buffer is not NUL terminated. n bytes have been read, the rest of the buffer is indeterminate. You should set a '\0' byte at offset n and only try reading BUF_MAX-1 bytes to keep a byte available for all cases and do this:
buffer[n] = '\0';
strcat(full_text, buffer);
Furthermore, you do not test if there is enough room available in full_text for the n+1 bytes strcat will copy at the end.
On another front, packets can be sliced and diced into chunked of different sizes when received by the server. Buffering is required to ensure a reliable client / server communication. To enable this buffering, you need to devise a protocol to determine when a packet has been fully received: a simple protocol is to transmit lines terminated by '\n'.

Resources