What does it mean when CreateNamedPipe returns of 0xFFFFFFFF perror() says "NO ERROR'? - named-pipes

I am using CreateNamedPipe. It returns 0XFFFFFFFF but when I call GetLastError and perror I get "NO ERROR".
I have checked https://learn.microsoft.com/en-us/windows/win32/ipc/multithreaded-pipe-server and I heve coded very similar.
I coded this using an example provided here: https://stackoverflow.com/questions/47731784/c-createnamedpipe-error-path-not-found-3#= and he says it means ERROR_PATH_NOT_FOUND (3). But my address is "\\.\pipe\pipe_com1. Note that StackOverflow seems to remove the extra slashes but you will see them in the paste of my code.
I followed the example here: Create Named Pipe C++ Windows but I still get the error. Here is my code:
// Create a named pipe
// It is used to test TcpToNamedPipe to be sore it it is addressing the named pipe
#include <windows.h>
#include <stdio.h>
#include <process.h>
char ch;
int main(int nargs, char** argv)
{
if (nargs != 2)
{
printf("Usage pipe name is first arg\n");
printf("press any key to exit ");
scanf("%c", &ch);
return -1;
}
char buffer[1024];
HANDLE hPipe;
DWORD dwRead;
sprintf(buffer, "\\\\.\\pipe\\%s", argv[1]);
hPipe = CreateNamedPipe((LPCWSTR)buffer,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
1,
1024*16,
1024*16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
if (hPipe == INVALID_HANDLE_VALUE)
{
//int errorno = GetLastError();
//printf("error creating pipe %d\n", errorno);
perror("");
printf("press any key to exit ");
scanf("%c", &ch);
return -1;
}
while (hPipe != INVALID_HANDLE_VALUE)
{
if (ConnectNamedPipe(hPipe, NULL) != FALSE) // wait for someone to connect to the pipe
{
while (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &dwRead, NULL) != FALSE)
{
/* add terminating zero */
buffer[dwRead] = '\0';
/* do something with data in buffer */
printf("%s", buffer);
}
}
DisconnectNamedPipe(hPipe);
}
return 0;
}
I'm guessing that the pointer to the address may be wrong and CreateNamedPipe is not seeing the name of the pipe properly. So I used disassembly and notice that the address is in fact a far pointer. Here is that disassembly:
00CA1A45 mov esi,esp
00CA1A47 push 0
00CA1A49 push 0
00CA1A4B push 4000h
00CA1A50 push 4000h
00CA1A55 push 1
00CA1A57 push 0
00CA1A59 push 3
00CA1A5B lea eax,[buffer]
00CA1A61 push eax
00CA1A62 call dword ptr [__imp__CreateNamedPipeW#32 (0CAB00Ch)]
Can someone spot my problem?

Related

How can we determine whether a socket is ready to read/write?

How can we determine whether a socket is ready to read/write in socket programming.
On Linux, use select() or poll().
On Windows, you can use WSAPoll() or select(), both from winsock2.
Mac OS X also has select() and poll().
#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
select() and pselect() allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/O operation (e.g., input possible). A file descriptor is considered ready if it is possible to perform the corresponding I/O operation (e.g., read(2)) without blocking. – https://linux.die.net/man/3/fd_set
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
poll() performs a similar task to select(2): it waits for one of a set of file descriptors to become ready to perform I/O.
– https://linux.die.net/man/2/poll
Example of select usage:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int
main(void)
{
fd_set rfds;
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
/* Don't rely on the value of tv now! */
if (retval == -1)
perror("select()");
else if (retval)
printf("Data is available now.\n");
/* FD_ISSET(0, &rfds) will be true. */
else
printf("No data within five seconds.\n");
exit(EXIT_SUCCESS);
}
Explanation of the above code:
FD_ZERO initializes the rfds set. FD_SET(0, &rfds) adds fd 0 (stdin) to the set. FD_ISSET can be used to check whether a specific file descriptor is ready after select returns.
The select call in this example waits until rfds has input or until 5 seconds passes. The two NULLs in the select call are where file descriptor sets (fd_sets) to be checked for ready to write status and exceptions, respectively, would be passed. The tv argument is the number of seconds and microseconds to wait. The first argument to select, nfds, is the highest numbered file descriptor in any of the three sets (read, write, exceptions sets) plus one.
Example of poll usage (from man7.org):
/* poll_input.c
Licensed under GNU General Public License v2 or later.
*/
#include <poll.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
int
main(int argc, char *argv[])
{
int nfds, num_open_fds;
struct pollfd *pfds;
if (argc < 2) {
fprintf(stderr, "Usage: %s file...\n", argv[0]);
exit(EXIT_FAILURE);
}
num_open_fds = nfds = argc - 1;
pfds = calloc(nfds, sizeof(struct pollfd));
if (pfds == NULL)
errExit("malloc");
/* Open each file on command line, and add it 'pfds' array. */
for (int j = 0; j < nfds; j++) {
pfds[j].fd = open(argv[j + 1], O_RDONLY);
if (pfds[j].fd == -1)
errExit("open");
printf("Opened \"%s\" on fd %d\n", argv[j + 1], pfds[j].fd);
pfds[j].events = POLLIN;
}
/* Keep calling poll() as long as at least one file descriptor is
open. */
while (num_open_fds > 0) {
int ready;
printf("About to poll()\n");
ready = poll(pfds, nfds, -1);
if (ready == -1)
errExit("poll");
printf("Ready: %d\n", ready);
/* Deal with array returned by poll(). */
for (int j = 0; j < nfds; j++) {
char buf[10];
if (pfds[j].revents != 0) {
printf(" fd=%d; events: %s%s%s\n", pfds[j].fd,
(pfds[j].revents & POLLIN) ? "POLLIN " : "",
(pfds[j].revents & POLLHUP) ? "POLLHUP " : "",
(pfds[j].revents & POLLERR) ? "POLLERR " : "");
if (pfds[j].revents & POLLIN) {
ssize_t s = read(pfds[j].fd, buf, sizeof(buf));
if (s == -1)
errExit("read");
printf(" read %zd bytes: %.*s\n",
s, (int) s, buf);
} else { /* POLLERR | POLLHUP */
printf(" closing fd %d\n", pfds[j].fd);
if (close(pfds[j].fd) == -1)
errExit("close");
num_open_fds--;
}
}
}
}
printf("All file descriptors closed; bye\n");
exit(EXIT_SUCCESS);
}
Explanation of above code:
This code is a bit more complex than the previous example.
argc is the number of arguments. argv is the array of arguments given to the program. argc[0] is usually the name of the program. If argc is less than 2 (which means only one argument was given), the program outputs a usage message and exits with a failure code.
pfds = calloc(nfds, sizeof(struct pollfd)); allocates memory for an array of struct pollfd which is nfds elements long and zeroes the memory. Then there is a NULL check; if pfds is NULL, that means calloc failed (usually because the program ran out of memory), so the program prints the error with perror and exits.
The for loop opens each filename specified in argv and assigns it to corresponding elements of the pfd array. Then sets .events on each element to POLLIN to tell poll to check each file descriptor for whether it is ready to read
The while loop is where the actual call to poll() happens. The array of struct pollfds, pfds, the number of fds, nfds, and a timeout of -1 is passed to poll. Then the return value is checked for error (-1 is what poll return when there is an error) and if there is an error, the program prints an error message and exits. Then the number of ready file descriptors is printed.
In the second for loop inside the while loop, the program iterates over the array of pollfds and checks the .revents field of each structure. If that field is nonzero, an event occurred on the corresponding file descriptor. The program prints the file descriptor, and the event, which can be POLLIN (ready for input), POLLHUP (hang up), or POLLERR (error condition). If the event was POLLIN, the file is ready to be read.
The program then reads 10 bytes into buf. If an error happens when reading, the program prints an error and exits. Otherwise, the program prints the number of bytes read and the contents of the buffer buf.
In case of error or hang up (POLLERR, POLLHUP) the program closes the file descriptor and decrements num_open_fds.
Finally the program says that all file descriptors are closed and exits with EXIT_SUCCESS.

Socket programming, process blocked on select?

I want do a simple program, where a father process create some child processes; before child pause(), they notification father process.
Child processes run correctly, but father wait on select, otherwise child have written on socket; where is the mistake?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
typedef struct{
pid_t pid;
int sockfd;
}Child;
void err_exit(char* str)
{
perror(str);
exit(EXIT_FAILURE);
}
int convert_int(char* str)
{
int v;
char*p;
errno = 0;
v = strtol(str,&p,0);
if(errno != 0 || *p != '\0')
err_exit("errno");
return v;
}
void child_job(pid_t pid,int sockfd)
{
int v = write(sockfd,"1",1);
if(v == -1)
err_exit("write");
printf("process %d in pause()\n",pid);
pause();
}
int main(int argc, char* argv[])
{
int nsel;
fd_set masterset;
int n_child,i;
int sockfd[2];
pid_t pid;
Child* c = NULL;
if(argc != 2)
err_exit("usage: <awake2> #children\n");
FD_ZERO(&masterset);
n_child = convert_int(argv[1]);
c = malloc(n_child*sizeof(Child));
if(c == NULL)
err_exit("malloc");
for(i = 0; i <n_child; i++){
if ((socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd)) < 0) { //create socket between child and father
perror("errore in socketpair");
exit(1);
}
if ((pid = fork()) > 0) {
if (close(sockfd[1]) == -1) { //father process closes sockfd[1]
perror("errore in close");
exit(1);
}
c[i].pid = pid;
c[i].sockfd = sockfd[0];
FD_SET(c[i].sockfd, &masterset);
}
else if(!pid)
child_job(getpid(),c[i].sockfd);
}
for(;;){
if ((nsel = select(n_child+1, &masterset, NULL, NULL, NULL)) < 0) {
perror("errore in bind");
exit(1);
}
int i;
for(i = 0; i <n_child; i++){
if(FD_ISSET(c[i].sockfd, &masterset)) {
printf("changed fd\n");
}
}
}
}
One thing that's wrong is you're passing c[i].sockfd to child_job(). In the parent process, it was set to the first socket fd in the pair, but child_job() is called in the child process, where c never gets set to anything. You're passing the original contents of the malloc memory. Change that to child_job(getpid(), sockfd[1]); and you'll be getting closer.
Another thing is that the first argument to select is probably too low. n_child is the number of children, but you need to pass a number here that's greater than the highest file descriptor in your set. For example, run the program with the argument 1 so it creates 1 child. It is likely to start out with file descriptors 0, 1, and 2 open, so the socket pair will be file descriptors 3 and 4. The 3 goes into the fd_set, but the first argument to select is 1+1=2. select ignores your fd 3 because it's above the limit.
To fix that, create a new variable int maxfd; near your fd_set, initialize it to -1 when you FD_ZERO the set, and after every call to FD_SET, update it:
if( [whatever fd you just gave to FD_SET] > maxfd)
maxfd = [whatever fd you just gave to FD_SET];
and call select with maxfd+1 as the first argument.
(Or maybe switch to poll)
That should get you far enough that your first select call works. After that, you'll find more problems.
The fd_set you pass to select will be modified (that's why you can do FD_ISSET tests on it afterward). If you go back to the top of the loop and pass it again without reinitializing it, select will not be looking at all the file descriptors any more, just the ones that were ready in the first call. To fix this, make a second fd_set and copy the master into it just before the select call, and never pass the master to select. (Or you can rebuild the set from scratch each time by scanning the child table.)
If you get a readable fd from select, you should read it before calling select again, otherwise you're just in a "eat CPU calling select over and over" loop.

Behavior of select() on stdin when used on a pipe

I am trying to understand an observation on behavior of select() when used on stdin, when it is receiving data from a pipe.
Basically I had a simple C program using the following code:
hello.c:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <termios.h>
int main(int argc, char *argv[])
{
int flags, opt;
int nsecs, tfnd;
fd_set rfds;
struct timeval tv;
int retval;
int stdin_fileno_p1 = STDIN_FILENO+1;
char c;
int n;
/* Turn off canonical processing on stdin*/
static struct termios oldt, newt;
tcgetattr( STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON);
tcsetattr( STDIN_FILENO, TCSANOW, &newt);
while (1)
{
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
retval = select(stdin_fileno_p1, &rfds, NULL, NULL, &tv);
if ( retval && (retval!=-1) )
{
n = read(STDIN_FILENO, &c, 1);
write(STDOUT_FILENO, &c, 1);
}
else printf("No Data\n");
usleep(100000);
}
tcsetattr( STDIN_FILENO, TCSANOW, &oldt);
}
If I ran the program as follows I could see characters echoing when I type keys on while the program is running. When keys are not pressed, it displays "No Data" as expected.
./hello
However, if use the program as follows, the program never gets to a state where is displays "No Data". Instead last character "c" is repeatedly displayed.
echo -n abc | ./hello
I'm a bit puzzled by this observation, and would be grateful if you could help me to understand the observed behavior.
The problem is that your program does not detect an end-of-file condition when it reads from the STDIN_FILENO descriptor. After echo has written the c character it will close its end of the pipe, which will cause the select in your program to return immediately and your read to return 0 as an indication that no more data will ever be available from that descriptor. Your program doesn't detect that condition. Instead it just calls write with whatever character was left in the buffer by the last successful read and then repeats the loop.
To fix, do if (n==0) break; after the read.

ncurses interrupts system call when resizing terminal

I have a problem with ncurses and couldn't find a solution on the web, so I've written following little program to demonstrate the problem.
You can compile it via:
sudo aptitude install ncurses-dev
g++ -lncurses -o resize resize.cpp
It displays an integer counter incremented every second by forking into a timer process which periodically sends one byte to the parent process via a socketpair. You can quit it by pressing CTRL+C.
When you resize the terminal you should get an error message of 'Interrupted system call'. So the read call gets interrupted by SIGWINCH when resizing. But how can I avoid this? Or is it common that the system call gets interrupted? But how would I handle an interrupted system call in order to proceed incrementing the counter since the file descripter appears to be dead after interruption.
If you use non-blocking sockets, you would get 'Resource temporarily unavailable' instead.
I am using stable debian wheezy, so the ncurses version is 5.9-10 and the libstdc++ version is 4.7.2-5.
#include <ncurses.h>
#include <signal.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <string>
#include <iostream>
//Define a second.
timespec span = {1, 0};
//Handles both, SIGWINCH and SIGINT
void handle(int signal) {
switch (signal) {
case SIGWINCH:
//Reinitialize ncurses to get new size
endwin();
refresh();
printw("Catched SIGWINCH and handled it.\n");
refresh();
break;
case SIGINT:
//Catched CTRL+C and quit
endwin();
exit(0);
break;
}
}
//This registers above signal handler function
void set_handler_for(int signal) {
struct sigaction action;
action.sa_handler = handle;
action.sa_flags = 0;
if (-1 == sigemptyset(&action.sa_mask) or -1 == sigaction(signal, &action, NULL))
throw "Cannot set signal handler";
}
main() {
int fd[2];
//In this try block we fork into the timer process
try {
set_handler_for(SIGINT);
set_handler_for(SIGWINCH);
//Creating a socketpair to communicate between timer and parent process
if (-1 == socketpair(PF_LOCAL, SOCK_STREAM, 0, fd))
throw "Cannot create socketpair";
pid_t pid;
//Doing the fork
if (-1 == (pid = fork()))
throw "Cannot fork process";
if (!pid) {
//We are the timer, so closing the other end of the socketpair
close(fd[0]);
//We send one byte every second to the parent process
while (true) {
char byte;
ssize_t bytes = write(fd[1], &byte, sizeof byte);
if (0 >= bytes)
throw "Cannot write";
nanosleep(&span, 0);
}
//Here the timer process ends
exit(0);
}
//We are the parent process, so closing the other end of the socketpair
close(fd[1]);
}
catch (const char*& what) {
std::cerr << what << std::endl;
exit(1);
}
//Parent process - Initializing ncurses
initscr();
noecho();
curs_set(0);
nodelay(stdscr, TRUE);
//In this try block we read (blocking) the byte from the timer process every second
try {
int tick = 0;
while (true) {
char byte;
ssize_t bytes = read(fd[0], &byte, sizeof byte);
if (0 >= bytes)
throw "Cannot read";
//Clear screen and print increased counter
clear();
mvprintw(0, 0, "Tick: %d - Resize terminal and press CTRL+C to quit.\n", ++tick);
//Catch special key KEY_RESIZE and reinitialize ncurses to get new size (actually not necassary)
int key;
while ((key = getch()) != ERR) {
if (key == KEY_RESIZE) {
endwin();
refresh();
printw("Got KEY_RESIZE and handled it.\n");
}
}
//Update the screen
refresh();
}
}
catch (const char*& what) {
//We got an error - print it but don't quit in order to have time to read it
std::string error(what);
if (errno) {
error.append(": ");
error.append(strerror(errno));
}
error = "Catched exception: "+error+"\n";
printw(error.c_str());
refresh();
//Waiting for CTRL+C to quit
while (true)
nanosleep(&span, 0);
}
}
Thank you!
Regards
Most (if not all) system calls have an interrupted error code (errno == EINTR), this is normal.
I would check for EINTR on the read from the pipe and ignore it, just read again.
I wouldn't call any ncurses functions in the signal handler, some are re-entrant but I doubt printw is. Just do the KEY_RESIZE check.
Okay, I got it working by only using re-entrant functions within signal handlers. Now the socketpair is still working after an EINTR or EAGAIN.
Thank you!
#include <ncurses.h>
#include <signal.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <string>
#include <iostream>
// Define a second.
timespec base = {1, 0};
// Holds raised SIGINTs.
size_t raised_SIGINT = 0;
// Holds raised SIGWINCHs.
size_t raised_SIGWINCH = 0;
// Handle SIGWINCH
void handle_SIGWINCH(int) {
++raised_SIGWINCH;
}
// Handle SIGINT
void handle_SIGINT(int) {
++raised_SIGINT;
}
// Registers signal handlers.
void assign(int signal, void (*handler)(int)) {
struct sigaction action;
action.sa_handler = handler;
action.sa_flags = 0;
if (-1 == sigemptyset(&action.sa_mask) or -1 == sigaction(signal, &action, NULL))
throw "Cannot set signal handler";
}
// Prints ticks alive and usage information.
inline void print(size_t ticks) {
mvprintw(0, 0, "%ds alive. Resize terminal and press CTRL+C to quit.\n\n", ticks);
}
int main() {
// Holds the two socketpair file descriptors.
int fd[2];
// Fork into the timer process.
try {
// Register both signals.
assign(SIGINT, handle_SIGINT);
assign(SIGWINCH, handle_SIGWINCH);
// Create a socketpair to communicate between timer and parent process.
if (-1 == socketpair(PF_LOCAL, SOCK_STREAM, 0, fd))
throw "Cannot create socketpair";
// Doing the fork.
pid_t pid;
if (-1 == (pid = fork()))
throw "Cannot fork process";
if (!pid) {
// We are the timer, so closing the parent end of the socketpair.
close(fd[0]);
// We send one byte every second to the parent process.
while (true) {
timespec less = base;
int ret;
// Continue sleeping after SIGWINCH but only for the time left.
while (-1 == (ret = nanosleep(&less, &less)) and errno == EINTR and raised_SIGWINCH);
// Maybe quit by user.
if (raised_SIGINT)
return 0;
// If something went wrong, terminate.
if (-1 == ret)
throw "Cannot sleep";
// Repeated writing if interrupted by SIGWINCH.
char byte;
ssize_t bytes;
do {
// Doing the write.
bytes = write(fd[1], &byte, sizeof byte);
}
while (0 >= bytes and (errno == EAGAIN or errno == EINTR) and raised_SIGWINCH);
// Maybe quit by user.
if (raised_SIGINT)
return 0;
// If something went wrong, terminate.
if (0 >= bytes)
throw "Cannot write";
}
// Here the timer process ends.
return 0;
}
// We are the parent process, so closing the timer end of the socketpair.
close(fd[1]);
}
catch (const char*& what) {
// Print fatal error and terminate timer process causing parent process to terminate, too.
std::cerr << what << std::endl;
return 1;
}
// Initializing ncurses for the parent process.
initscr();
// Disable typing.
noecho();
// Disable cursor.
curs_set(0);
// Make reading characters non-blocking.
nodelay(stdscr, TRUE);
// Catch fatal errors.
try {
// Holds ticks alive.
size_t ticks = 0;
// Blockingly read the byte from the timer process awaiking us every second.
while (true) {
// Print ticks alive before incrementing them.
print(ticks++);
// Holds typed keys.
std::string keys;
// Read typed keys.
for (int key = getch(); key != ERR; key = getch())
if (key != KEY_RESIZE)
keys += key;
// Format typed keys string.
if (keys.size())
printw("You've typed: ");
else
keys += "\n";
keys += "\n\n";
// Print typed keys string.
printw(keys.c_str());
// Doing the prints.
refresh();
// Repeated reading if interrupted by SIGWINCH.
ssize_t bytes = 0;
bool again = false;
do {
// Doing the read.
char byte;
bytes = read(fd[0], &byte, sizeof byte);
again = (0 >= bytes and (errno == EAGAIN or errno == EINTR) and raised_SIGWINCH);
// Print how often we got interrupted by SIGWINCH per time base.
if (again) {
// Next two calls are the common way to handle a SIGWINCH.
endwin();
refresh();
// For simpicity clear everything.
clear();
// Re-print ticks.
print(ticks);
// Print the interruption counter.
printw("%dx catched SIGWINCH per time base.\n\n", raised_SIGWINCH);
// Doing the prints.
refresh();
}
}
while (again);
// Reset SIGWINCH raises per time base.
raised_SIGWINCH = 0;
// Maybe quit by user.
if (raised_SIGINT) {
endwin();
return 0;
}
// If something went wrong, terminate.
if (0 >= bytes)
throw "Cannot read";
}
}
catch (const char*& what) {
// We got an error, appending errno if set.
std::string error(what);
if (errno) {
error.append(": ");
error.append(strerror(errno));
}
error = "Catched exception: "+error+"\n";
// Print the fatal error.
printw(error.c_str());
//Doing the print.
refresh();
// Waiting for CTRL+C to quit.
while (true)
nanosleep(&base, 0);
// Quit by user.
endwin();
return 0;
}
}

streaming with tcp using opencv and socket

i have done simple tcp client/server program got working well with strings and character data...i wanted to take each frames(from a webcam) and sent it to server.. here is the part of client program where error happened:
line:66 if(send(sock, frame, sizeof(frame), 0)< 0)
error:
client.cpp:66:39: error: cannot convert ‘cv::Mat’ to ‘const void*’ for argument ‘2’ to ‘ssize_t send(int, const void*, size_t, int)
i cant recognise this error....kindly help...the following complete client program:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<stdlib.h>
#include<netdb.h>
#include<unistd.h>
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc,char *argv[])
{
int sock;
struct sockaddr_in server;
struct hostent *hp;
char buff[1024];
VideoCapture capture;
Mat frame;
capture.open( 1 );
if ( ! capture.isOpened() ) { printf("--(!)Error opening video capture\n"); return -1; }
begin:
capture.read(frame);
if( frame.empty() )
{
printf(" --(!) No captured frame -- Break!");
goto end;
}
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
perror("socket failed");
exit(1);
}
server.sin_family =AF_INET;
hp= gethostbyname(argv[1]);
if(hp == 0)
{
perror("get hostname failed");
close(sock);
exit(1);
}
memcpy(&server.sin_addr,hp->h_addr,hp->h_length);
server.sin_port = htons(5000);
if(connect(sock,(struct sockaddr *) &server, sizeof(server))<0)
{
perror("connect failed");
close(sock);
exit(1);
}
int c = waitKey(30);
if( (char)c == 27 ) { goto end; }
if(send(sock, frame, sizeof(frame), 0)< 0)
{
perror("send failed");
close(sock);
exit(1);
}
goto begin;
end:
printf("sent\n",);
close(sock);
return 0;
}
Because TCP provides a stream of bytes, before you can send something over a TCP socket, you must compose the exact bytes you want to send. Your use of sizeof is incorrect. The sizeof function tells you how many bytes are needed on your system to store the particular type. This bears no relationship to the number of bytes the data will require over the TCP connection which depends on the particular protocol layered on top of TCP you are implementing which must specify how data is to be sent at the byte level.
like david already said, you got the length wrong. sizeof() won't help, what you want is probably
frame.total() * frame.channels()
you can't send a Mat object, but you can send the pixels ( the data pointer ) , so this would be:
send(sock, frame.data,frame.total() * frame.channels(), 0)
but still a bad idea. sending uncompressed pixels over the netwotrk ? bahh.
please look at imencode/imdecode
i'm pretty sure, you got the client / server roles in reverse here.
usually the server holds the information to retrieve ( the webcam ), and the client connects to that
and requests an image.