Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当我关闭客户端套接字时,如何防止服务器关闭?C++;_C++_Sockets_Tcp_Server_Client - Fatal编程技术网

C++ 当我关闭客户端套接字时,如何防止服务器关闭?C++;

C++ 当我关闭客户端套接字时,如何防止服务器关闭?C++;,c++,sockets,tcp,server,client,C++,Sockets,Tcp,Server,Client,我有以下代码,即“server.cpp”。它正确地建立与客户端的连接并流式传输视频。问题是,当我关闭客户端时,不管主程序中的while周期如何,服务器也会自动关闭,即使我正在使用pthread_create 您能帮我找到一个解决方案,避免它关闭,并在新客户端连接到它之前保持活动状态吗 /** * OpenCV video streaming over TCP/IP * Server: Captures video from a webcam and send it to a client

我有以下代码,即“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;
        }
    }

}
/**
*基于TCP/IP的OpenCV视频流
*服务器:从网络摄像头捕获视频并将其发送到客户端
*艾萨克·玛亚
*/
#包括“opencv2/opencv.hpp”
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间cv;
作废*显示(作废*);
int capDev=0;
视频捕获cap(capDev);//打开默认相机
int main(int argc,字符**argv)
{
//--------------------------------------------------------
//网络材料:套接字、绑定、侦听
//--------------------------------------------------------
int localSocket,remoteSocket,端口=4097;
localAddr、remoteAddr中的结构sockaddr\u;
pthread_t thread_id;
int addrLen=sizeof(结构sockaddr_in);
如果((argc>1)和&(strcmp(argv[1],“-h”)==0))
{

std::cerr您没有安全地将
remoteSocket
传递到
display()
,因此如果另一个客户端在
display()之前连接,您的竞争条件可能会改变
remoteSocket
的值
有机会使用上一个值。不要传递指向原始
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;
}
/**
*基于TCP/IP的OpenCV视频流
*服务器:从网络摄像头捕获视频并将其发送到客户端
*艾萨克·玛亚
*/
#包括“opencv2/opencv.hpp”
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间cv;
作废*显示(作废*);
int capDev=0;
VideoCapture cap(capDev);//打开默认摄像机
int main(int argc,字符**argv)
{
//--------------------------------------------------------
//网络材料:套接字、绑定、侦听
//--------------------------------------------------------
int localSocket,remoteSocket;
无符号短端口=4097;
localAddr、remoteAddr中的结构sockaddr\u;
索克伦·阿德伦;
pthread_t thread_id;
INTERR;
如果(argc>1)
{
long lport=strtol(argv[1],NULL,10);
如果((端口65535))
{

std::cerr请正确格式化您的代码,即使用缩进,并告诉我们“退出”的确切含义。它是否崩溃?打印错误并退出?悄悄退出?结束大括号比开始大括号少。循环后,
是否显示
执行?使用调试器执行断开逻辑的步骤可能会证明更正确从长远来看,这比问问题更有成效。无关:
exit(1)
main
中的
是一种毫无意义的
return 1;
将执行此任务。如果线程带异常退出,则可能会导致应用程序终止。您应该在try-catch块中运行线程中的所有内容,以防止异常逃逸。(您应该检查pthread的文档。但是线程的任何异常终止都可能导致应用程序终止)。您使用的
remoteSocket
存在竞争条件。此解决方案不起作用…我发现,如果在函数显示的调用–发送–中使用标志MSG_NOSIGNAL而不是0,则程序不会关闭…问题是,当我尝试重新连接客户端时,程序将在while(1)之前保持阻塞状态功能上display@F.DEVIVO:请参阅。但是无论使用哪种方法禁用
SIGPIPE
send()
都会在断开连接时失败,并产生错误代码,该代码已处理该错误代码以终止线程循环。除非
send()
正在报告成功。当客户端断开连接时,循环应中断。当客户端重新连接时,新线程应启动。