我有以下代码,即" server.cpp"。它正确建立与客户端的连接并流式传输视频。问题是,当我关闭客户端时,无论主程序中的while循环如何,即使我使用pthread_create,服务器也会自动关闭。
你能帮我找一个解决办法,以避免它关闭,并保持活着,直到新客户端连接到它?
/**
* OpenCV video streaming over TCP/IP
* Server: Captures video from a webcam and send it to a client
* by Isaac Maia
*/
#include "opencv2/opencv.hpp"
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <string.h>
using namespace cv;
void *display(void *);
int capDev = 0;
VideoCapture cap(capDev); // open the default camera
int main(int argc, char** argv)
{
//--------------------------------------------------------
//networking stuff: socket, bind, listen
//--------------------------------------------------------
int localSocket, remoteSocket, port = 4097;
struct sockaddr_in localAddr, remoteAddr;
pthread_t thread_id;
int addrLen = sizeof(struct sockaddr_in);
if ((argc > 1) && (strcmp(argv[1], "-h") == 0))
{
std::cerr << "usage: ./cv_video_srv [port] [capture device]\n"
<< "port : socket port (4097 default)\n"
<< "capture device : (0 default)\n" << std::endl;
exit(1);
}
if (argc == 2)
port = atoi(argv[1]);
localSocket = socket(AF_INET, SOCK_STREAM, 0);
if (localSocket == -1)
{
perror("socket() call failed!!");
}
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = INADDR_ANY;
localAddr.sin_port = htons(port);
if (bind(localSocket, (struct sockaddr *) &localAddr, sizeof(localAddr))
< 0)
{
perror("Can't bind() socket");
exit(1);
}
//Listening
listen(localSocket, 3);
std::cout << "Waiting for connections...\n" << "Server Port:" << port
<< std::endl;
//accept connection from an incoming client
while (1)
{
//if (remoteSocket < 0) {
// perror("accept failed!");
// exit(1);
//}
remoteSocket = accept(localSocket,
(struct sockaddr *) &remoteAddr,
(socklen_t*) &addrLen);
//std::cout << remoteSocket<< "32"<< std::endl;
if (remoteSocket < 0)
{
perror("accept failed!");
exit(1);
}
std::cout << "Connection accepted" << std::endl;
pthread_create(&thread_id, NULL, display, &remoteSocket);
//pthread_join(thread_id,NULL);
}
//pthread_join(thread_id,NULL);
//close(remoteSocket);
return 0;
}
void *display(void *ptr)
{
int socket = *(int *) ptr;
//OpenCV Code
//----------------------------------------------------------
Mat img, imgGray;
img = Mat::zeros(480, 640, CV_8UC1);
//make it continuous
if (!img.isContinuous())
{
img = img.clone();
}
int imgSize = img.total() * img.elemSize();
int bytes = 0;
int key;
//make img continuos
if (!img.isContinuous())
{
img = img.clone();
imgGray = img.clone();
}
std::cout << "Image Size:" << imgSize << std::endl;
while (1)
{
/* get a frame from camera */
cap >> img;
//do video processing here
cvtColor(img, imgGray, CV_BGR2GRAY);
//send processed image
if ((bytes = send(socket, imgGray.data, imgSize, 0)) < 0)
{
std::cerr << "bytes = " << bytes << std::endl;
break;
}
}
}
答案 0 :(得分:1)
您没有安全地将remoteSocket
传递给display()
,因此如果另一个客户端在remoteSocket
有机会之前连接,您的竞争条件可能会改变display()
的值使用以前的值。不要将指针传递给原始remoteSocket
,而是传递它的副本。
此外,display()
在退出之前使用它时没有关闭接受的套接字,因此您正在泄漏套接字描述符。最终,由于缺少可用的描述符,accept()
将失败,并且您的主循环将退出程序。
尝试更像这样的东西:
/**
* OpenCV video streaming over TCP/IP
* Server: Captures video from a webcam and send it to a client
* by Isaac Maia
*/
#include "opencv2/opencv.hpp"
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <unistd.h>
#include <string.h>
#include <cstdlib>
using namespace cv;
void* display(void *);
int capDev = 0;
VideoCapture cap(capDev); // open the default camera
int main(int argc, char** argv)
{
//--------------------------------------------------------
//networking stuff: socket, bind, listen
//--------------------------------------------------------
int localSocket, remoteSocket;
unsigned short port = 4097;
struct sockaddr_in localAddr, remoteAddr;
socklen_t addrLen;
pthread_t thread_id;
int err;
if (argc > 1)
{
long lport = strtol(argv[1], NULL, 10);
if ((lport <= 0) || (lport > 65535))
{
std::cerr << "usage: ./cv_video_srv [port] [capture device]\n"
<< "port : socket port (4097 default)\n"
<< "capture device : (0 default)\n" << std::endl;
return 1;
}
port = (unsigned short) lport;
}
localSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (localSocket == -1)
{
perror("socket() call failed");
return 1;
}
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = INADDR_ANY;
localAddr.sin_port = htons(port);
if (bind(localSocket, (struct sockaddr *) &localAddr, sizeof(localAddr)) < 0)
{
perror("Can't bind() socket");
close(localSocket);
return 1;
}
//Listening
if (listen(localSocket, 3) < 0)
{
perror("Can't listen() socket");
close(localSocket);
return 1;
}
std::cout << "Waiting for connections...\n"
<< "Server Port:" << port << std::endl;
//accept connection from an incoming client
while (1)
{
addrLen = sizeof(struct sockaddr_in);
remoteSocket = accept(localSocket,
(struct sockaddr *) &remoteAddr,
&addrLen);
//std::cout << remoteSocket << std::endl;
if (remoteSocket < 0)
{
perror("accept failed");
close(localSocket);
return 1;
}
std::cout << "Connection accepted" << std::endl;
int *socket = new int(remoteSocket);
err = pthread_create(&thread_id, NULL, display, socket);
if (err != 0)
{
//perror("pthread_create failed");
std::cerr << "pthread_create failed: " << strerror(err) << std::endl;
close(remoteSocket);
delete socket;
continue;
}
//pthread_join(thread_id,NULL);
}
//pthread_join(thread_id,NULL);
return 0;
}
void* display(void *ptr)
{
int socket = * (int*) ptr;
delete (int*) ptr;
//OpenCV Code
//----------------------------------------------------------
Mat img, imgGray;
img = Mat::zeros(480, 640, CV_8UC1);
//make it continuous
if (!img.isContinuous())
{
img = img.clone();
}
int imgSize = img.total() * img.elemSize();
int bytes = 0;
int key;
//make img continuos
if (!img.isContinuous())
{
img = img.clone();
imgGray = img.clone();
}
std::cout << "Image Size:" << imgSize << std::endl;
while (1)
{
/* get a frame from camera */
cap >> img;
//do video processing here
cvtColor(img, imgGray, CV_BGR2GRAY);
//send processed image
bytes = send(socket, imgGray.data, imgSize, 0);
if (bytes <= 0)
{
if (bytes < 0)
perror("send failed");
break;
}
}
close(socket);
return NULL;
}