php - 从 PHP 连接到 C++ 服务器太多次导致访问冲突异常

标签 php c++ sockets exception memory

所以我有一个 C++ 服务器,其中有一些我想从 PHP 访问的数据。 然而,我需要能够处理这样一个事实,即许多人可能会同时连接到它,并用大量数据包淹没服务器。

我只有一个 PHP 脚本可以打开一个套接字,向它发送“hello”,然后关闭套接字。 如果我一遍又一遍地刷新浏览器上的页面,它就会淹没服务器。然而,在发送了大约 70->100 个数据包(连接到套接字、发送数据、关闭套接字超过 70 次)之后,我得到了一个访问冲突异常:

Unhandled exception at 0x010BC96D in Server.exe: 0xC0000005: Access violation reading location 0xFEEEFEEE.

Variable dump

这是我的 TCP 连接设置:

double webListen = tcplisten(cst::WEB_PORT, 100, 1);

std::list<double> webUsers;

if (webListen <= 0) {
    cout << "Failed to listen on port " << cst::WEB_PORT <<endl;
}
cout << endl << "Server listening on port " << cst::WEB_PORT << endl;
while(1){
    //Sleep(5);
    double WebUser = tcpaccept(webListen, 0);
    if(WebUser > -1){
        cout<< "NEW WEB SOCKET: " << WebUser <<  endl;
        webUsers.push_back(WebUser);
    }

    std::list<double>::iterator it = webUsers.begin();
    while (it != webUsers.end())
    {

        cout << "SOCK: " << *it << endl;
        double Size = receivemessage(*it, 1024, 4);
        if(Size == -1){

        }
        else if(Size == 0){
            cout << "WEB SOCKET DISCONNECTED: " << *it << endl;
            it = webUsers.erase(it);
        }
        else if(Size > 0){
            cout << "SIZE: " << Size << endl;
            //Not reading data until exception is fixed
        }

    }

}

(我在 receivemessage() 的参数中放了 4 因为它 这是我的 receivemessage() 函数:

int CSocket::receivemessage(int len, CBuffer*destination)
{
    if(sockid<0)return -1;
    int size = -1;
    //std::vector<char> buff;
    std::vector<char> *buff;
    if(udp)
    {
        size = 8195;
        //buff = new char[size];
        buff = new std::vector<char>(size,'0');
        size = recvfrom(sockid, &(*buff)[0], size, 0, (SOCKADDR *)&SenderAddr, &SenderAddrSize);
    } else
    {
        if(format == 0 && !len)
        {
            unsigned short length;
            if(recv(sockid, (char*)&length, 2, 0) == SOCKET_ERROR)return -1;
            buff = new std::vector<char>(length,'0');
            //buff = new char[length];
            size = recv(sockid, &(*buff)[0], length, 0);
        } else if(format == 1 && !len)
        {
            size = 65536;
            buff = new std::vector<char>(size,'0');
            //buff = new char[size];
            size = receivetext(&(*buff)[0], size);
        } else if(format == 2 || len > 0)
        {
            buff = new std::vector<char>(len,'0');
            //buff = new char[len];
            size = recv(sockid, &(*buff)[0], len, 0);
        }
    }
    if(size > 0)
    {
        destination->clear();
        destination->addBuffer(&(*buff)[0], size);
    }
    delete buff;
    //if(buff != NULL)delete[] buff;
    return size;
}

还有我的 PHP 脚本:

   <?php
    require_once("../server_info.php"); //contains get_host() and get_port_web()
    $waitTimeoutInSeconds = 1; 
    $errCode = 0;
    $errStr = 0;

    if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0)))
    {
        $errorcode = socket_last_error();
        $errormsg = socket_strerror($errorcode);

        die("Couldn't create socket: [$errorcode] $errormsg \n");
    }

    echo "Socket created \n";

    //Connect socket to remote server

    if(!socket_connect($sock , get_host() , get_port_web()))
    {
        $errorcode = socket_last_error();
        $errormsg = socket_strerror($errorcode);

        die("Could not connect: [$errorcode] $errormsg \n");
    }

    echo "Connection established \n";

    $message = "hello";

    //Send the message to the server
    if( ! socket_send ( $sock , $message , strlen($message) , 0))
    {
        $errorcode = socket_last_error();
        $errormsg = socket_strerror($errorcode);

        die("Could not send data: [$errorcode] $errormsg \n");
    }

    echo "Message sent successfully \n";

    socket_close($sock);

?>

我不确定为什么在大约 70-100 个套接字后会导致异常。我在某处有内存泄漏吗? (可能在 receivemessage() 函数中?)。

有时甚至在超过 34 个套接字连接时它也会抛出异常。 不确定此时该做什么。

最佳答案

您不应该在删除指针之前测试它是否为 NULL,该语言保证 delete(NULL) 不会执行任何操作。 另外,看看你的代码,看看你是否真的需要它作为一个指针。如果把它做成一个简单的 vector 不是更容易吗?

回到你的崩溃,很可能它的原因不在你发布的代码段中。

Access violation reading location 0xFEEEFEEE.

如果您查看 Locals 窗口,您会注意到“this”指向 0xFEEEFEEE,这在 Windows 中是一个神奇的数字:在调试版本中,它是分配给释放的堆空间的值。 所以看起来在某个时候 receivemessage() 被调用到一个已删除的 CSocket 对象上。这是我要开始寻找原因的区域。

关于php - 从 PHP 连接到 C++ 服务器太多次导致访问冲突异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27615554/

相关文章:

c++ - 遗传算法中的交叉技术

c++ - 实现在单向链表(addsort)中添加和排序数据的函数?

c - 知道 C 中的任何跨平台套接字库(Windows 和 Linux)吗?

php - 通过表单发送 HTML 代码

PHP/MySQL - 如何通过 PDO 使用 MySQL BEGIN/COMMIT

php - 如何计算某个meta_key在列中出现meta_value的次数?

c# - 通过 ping 或 socket 检查代理有什么区别?

php - Yii2 并在 ArrayDataProvider 中排序

c++ - 为什么STL选择基于树的映射而不是基于散列的映射?

python - TCP/IP Server-Client 是否有数据发送限制?