I have a client/server program.
Client does the following in a loop.
Server does the following in a loop.
For some iterations this works fine, after approx 10 iterations only string2 is seen to be read on both client and server. Why this so? Also, in in client program in while() loop if read() is called after 2nd write() everything works fine.
In client, from second iteration read() should return the whole data in pipe because pipe does not have message boundaries. But it just reads only the data written by 1 write() call in server.
Below is my code for reference.
server.c
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
int main()
{
client_to_server;
char *myfifo = "/tmp/client_to_server_fifo";
int server_to_client;
char *myfifo2 = "/tmp/server_to_client_fifo";
char buf[BUFSIZ];
/* create the FIFO (named pipe) */
mkfifo(myfifo, 0666);
mkfifo(myfifo2, 0666);
/* open, read, and display the message from the FIFO */
client_to_server = open(myfifo, O_RDONLY);
server_to_client = open(myfifo2, O_WRONLY);
printf("Server ON bufsize=%d.\n", BUFSIZ);
while (1)
{
read(client_to_server, buf, BUFSIZ);
if (strcmp("exit",buf)==0)
{
printf("Server OFF.\n");
break;
}
else if (strcmp("",buf)!=0)
{
printf("Received: %s\n", buf);
printf("Sending back...\n");
write(server_to_client,buf,BUFSIZ);
}
/* clean buf from any data */
memset(buf, 0, sizeof(buf));
}
close(client_to_server);
close(server_to_client);
unlink(myfifo);
unlink(myfifo2);
return 0;
}
client.c
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include<string.h>
int main()
{
int client_to_server;
char *myfifo = "/tmp/client_to_server_fifo";
int server_to_client;
char *myfifo2 = "/tmp/server_to_client_fifo";
char str[BUFSIZ];
/* write str to the FIFO */
client_to_server = open(myfifo, O_WRONLY);
server_to_client = open(myfifo2, O_RDONLY);
char buf1[30] = "str1";
char buf2[30] = "str2";
while(1){
//write first string
write(client_to_server, buf1, sizeof(buf1));
read(server_to_client,str,sizeof(str));
perror("Read:"); // Very crude error check
printf("...received from the server: %s\n",str);
memset(str, '\0', sizeof(str));
//write second string
write(client_to_server, buf2, sizeof(buf2));
}
close(client_to_server);
close(server_to_client);
return 0;
}
Below is the output: Server output: Server ON bufsize=8192. Received: str1 Sending back... Received: str2 Sending back... Received: str1 Sending back... Received: str2 Sending back... Received: str1 Sending back... Received: str2 Sending back... Received: str1 Sending back... Received: str2 Sending back... Received: str1 Sending back... Received: str2 Sending back... Received: str1 Sending back... Received: str2 Sending back... Received: str1 Sending back... Received: str2 Sending back... Received: str1 Sending back... Received: str2 Sending back... Received: str1 Sending back... Received: str2 Sending back... Received: str1 Sending back... Received: str2 Sending back... Received: str2 Sending back... Received: str2 Sending back... Received: str2 Sending back... Received: str2 Sending back... Received: str2 Sending back... Received: str2 Sending back... Received: str2
Below is the output from client: ...received from the server: str1 ...received from the server: str2 ...received from the server: str1 ...received from the server: str2 ...received from the server: str1 ...received from the server: str2 ...received from the server: str1 ...received from the server: str2 ...received from the server: str1 ...received from the server: str2 ...received from the server: str1 ...received from the server: str2 ...received from the server: str1 ...received from the server: str2 ...received from the server: str1 ...received from the server: str2 ...received from the server: str1 ...received from the server: str2 ...received from the server: str1 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2 ...received from the server: str2
The short answer is the client and server receive "str2\0str1\0" but print just up to the first \0, i.e. "str2".
The long answer is on the client side that you send not just strings "str1" and "str2" but also the terminating NUL:
write(client_to_server, buf1, sizeof(buf1));
The sizeof here returns the length of the string plus terminating NUL.
Now the server side. You read up to BUFSIZ bytes. So if the client is fast enough to send few strings, i.e. "str2\0str1\0" you will read all strings in one go. To fix this you have to take into account what the read returns, i.e.:
ssize_t ret = read(client_to_server, buf, BUFSIZ);
printf("Received: size %zd\n", ret); // print the size
fwrite(buf, 1, ret, stdout); // print the buffer with NULs
write(server_to_client,buf,ret); // write back just the data you actually received