Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.86/21: Рейтинг темы: голосов - 21, средняя оценка - 4.86
 Аватар для KuKu
1563 / 1041 / 94
Регистрация: 17.04.2009
Сообщений: 2,995

Покритикуйте сервер

21.09.2011, 23:17. Показов 4359. Ответов 38
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день! Посмотрите и скажите пожалуйста возможные ошибки/недоработки/потенциальные косяки у класса mServer. Особенно интересуют потенциальные косяки при большом количестве подлючений. Надеюсь разобраться будет легко в том, что понаписано - если что пишите, а то сам забываю что, где написано
Server.cpp - main file

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include "mServer.h"
using namespace std;
 
class newServer:public mServer
{
public:
    newServer():mServer()
    {
 
    }
    virtual int mGrabberListen(int sock_id)
    {
        cout << "connect:" << sock_id << endl;
        return(0);
    }
    virtual int mGrabberRecv(char* message_in, int sock_id, int length)
    {
        cout << sock_id<< ":["<< length << "]:"<< message_in << endl;
        (*this).mSend(sock_id, message_in);
        return(0);
    }
    virtual int mGrabberClose(int sock_id)
    {
        cout << sock_id<< ":closed" << endl;
        return(0);
    }
};
int main()
{
 
    int result;
    sem_t sem1;
           sem_init(&sem1, 0, 0);
 
    newServer::size_in = 1024;
    newServer::max_connection = 64;
 
    newServer server;
 
    result = server.mBind(8080, 0);
    if (result<0) return(0);
    result = server.mListenStart();
    if (result<0) return(0);
    cout << "i'm listening" << endl;
    sem_wait(&sem1);
    return 0;
}

mServer.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#ifndef MSERVER_H_
#define MSERVER_H_
 
#include <string.h>
#include <stack>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/time.h>
#include <sys/types.h>
 
class mServer
{
private:
    int             listener;       // socket-listener
    int*                sock;           // client's socket
    pthread_t           threadListener;     // listener's socket
    pthread_t*          threadSock;     // client's thread
    std::stack<short>       freeSock;       // stack free sockets
    sockaddr_in         addr;           // my address
    char**              message_in;     // array incoming messages
    sem_t               sem;            // for stack synchronize
 
    int mRecv(int sock_id);                 // receive message
    int mClose(int sock_id);                // close connection
protected:
    bool isListen;                      // service working ?
    int mSend(int sock_id,char* message);           // send message
public:
    static int size_in;                 // max size incoming message's
    static int max_connection;              // max number of connections
 
    mServer();
    virtual ~mServer();
 
    int mBind(unsigned int port, char* address);
    int mListenStart();                         // start service
 
    friend void* bRecv(void* argv);                     // client's thread-receive-function
    friend void* bListen(void* argv);                   // thread-listen function
 
    virtual int mGrabberRecv(char* message_in, int sock_id, int length)     // event-function receive message
    {return(0);}
    virtual int mGrabberListen(int sock_id)                 // event-function open connection
    {return(0);}
    virtual int mGrabberClose(int sock_id)                  // event-function close connection
    {return(0);}
};
#endif

mServer.cpp

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "mServer.h"
 
int mServer::size_in = 256;
int mServer::max_connection = 64;
 
void* bRecv(void* argv)
{
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
    mServer* cm = (mServer*) argv;
    int i = (*cm).freeSock.top();
    (*cm).freeSock.pop();
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    sem_post(&((*cm).sem));
 
    int flag = 1;
    while(flag>0)  // <0 - error, 0 - close
    {
        flag = (*cm).mRecv(i);
        if (flag>0) (*cm).mGrabberRecv((*cm).message_in[i], i, flag);
    }
    return(0);
}
void* bListen(void* argv)
{
    mServer* cm = (mServer*) argv;
    int i;
    int buf;
    while ((*cm).isListen)
    {
        buf = accept((*cm).listener, NULL, NULL);
        if (buf < 0)
        {
            (*cm).mGrabberListen(-1);
        }
        else
        {
            sem_wait(&((*cm).sem));
            pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
            i = (*cm).freeSock.top();
            (*cm).sock[i] = buf;
            if (pthread_create(&((*cm).threadSock[i]), NULL, bRecv, argv)!=0)
                return(0);
            (*cm).mGrabberListen(i);
            pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
        }
    }
    return(0);
}
mServer::mServer()
{
    isListen = false;
    sock = new int[max_connection];
    message_in = new char*[max_connection];
    threadSock = new pthread_t[max_connection];
 
    for(short i=max_connection-1;i>=0;--i)
    {
        sock[i] = 0;
        threadSock[i] = 0;
        freeSock.push(i);
        message_in[i] = new char[size_in];
    }
 
}
mServer::~mServer()
{
    delete[] sock;
    for(int i=0;i<max_connection;++i)
        delete[] message_in[i];
    delete[] message_in;
    delete[] threadSock;
    sem_destroy(&sem);
    close(listener);
}
int mServer::mBind(unsigned int port, char* address)
{
    listener = socket(AF_INET, SOCK_STREAM, 0);
    if (listener<0) return(-1);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);//htonl(0xC0A80365);
    if (bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0) return(-1);
    if (listen(listener, max_connection)<0) return(-1);
    return(0);
}
int mServer::mSend(int sock_id, char* message)
{
    int i = strlen(message);
    message[i]='\0';
    int res = send(sock[sock_id], message,i+1,0);
    return(res);
}
int mServer::mRecv(int sock_id)
{
    int i = recv(sock[sock_id], message_in[sock_id], size_in, 0);
    if (i<=0)
    {
        mClose(sock_id);
    }
    return(i);
}
int mServer::mClose(int sock_id)
{
    close(sock[sock_id]);
    sem_wait(&sem);
    freeSock.push(sock_id);
    mGrabberClose(sock_id);
    if (threadSock[sock_id]!=0) pthread_cancel(threadSock[sock_id]);
    threadSock[sock_id] = 0;
    sock[sock_id] = 0;
    sem_post(&sem);
    return(0);
}
int mServer::mListenStart()
 {
    if (sem_init(&sem, 0, 1)!=0) return(-1);
    if(pthread_create(&threadListener, NULL, bListen, (void*)(this))!=0)
        return(-1);
    isListen = true;
    return(0);
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.09.2011, 23:17
Ответы с готовыми решениями:

Ввод/вывод. Покритикуйте код
Как можно это написать еще лучше (производительнее, эстетичнее, логичнее, экономнее по памяти и строкам)? char *DATA_TEXT =...

Покритикуйте - ка!:)
Покритикуйте - ка!:) www.izobret.tu1.ru

Покритикуйте
mstumaster.ru что то меня смущает в юзабилити, я уже на него смотреть не могу беспристрастно b-( ну и советы по другим...

38
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 654
24.09.2011, 11:39
Студворк — интернет-сервис помощи студентам
niXman, А объясните пожалуйста, как coroutines/green-threads/прочая хрень может работать быстрее ну или тратить меньше ресурсов, чем простое однопоточное асинхронное приложение?
У меня как-то в голове не укладывается)
0
 Аватар для KuKu
1563 / 1041 / 94
Регистрация: 17.04.2009
Сообщений: 2,995
24.09.2011, 12:13  [ТС]
Скорее всего в итоге не работает быстрее, а задержки распределены по всем соединениям/операциями равномерно. Т.е в обычном асинхронном было: 10 клиентов ждут 1 секунду, и 10 ждут 5 секунд. А при coroutines/green-threads/прочая хрень все ждут по 3 секунды.(хотя может какие-то заморочки с распараллеливанием по ядрам есть)
1
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 654
24.09.2011, 12:58
Цитата Сообщение от KuKu Посмотреть сообщение
Скорее всего в итоге не работает быстрее
Ну я под "в голове не укладывается" это и имел ввиду.

Цитата Сообщение от KuKu Посмотреть сообщение
А при coroutines/green-threads/прочая хрень все ждут по 3 секунды.
Каким образом? Я совершенно не понимаю.

Цитата Сообщение от KuKu Посмотреть сообщение
хотя может какие-то заморочки с распараллеливанием по ядрам есть
Нет, переключение контекста cpu убъет машину однозначно.
0
 Аватар для KuKu
1563 / 1041 / 94
Регистрация: 17.04.2009
Сообщений: 2,995
24.09.2011, 13:54  [ТС]
Лучше подождать более осведомленных, я тут в угадайку скорее играю
Про 3 секунды не правильно сказал. Себе представляю так, одному клиенту сервер должен обдумать и отправить 3 независимых блока информации, а другому - 6. При последовательной обработке сервер вначале все отправляет первому, а потом принимается за второго. При сопрограммах отправляет вначале первому один блок, а второму два. Потом снова первому один, второму два и еще раз по кругу. В итоге второй клиент получил свои блоки хоть как в конце, но не скачками, а плавно. Может пример не корректный в практическом плане, но подобные оптимизации наверное больше зависят от специфики сервера и что от него ожидают клиенты.
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 654
24.09.2011, 14:09
Цитата Сообщение от KuKu Посмотреть сообщение
Себе представляю так
Одного не понимаю, кто запрещает сделать также, но без coroutine?

Цитата Сообщение от KuKu Посмотреть сообщение
Лучше подождать более осведомленных
Я только "за")
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
24.09.2011, 15:58
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
На юниксах это makecontext()/swapcontext() ?
я не знаю что это такое)
вот. читать в такой последовательности.
http://blog.think-async.com/20... works.html
http://blog.think-async.com/20... ealed.html
http://blog.think-async.com/20... -code.html
http://blog.think-async.com/20... tines.html

Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
Каких-то своих объектов или объектов ОС?
своих.

Добавлено через 1 минуту
Цитата Сообщение от prik Посмотреть сообщение
как coroutines/green-threads/прочая хрень может работать быстрее ну или тратить меньше ресурсов, чем простое однопоточное асинхронное приложение?
я не говорил что быстрее однопоточной программы.

Добавлено через 2 минуты
Цитата Сообщение от KuKu Посмотреть сообщение
задержки распределены по всем соединениям/операциями равномерно. Т.е в обычном асинхронном было: 10 клиентов ждут 1 секунду, и 10 ждут 5 секунд. А при coroutines/green-threads/прочая хрень все ждут по 3 секунды.
сопрограммы/микропотоки ничего ждать не должны. говоря о сетевом вводе-выводе, я подразумеваю неблокирующий ввод-вывод. а при неблокирующем вводе-выводе, по сути, нет _активного_ожидающего_кода_.

Добавлено через 11 минут
Цитата Сообщение от KuKu Посмотреть сообщение
Себе представляю так, одному клиенту сервер должен обдумать и отправить 3 независимых блока информации, а другому - 6. При последовательной обработке сервер вначале все отправляет первому, а потом принимается за второго.
это пример банального однопоточного сервера с блокирующим вводом-выводом. а теперь добавь к этому неблокирующий вывод, и получишь _однопоточный_сервер_не ожидающий_завершения_операции_ввода-ввода. т.е., при отправке данных первому клиенту, сервер не ждет их доставки. так же и при чтении данных, сервер просто создает операцию чтения и дальше занимается остальными операциями. а когда данные для созданной задачи придут - ты получишь об этом уведомление в виде вызова обработчика поставленной задачи.
это собственно и есть описание принципов asio/libevent. другие не пользовал, но наверняка принцип тот же.

Добавлено через 6 минут
prik, не нужно все понимать буквально.
говоря "кол-во которых может превышать 1000000 без затрат на переключение контекста." - имел ввиду то, что это возможность создать огромное кол-во потоков. но нужно понимать, что это не настоящий потоки который создает ОС, и потому нет переключений контекста. и такие потоки, я бы скорее назвал _псевдопотоками_.

Добавлено через 5 минут
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
На юниксах это makecontext()/swapcontext()
почитал. хм...чего же я раньше этого не встречал. очень забавная штуковина. вот только нужно посмотреть/потестить ран-тайм оверхед.
и для венды нашел реализацию: http://www.codeproject.com/KB/... ntext.aspx
1
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 654
24.09.2011, 16:32
Цитата Сообщение от niXman Посмотреть сообщение
prik, не нужно все понимать буквально.
Кто такие coroutine/green-threads/легкие процессы я примерно представляю. И вроде понимаю, что оно выиграет у решения с системными процессами/потоками за счет отсутствия накладных расходов на переключения контекста(в ОС смысле).
Но я напрочь не понимаю, чем это лучше однопоточного решения или варианта с пулом процессов/потоков.
Мой вопрос/просьба объяснить выделенное.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
24.09.2011, 16:54
Цитата Сообщение от prik Посмотреть сообщение
Но я напрочь не понимаю, чем это лучше однопоточного решения или варианта с пулом процессов/потоков.
Если под "лучше" понимать скорость, то никого выигрыша по сравнению с одной нитью и проигрыш качественной реализации threadpool.
_НО_ кроме скорости выполнения есть еще и скорость/удобство/цена разработки и если некую задачу _удобно_ решать в много_много_тысяч процессов, то ответ ИМХО очевиден.

Добавлено через 7 минут
Цитата Сообщение от niXman Посмотреть сообщение
вот. читать в такой последовательности.
Спс. Но так (как обычно с boost) ничего про внутренне устройство( А я вам уже плакался, что осиливаю их шаблоны с превеликим трудом) Надеялся вы расскажите "что у нее в нутри".


Цитата Сообщение от niXman Посмотреть сообщение
почитал. хм...чего же я раньше этого не встречал. очень забавная штуковина. вот только нужно посмотреть/потестить ран-тайм оверхед.
Я тоже сам не пользовался. По логике вещей цена у него как у longjmp().
1
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
24.09.2011, 22:38
Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
ничего про внутренне устройство
ну что ты в самом деле...
первая ссылка, это как затравка. пример многопользовательского асинхронного эхо-сервера объемом меньше 100 строк.
остальные ссылки, именно в таком порядке, описывают внутреннее устройство и дополняют теорией.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
25.09.2011, 10:34
Цитата Сообщение от niXman Посмотреть сообщение
ну что ты в самом деле...
первая ссылка, это как затравка. пример многопользовательского асинхронного эхо-сервера объемом меньше 100 строк.
Прикидываетесь или реально не понимаете? Я вас пытаю как сделана coroutine в самом boost.
Почему меня это интересует: выше я вам как пример показал набор POSIX функций для переключения контекста, как вы понимаете это действо специфично для разных платформ. Со ответсвенно и на линуксе и на фре они много раз оказывались не работоспособны на cpu отличных от x86. Вот мне и интересно как в библиотеке которую активно пихают в промышленный стандарт устроено сохранение и переключение контекста. Думал вы расскажите...
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 654
25.09.2011, 12:17
На сколько я понимаю это плюсовое безобразие, там вообще нет никакого переключения контекста.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
25.09.2011, 12:31
Угу, там не полная реализация того что называется Duff's device (по тому и stackless) со всеми ее ограничениями, но это пародия на сопрограмму. Я же не много про другое... Пару лет назад в рамках гугловских летних программ для студентов был проект реализовать полноценные сопрограммы для boost. Чем дело кончилось я не знаю, сейчас поискал в boost - их нет, хотел вот у Nixman'а узнать...

Добавлено через 2 минуты
Цитата Сообщение от prik Посмотреть сообщение
плюсовое безобразие
Вы прямо как линуксячий папа
1
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 654
26.09.2011, 14:02

Не по теме:

Цитата Сообщение от g_u_e_s_t Посмотреть сообщение
Вы прямо как линуксячий папа
Вы мне льстите.


Если все-таки вернуться к началу обсуждения.
Я так и не понял как лучше реализовать высокопроизводительный эхо сервер?
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
26.09.2011, 14:58
Цитата Сообщение от prik Посмотреть сообщение
Я так и не понял как лучше реализовать высокопроизводительный эхо сервер?

asio + пул потоков.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
26.09.2011, 15:27
Самое "вкусное" к сожалению получиться платформозависимым.
Думаю что в не конкуренции окажется OpenBSD с ее SO_SPLICE.
Линукс - либо splice() (ценой 2х лишних дескрипторов на каждый сокет) либо как все (плюс штраф за epoll_ctl()):
не блокируемый асинхронный i/o и пул нитей (как уже и успел сказать Nixman)
1
 Аватар для KuKu
1563 / 1041 / 94
Регистрация: 17.04.2009
Сообщений: 2,995
29.09.2011, 19:17  [ТС]
Можно еще раз для особо медленных) - поправьте, если опять не так понял.
Должен быть один поток, в котором идет идет accept, recv от всех клиентов к примеру через epoll или тому подобное. Плюс пул потоков, который парсит, что пришло от клиентов, думает над ответом и отправляет им ответ. Или куда этот пул нитей?(просто вначале слова потоки это плохо, а потом пулл потоков)
0
725 / 224 / 73
Регистрация: 01.03.2011
Сообщений: 654
29.09.2011, 19:32
Вы говорите все еще об эхо-сервере или уже о чем-то другом?
0
 Аватар для KuKu
1563 / 1041 / 94
Регистрация: 17.04.2009
Сообщений: 2,995
29.09.2011, 20:06  [ТС]
К примеру так
Цитата Сообщение от KuKu Посмотреть сообщение
Грубо говоря там 5к людей, три четверти висят мертвым грузом, четверть раз в 10 секунд отправляют по 200 байт.
+ заставим сервер немного подумать: есть антимат защита и на фразу "!погода Пермь" - он залазит в гисметео и смотрит погоду + на каждого пользователя хранится контактная информация и его заметки. Это так, чтобы сервер был не просто пересыльщик сообщения, а немного лазил по бд и думал.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
30.09.2011, 09:23
KuKu, ваш вопрос на столько расплывчат (например лазил по БД), что ответить как-то более конкретно просто не возможно)
А так да, если вы нагрузите машину полностью (потоками или процессами не важно) будет хорошо.
Вы помниться говорили про IRC, так посмотрите что есть и как работает. Ответьте на вопросы (не мне, себе) типа "а как оно держит 5к пользователей", "чем меня это не устраивает", "где бутылочное горлышко", "что с этим можно сделать" и тд.

Не по теме:

Я бы посоветовал посмотреть на другие языки..

1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.09.2011, 09:23

Покритикуйте
нужна критика по дизайну http://www.unitytrans.ru/

Покритикуйте
Приветствую всех. В сфере продвижения и оптимизации я относительно недавно. Сайт прогнал по каталогам, купил несколько легеньких ссылок,...

Покритикуйте код
Есть класс Студенты (реализован через односвязный список), хотел бы услышать критику по поводу его улучшения, если кому не лень разбираться...

Покритикуйте код
В продолжение моей прошлой темы. Накидал тут игрушку на swing 2048, воспользовался советом который дали другому пользователю. Раньше я уже...

Покритикуйте код
Добрый вечер. Выполнял одно тестовое задание (уже получил отрицательный ответ), буду рад, если скажите все ошибки, а также, как их можно...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
Baragoz - DPS/HPS бот для WoW 3.3.5a, многоязычный
AmbA 26.10.2026
Хотите ещё ботов? У меня есть один! А я пока отдохну от него. https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=12062&stc=1&d=1793007952 Инструкция внутри. Сразу отвечу: А в PvP с ним. . .
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru