simple client/server program using named pipes in linux - c++

I am trying to write a program that has two separate process that talk via named pipes. The client which sends a message to a server, and the server which needs to broadcast that message to all clients attached to it. So far, I can get a connection between the two, but I cannot get more than one message to work no matter what I have tried. Below is the code I have written that will allow a connection and transmission of a single message.
server.cpp:
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#define FIFO_FILE_1 "/tmp/client_to_server_fifo"
#define FIFO_FILE_2 "/tmp/server_to_client_fifo"
int main()
{
int client_to_server;
int server_to_client;
char buf[BUFSIZ];
/* create the FIFO (named pipe) */
mkfifo(FIFO_FILE_1, 0666);
mkfifo(FIFO_FILE_2, 0666);
printf("Server ON.\n");
while (1)
{
/* open, read, and display the message from the FIFO */
client_to_server = open(FIFO_FILE_1, O_RDONLY);
server_to_client = open(FIFO_FILE_2, O_WRONLY);
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);
}
close(client_to_server);
close(server_to_client);
unlink(FIFO_FILE_1);
unlink(FIFO_FILE_2);
return 0;
}
client.cpp:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <wait.h>
#include <string.h>
#define FIFO_FILE_1 "/tmp/client_to_server_fifo"
#define FIFO_FILE_2 "/tmp/server_to_client_fifo"
int main()
{
system("clear");
int client_to_server;
int server_to_client;
char str[140];
printf("Input message to server: ");
scanf("%139[^\r\n]", str);
/* write str to the FIFO */
client_to_server = open(FIFO_FILE_1, O_WRONLY);
server_to_client = open(FIFO_FILE_2, O_RDONLY);
if(write(client_to_server, str, sizeof(str)) < 0){
perror("Write:");//print error
exit(-1);
}
if(read(server_to_client,str,sizeof(str)) < 0){
perror("Read:"); //error check
exit(-1);
}
printf("\n...received from the server: %s\n\n\n",str);
close(client_to_server);
close(server_to_client);
/* remove the FIFO */
return 0;
}

close(client_to_server);
close(server_to_client);
Remove these lines from while loop because when server has done its work for the first time it will close the pipe and you cant be able to proceed further in pipes.

Related

read and write doesn't work in named pipes c++

Please excuse my English, its not the best. Thank you.
I am suppose to write 2 simple programs, which are suppose to enable two communication between processes in/with named pipes(C++).
Each code search through the directory and (name of the directory is suppose to be inputed by a user) search for FIFO file type. After finding a file, first code opens to read, second code opens to write. If process can't find a file, then it will ask user to input a new path.
First code write the message in the terminal(stdin) and send it through the pipe to second process. Second process read the message from the pipe and shows it in terminal(stdout). Both processes are suppose to end after reading message from stdin and sending a statement 'END';
I am still learning and trying to find more about named pipes so for now I could only write some basics programs(just to read and write) but still I don't understand why both of them doesn't work.
Can You tell me what is wrong with my codes? Thank You.
here is my code for read
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
char sentence [256];
int fp, numr ,numop;
umask(0);
fp = mkfifo("myfifo", S_IFIFO|0666);
if(fp < 0)
{
printf("Cant make a file\n");
return 1;
}
numop = open("myfifo",O_RDONLY);
if(numop < 0)
{
printf("Cant open the file\n");
return 1;
}
numr = read(fp,&sentence,sizeof(sentence));
if( numr < 0)
{
printf("Cant read the message\n");
return 1;
}
fgets(sentence,256,stdin);
printf("Message: %s\n",sentence);
close(fp);
return 0;
}
here is for write
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int fd , numw;
char sentence [256];
fd = open("myfifo", O_WRONLY);
if(fd < 0)
{
printf("Can't open a file\n");
return 1;
}
printf ("Enter the message : ");
fgets(sentence,250,stdin);
numw = write(fd,sentence,strlen(sentence)+1);
if(numw < 0)
{
printf("Can write the message");
return 1;
}
close(fd);
return 0;
}
can you tell me what am I doing wrong?

QSerialPort cannot open with error code 11

I'm trying to communicate with a device which provided a serial port. When I use the example C program provided by the device producer, it was successfully connected and I can send/receive data. But when I use my C++ program with QSerialPort, the open() method returned false and the error() returned 11 (An unidentified error occurred, as described by Qt documentation). Could anyone please help me?
OS: Cent OS 6.9
gcc/g++: 4.8
Qt: 5.6.0
An example of connecting with QSerialPort:
#include <qserialport.h>
#include <qstring.h>
int main(int argc, const char *argv[])
{
QString portName = "/dev/corser/x64ExpCL4x1_s0";
QSerialPort *pSerial = new QSerialPort();
pSerial->setPortName(portName);
pSerial->setBaudRate(QSerialPort::Baud9600);
pSerial->setParity(QSerialPort::NoParity);
pSerial->setDataBits(QSerialPort::Data8);
pSerial->setStopBits(QSerialPort::OneStop);
pSerial->setFlowControl(QSerialPort::NoFlowControl);
bool success = pSerial->open(QIODevice::ReadWrite);
if (!success) {
printf("Error: %d\n", pSerial->error());
} else {
printf("Success.\n");
pSerial->close();
}
delete pSerial;
return 0;
}
This program prints out Error: 11.
Here is a C program which is excerpted from the device's example program. This program just try to connect the serial port and then close the connection. While the original example program is complicated. It is actually kind of a "Terminal" program which sends user-input commands to the device and prints out the responses from the device.
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <ctype.h> /* Character types */
#define TRUE 1
#define FALSE 0
typedef struct
{
int open; // Flag for current open status of port
int update; // Flag indicating parameter changes
char *port; // Current port to be opened
int iod; // I/O index for open device port
struct termios stty; // Terminal port control structure
} SCOM_CTL;
struct termios ttctl = {0};
struct termios ttsav = {0};
struct termios coctl = {0};
struct termios cnctl = {0};
#define OPEN 1
#define CLOSE 2
#define UPDATE 3
#define NO_UPDATE 4
SCOM_CTL scom;
int main( int argc, char **argv )
{
scom.port = "/dev/corser/x64ExpCL4x1_s0";
scom_init();
scom_open_port();
if (scom.open == OPEN)
{
fputs("\rSuccess.\r\n", stdout);
scom_close_port(scom.iod);
}
else
{
fputs("\rError.\r\n", stdout);
}
}
// Initialize the console (stdin) for raw access.
int scom_init()
{
int i;
scom.open = CLOSE;
scom.update = NO_UPDATE;
scom.iod = -1;
tcgetattr(0, &coctl); // Save a copy to restore stdin.
tcgetattr(0, &cnctl);
cfmakeraw( &cnctl); // Set stdin to raw !
tcsetattr(0, 0, &cnctl);
}
int scom_open_port()
{
int i, iod;
if (scom.open == OPEN)
{
close(scom.iod);
scom.open = CLOSE;
}
if ( (iod = open( scom.port, (O_RDWR | O_NOCTTY))) == -1)
{
conres(); /* Reset the console. */
fputs("term : Open Failure on device\n", stdout);
return -1;
}
scom.iod = iod;
scom.open = OPEN;
scom.update = NO_UPDATE;
}
int scom_close_port()
{
scom.open = CLOSE;
close(scom.iod);
}
int conres()
{
return(tcsetattr(0, 0, &coctl));
}
This program prints out Success.

c++ pipe buffering disable

How to disable buffering in pipe. I'm creating a simple recorder/player for I/O. To do this I need record output witch time delays.
To record delays, I need something like this
example tekst
"wait 1s"
example tekst
"wait 1s"
example tekst
...
but if I use
pipe2(in, O_DIRECT );
i see something like this
"wait 100s"
"100 times" example tekst
"wait 100s"
"100 times" example tekst
...
man7 tells:
O_DIRECT (since Linux 3.4)
Create a pipe that performs I/O in "packet" mode. Each
write(2) to the pipe is dealt with as a separate packet, and
read(2)s from the pipe will read one packet at a time.
I tried to disable buffering, by:
fcntl(in[1], F_SETPIPE_SZ, 1);
but it's still not working.
read.cpp
#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <assert.h>
bool keep = true;
void intHandler(int dummy) {
keep = 0;
}
int main(void) {
signal(SIGINT, intHandler);
int in[2];
int out[2];
int pid;
int fo;
char buf[1024];
pipe2(in, O_DIRECT );
pipe2(out, O_DIRECT );
pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) {
close(in[0]);
close(out[1]);
close(0);
close(1);
dup2(in[1], 1);
dup2(out[0], 0);
close(in[1]);
close(out[0]);
sleep(1);
char *newargv[] = {"/root/Pulpit/a1", NULL, NULL, NULL};
char *newenviron[] = {NULL};
int ret = execve("/root/Pulpit/a1", newargv, newenviron);
printf("%d", ret);
return 0;
} else {
close(out[0]);
close(in[1]);
int n = 0;
while (keep) {
int wyn = read(in[0], buf, 1024);
if (wyn > 0) {
char aa[1024];
write(1, buf, wyn);
fsync(1);
}
}
}
return (0);
}
a1.cpp
#include <cstdlib>
#include <unistd.h>
#include "stdio.h"
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
while(true){
printf("example text\n");
usleep(100000);
}
return 0;
}

How to create pty that is connectable by Screen app in Linux

I wanted to create C/C++ application, that creates new (virtual) device in /dev/xxx and will be able to connect with 'screen' application.
For example program running in loop, that creates new /dev/ttyABC. Then I'll use 'screen /dev/ttyABC', and when I send there some chars, then app send it back to the 'screen'.
I really don't know where start. I found some referencies on pty library but I don't even know, if I have right direction.
Could you help me? Where to look? Post example?
Thanks
You could use a Pseudoterminal via openpty to achieve this. openpty returns a pair of file descriptors (master and slave pty devices) that are connected to each other via their stdout / stdin. The output of one will appear at the input of another and vice-versa.
Using this (rough!) example...
#include <fcntl.h>
#include <cstdio>
#include <errno.h>
#include <pty.h>
#include <string.h>
#include <unistd.h>
int main(int, char const *[])
{
int master, slave;
char name[256];
auto e = openpty(&master, &slave, &name[0], nullptr, nullptr);
if(0 > e) {
std::printf("Error: %s\n", strerror(errno));
return -1;
}
std::printf("Slave PTY: %s\n", name);
int r;
while((r = read(master, &name[0], sizeof(name)-1)) > 0) {
name[r] = '\0';
std::printf("%s", &name[0]);
}
close(slave);
close(master);
return 0;
}
... Echoing some text (in another terminal session) to the slave pty sends it to master's input. E.g. echo "Hello" > /dev/pts/2
Based on the answer provided by #gmbeard , I was able to create an echo PTY device and connect to it with screen and minicom. What made the difference was using a raw PTY device by initializing a termios struct.
Here is the code
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <cstdio>
#include <pty.h>
#include <termios.h>
#define BUF_SIZE (256)
int main(int, char const *[])
{
int master, slave;
char buf[BUF_SIZE];
struct termios tty;
tty.c_iflag = (tcflag_t) 0;
tty.c_lflag = (tcflag_t) 0;
tty.c_cflag = CS8;
tty.c_oflag = (tcflag_t) 0;
auto e = openpty(&master, &slave, buf, &tty, nullptr);
if(0 > e) {
std::printf("Error: %s\n", strerror(errno));
return -1;
}
std::printf("Slave PTY: %s\n", buf);
int r;
while ( (r = read(master, buf, BUF_SIZE)) > 0 )
{
write(master, buf, r);
}
close(slave);
close(master);
return 0;
}

libnids didn't capture xmpp packet

this program can detect http flow and etc....
but it ignores XMPP flow ; i don't know why ?
(I guess this is a port problem , but i don't know where i should fix it )
Below are the relevant sections from main.cpp :
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include "nids.h"
#include <cstdlib>
#include <unistd.h>
#define int_ntoa(x) inet_ntoa(*((struct in_addr *)&x))
// struct tuple4 contains addresses and port numbers of the TCP connections
// the following auxiliary function produces a string looking like
// 10.0.0.1,1024,10.0.0.2,23
char *
adres (struct tuple4 addr)
{
static char buf[256];
strcpy (buf, int_ntoa (addr.saddr));
sprintf (buf + strlen (buf), ",%i,", addr.source);
strcat (buf, int_ntoa (addr.daddr));
sprintf (buf + strlen (buf), ",%i", addr.dest);
return buf;
}
void
tcp_callback (struct tcp_stream *a_tcp, void ** this_time_not_needed)
{
printf("packet captured !\n");
}
int
main ()
{
// here we can alter libnids params, for instance:
// nids_params.n_hosts=256;
struct nids_chksum_ctl nochksumchk;
nochksumchk.netaddr = 0;
nochksumchk.mask = 0;
nochksumchk.action = NIDS_DONT_CHKSUM;
//char fileName[] = "/home/test.pcap";
//nids_params.filename =fileName;
nids_register_chksum_ctl(&nochksumchk, 1);
char myDevice [] = "eth0";
nids_params.device =myDevice;
if (!nids_init ())
{
fprintf(stderr,"%s\n",nids_errbuf);
exit(1);
}
nids_register_tcp ( (void*)tcp_callback);
nids_run ();
return 0;
}
My pcap file has some problem about syncing in tcp connection .
So above snippet code of libnids is correct !