Итак, у меня есть сервер C ++, и в нем есть некоторые данные, к которым я хотел бы получить доступ из PHP.
Однако я должен быть в состоянии справиться с тем фактом, что многие люди могут подключиться к нему одновременно и залить сервер тоннами пакетов.
У меня просто есть PHP-скрипт, который открывает сокет, передает ему привет и закрывает сокет.
Если я обновляю страницу в браузере снова и снова, она затопляет сервер. Однако после отправки около 70-> 100 пакетов (подключение к сокету, отправка данных, закрытие сокета более 70 раз) я получаю исключение нарушения доступа:
Необработанное исключение в 0x010BC96D в Server.exe: 0xC0000005: расположение чтения нарушения доступа 0xFEEEFEEE.
Вот моя настройка соединения 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
}
}
}
(Я поставил 4 в аргументы для receivemessage (), потому что его
А вот моя функция 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) ничего не сделает.
Кроме того, взгляните на свой код и посмотрите, действительно ли вам это нужно, чтобы он был указателем. Не было бы проще, если бы вы сделали это простым вектором?
Возвращаясь к вашему сбою, есть большая вероятность, что причина этого не в куске кода, который вы разместили.
Место чтения нарушения доступа 0xFEEEFEEE.
Если вы заглянете в окно Locals, то заметите, что «this» указывает на 0xFEEEFEEE, что является магическим числом в Windows: в отладочных сборках это значение присваивается свободному пространству кучи.
Таким образом, похоже, что в какой-то момент receivemessage () вызывается для удаленного объекта CSocket. Это та область, где я бы начал искать причину.
Кажется, что либо у tcpaccept (), либо receivemessage () возникла какая-то тупиковая ситуация, потому что они выполнялись в нескольких потоках и требовали одновременного доступа в какой-то момент.
Мое решение состояло в том, чтобы просто заблокировать взаимное исключение вокруг них обоих или просто оставить их всех в одном потоке.