Страницы

Поиск по вопросам

Показаны сообщения с ярлыком сервер. Показать все сообщения
Показаны сообщения с ярлыком сервер. Показать все сообщения

среда, 15 апреля 2020 г.

SSH server на Android

#android #ssh #сервер

                    
Можно настроить ssh сервер на андроиде? Как?    


Ответы

Ответ 1



Можно установить приложение из Android Market: SSHDroid, которое реализует SSH-сервер для Android-телефона. Приложение сделано на основе Dropbear SSH.

четверг, 19 марта 2020 г.

Получение данных из URL после знака # (hash) на сервере

#url #ajax #php #сервер


Доброго времени суток Друзья! Продолжаю писать свою CMS систему, среди её "фишек"
будет функция перехода в режим "быстрой навигации".
Режим быстрой навигации, это по сути реализация системы клиент -><- сервер :

Клиент заходит на сайт, обработчик на сервере принимает запрос вида "?m:s;p:h;i:1;",
генерирует каркас(шаблон) и отдаёт.
Клиент получив каркас, отправляет новый запрос(Ajax) на сервер и заполняет принятыми
в ответ данными необходимые поля.

Слишком растянул вступление для вопроса, но хотелось бы по лучше объяснить, что же
я хочу узнать.
При переходе по следующей ссылке : mysite.ru/?m=s&p=h&i=1 сервер получит эти данные
через суперглобальный массив $_GET.
При переходе по следующей ссылке : mysite.ru/#m:s;p:h;i:1; серверу необходимо получить
данные после знака решётки(#).
Всё бы ничего, есть вариант использовать Javascript и с помощью браузера передать
эти данные на сервер, но есть одно "но", а если эту ссылку открыл не браузер, а например
поисковый робот?
И тут собственно возникает вопрос :
Как на сервере только средствами PHP получить данные из URL после знака решётки(#) ?
Использовать функцию parse_url() можно, но она позволяет обработать строку запроса,
а не получить её.
В интернете по этому поводу мало информации, а где то ещё и видел, что средствами
только PHP сделать этого нельзя.
Есть сервис от Яндекс, Яндекс.Музыка, там реализовано аналогичное.
Хочу дополнить свой вопрос :
А можно ли с помощью Javascript превращать текущий URL в URL вида "?m:h;......."
при этом не переходя на него, хотелось бы как то всётаки реализовать такую совместимость
и для поисковика, и для пользователя, который захочет взять ссылку себе на заметку.    


Ответы

Ответ 1



Судя по всему такое всё-таки невозможно. Понимаю, меня тоже такой ответ не устраивает, но был опыт поиска решения. Сервер просто не получает хэш. Так что только яваскриптом его отдельно отправлять. Для поисковых роботов и прочих безяваскриптовых существ должны быть адреса вида mysite.ru/m:s;p:h;i:1;, по которым доступна та же самая информация без аякса.

Ответ 2



Как на сервере только средствами PHP получить данные из URL после знака решётки(#) ? Никак, якоря являются свойством локальной HTML-страницы и не передаются PHP-скрипту в любом случае.

воскресенье, 8 марта 2020 г.

Какое преимущество кластера перед одним сервером?

#база_данных #сервер #железо #кластер #кластеризация


Примерные данные по кластеру:
1 сервер - Балансировщик приложении
2 сервера - Сервер приложении
2 сервера - Сервер БД
1 сервер - Сервер поиска и хранении

Детальной разницы и преимущества не знаю, поэтому хотелось бы узнать у более компететных
участников форума.

Что можно почитать на эту тему? Куда смотреть? 
    


Ответы

Ответ 1



Тема слишком обширная. Много чего можно посоветовать. Но банально. Есть у вас 1 сервер БД, к примеру. Что будет, если он упадёт? Всё плохо. Во-первых, вы данные потеряете (по крайней мере данные с прошлого бекапа). Во-вторых, ваши сервисы остальные работать не смогут без базы. Теперь же, предположим, у вас 3 ноды базы в кластере и настроена репликация (то есть, дублирование данных). Если 1 нода выйдет из строя, то кластер продолжит работу. Если у вас 5 нод, то кластер может выдержать потерю 2 нод. Это, если кратно. Естественно, всё зависит от архитектуру СУБД. Что хорошо для riak, то не очень для mongodb и т.п. Но в целом кластеризация помогает сохранить работоспособность даже при потере каких-то узлов в системе. Плюс, это даёт распределение нагрузки, если хорошо всё связать с loadbalancer'ом. В плане репликации в целом там обычно две модели: master-master. Сложно реализуемый вариант. Обычно при этом попираются принципы ACID. У нас, к примеру, использует RethinkDB, там как раз master-master. Как даунсайд - отсутствие транзакций и т.п. плюшек, которые обычно есть в реляционных базах. В таком варианте все ноды могут писать данные, от этого все проблемы. master-slave. Проще реализовать. Пишет только master и пушит в слейвы. Со слейвов можно только читать. Отсюда простота реализации. Если выходит из строя мастер, то обычно слейвы голосует за то, кто будет новым мастером. Если всё удачно, то слейв становится мастером, а все остальные слейвы переключаются на него. Книги могу посоветовать в большей степени только на английском: Highscalability (: NoSQL Guide от Мартина Фаулера. Best practices по архитектуре в облаке от Amazon. Ещё советую читать статьи про конкретные реализации (по конкретной СУБД). Поможет этот сайт. Как уже сказал, лучше читать статьи про конкретные реализации: всё про репликацию в MaridDB, репликация и кластеризация в Postres. Про Scalability.

Сервер печати в Ubuntu с виртуальным принтером

#linux #сервер #cups


Задача подключить принтер для которого нет драйверов для современных ОС. Предполагаю
следующий принцип действия:


На сервере устанавливается (пусть даже с бубном) принтер, далее на других ПК устанавливается
виртуальный принтер который отправит pdf файл на сервер и проследит за его судьбой,
т.е. постановка в очередь, снятие с печати и т.п.
Как бонус сохранять все файлы отправленные на печать на сервере.


Существуют ли какие нибудь готовые решения?
    


Ответы

Ответ 1



Вам не нужен виртуальный принтер в linux. На сервере с cups устанавливается и настраивается принтер через любые грабли, добивается его внятная работа. Затем правятся ACL для разрешения печати с нужных машин. На клиентов ставится только cups-client, в /etc/cups/client.conf (штатно может не быть даже такой директории, как например в моём debian) пишется: Encryption IfRequested ServerName cups_server_host Никаких драйверов на клиентах не нужно. Всё, печать в системе работает как будто принтер локален и даже штатно экспортирует свои настройки, вроде печати без полей, цветной/чернобелой печати (настройки зависят от драйвера на сервере, но на клиенте настройка для их поддержки не требуется) Сохранение копий всех задач - лучше бы отдельным вопросом. Это явно вопрос к cups-серверу, но я подсказать не могу, не было такой задачи.

вторник, 25 февраля 2020 г.

Невозможно подключиться к серверу с другого IP

#java #android #сервер


Привет! Собрал небольшой "сервер" на Android, используя NanoHTTPD. Код активити:

    mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
    int ipAddress = mWifiManager.getConnectionInfo().getIpAddress();

    SERVER_IP = String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff),
                              (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff));

    try
    {
        mServer = new MyServer(SERVER_IP, SERVER_PORT);
        mServer.start();

        log("Server started! Please visit:");
        log("http://" + SERVER_IP + ":" + SERVER_PORT);
    }
    catch (Exception ex)
    {
        log("Shit! Can't start server!");
        for (StackTraceElement ste : ex.getStackTrace())
        {
            log(ste.toString());
        }
    }


Код сервера:

public class MyServer extends NanoHTTPD
{
    public MyServer(String address, int port)
    {
        super(address, port);
    }

    @Override
    public NanoHTTPD.Response serve(String uri, NanoHTTPD.Method method, Map headers, Map parms, Map files)
    {
        MainActivity.log("Incoming " + method.toString() + " request!");

        String html = "

Hello, World

"; return newFixedLengthResponse(html); } } После запуска приложения в логах появляется надпись: Server started! Please visit: http://192.168.1.3:1450 С другого устройства в той же WiFi сети захожу на страницу, показывается Hello, world!, а на "сервере" в логах Incoming GET request! Но как только я переключаю на "клиенте" WiFi сеть и пытаюсь сделать запрос на "сервер" http://мой.внешний.статический.ip:1450, то во всех браузерах мгновенно выводится ошибка ECONNREFUSED (Connection Refused). В домашней сети я открыл порты 1400-1500 для "сервера" и сделал перенаправление с порта 80 на порт 1450 (чтобы можно было не вводить порт). NAT и прочие провайдерские ограничения отсутствуют. Как можно исправить эту ошибку?


Ответы

Ответ 1



Если вы сделали перенаправление с 80 на 1450, то укажите роутеру на какой IP перенаправлять. И заходите http://мой.внешний.статический.ip:80 тогда. Порты 1400-1500 можете закрыть, раз у Вас перенаправление. И убедитесь, что 80 порт открыт для входящих соединений.

Ответ 2



В общем, это заняло у меня много времени, но я всё же добился своего. По совету @Eugene Krivenja я закрыл порты 1400-1500, ещё раз проверил перенаправление с 80 на 1450 - всё верно. Пытался после этого зайти на сервер - ошибка ECONNREFUSED всё равно возникала, но уже не сразу, а через 20-30 секунд. Ну, я тогда начал действовать кардинально: немного изменил код сервера, очистил и пересобрал проект (на всякий случай, лишний раз не помешает); обновил прошивку роутера и снова сделал перенаправление с порта 80 на 1450 для конкретного IP. Скрин настроек роутера после действий над ним: Затем я запустил приложение-сервер и попытался зайти на него с клиента. Что, собственно, прошло успешно: Ну и на "сервере" появились соответствующие сообщения: Итог. Мне так и не удалось выяснить, что же стало причиной недоступности сервера, однако у меня есть 2 подозрения: Проблема с прошивкой на роутере Мои кривые руки и невозможность для меня сделать всё правильно с первого раза. ...но всё же, после моих радикальных действий сервер запустился и я этому очень рад. P.S. Если возникнет вопрос, мол "Далеко ли ты уйдёшь на 480 Мб оперативки", то отвечу сразу - мне просто было интересно сделать свой "сервер" на Android, кроме как "Hello world" применения я ему не знаю. P.P.S Небольшая заметка для тех, кто тоже захочет так поэкспериментировать: не выбирайте для своего сервера порт меньше 1024 - Android не позволит это сделать.

понедельник, 24 февраля 2020 г.

Шаблонизация в веб приложениях: сервер, клиент, смешанная?

#angularjs #сервер #клиент_сервер #проектирование #веб_программирование


Во мне накопилось немного информации о возможных способах шаблонизации, но я так
и не сумел найти ничего, где понятно объяснялось бы что и в каких случаях лучше использовать.
Поэтому я решил выписать немного плюсов и минусов каждого типа так, как я их понимаю,
и обсудить их с вами... потому что обсудить это мне с кем-нибудь нужно :) 

1. Клиентская шаблонизация с json rest api

Достаем из базы данные => отдаем их на клиент в json/xml => разбираем данные на клиенте,
создавая объекты по клиентским моделям => добавляем каждую полученную модель в DOM. 

плюсы:  


пользователь ждет только нужные ему данные  
в процессе загрузки данных можем показать красивый прелоадер


минусы:


дублируем модели
лишний раз напрягаем клиентский браузер шаблонизацией


2. Тоже rest api, только шаблонизация, в целом, серверная

Достаем из базы данные => создаем из них html код => отдаем на клиент html => на
клиенте просто пихаем полученный html в DOM не думая.
Этот способ мне кажется самым практичным, но о нем почему-то практически не пишут.
Я просто что-то не то читаю, или есть серьезные недостатки, которых я просто не вижу?

плюсы:


первых два из пункта выше  
не дублируем модели


минусы:


выглядит так, будто их нет


3. Классическая серверная шаблонизация... только сервер

Выбираем данные из базы => на сервере это все дело делаем в html, но не кусочек страницы,
а всю страницу целиком => отдаем на клиент заново всю страницу.

плюсы:


не дублируем модели


минусы:


перерисовываем все то, что у пользователя уже было и все вытекающие по типу отсутствия
прелоадеров, пустой белой страницы и так далее


Вопросы


Какие еще есть вариации?
Кто что использует в своих проектах (личных, рабочих, как делают крупные компании...)? 
Почему? 
Какие плюсы и минусы я пропустил/не понял? 
В каком случае что использовать лучше? 

    


Ответы

Ответ 1



Кто что использует в своих проектах (личных, рабочих, как делают крупные компании...)? Крупная компания, более 20 разработчиков на проекте бывает. Либо полный server-side, либо полностью client-side, смешивание только в очень специфичных случаях (возможно бывают такие, сам не встречал). Server-side для проектов, где можно обеспечить full-stack разработчиков, чтобы и сверстать по мелочи, и скрипт на JS написать и запрос к базе сформировать смогли и т.д. Мобильные приложения не требуются, предоставления API для третьих лиц тоже. Чаще всего проекты, где веб-интерфейс минимален перспектив развития интерфейса нет. Client-side если команда большая, разделить можно на фронтэндщиков, бекендщиков, мобильщиков. Минусы - расходы на поддержку линии API. Чаще всего такой подход применяем, причем API first (у нас RAML). Была пара проектов в практике, где ответственность за отображение поделили между сервером и клиентом, очень неприятные впечатления: постоянные вопросы о том, кто за что должен отвечать, вопросы согласованности (например динамически формируемая форма на клиенте и ее перезаполнение в случае ошибочного сабмита). Требования к разработчикам очень высокие, нужно знать и client-side и server-side технологии.

Ответ 2



Во втором случае на самом деле есть куча минусов (кстати, слова "REST API" к нему неприменимы - потому что это не REST и не API). во-первых, возможности разметки в таком режиме получаются "обрезанными" - в частности, многие способы вставки HTML-кода в документ не запускают скрипты; во-вторых, страница, изготовленная из кучи надерганных кусков обычно является кошмаром верстальщика - совершенно не понятно в каком вообще файле надо искать нужный кусок верстки; в-третьих, постоянное дерганье innerHTML негативно сказывается на производительности; в-четвертых, такое решение обычно требует больше трафика чем оба альтернативных. Из плюсов же у него - поддержка большинством серверных фреймворков. По первому варианту - если вы не пишите ничего сложного, то "шаблонизация" клиентский браузер не напрягает. Особенно если использовать не шаблонизаторы, а библиотеки для двунаправленной привязки данных. Дублирование моделей тоже не является особенностью первого варианта - зачастую клиентская модель, серверная модель и модель передачи являются совершенно разными - и это совершенно нормально. Фактически, при переходе от тертьего варианта к первому модель не дублируется, а разделяется на две.

четверг, 13 февраля 2020 г.

Какое кэширование использовать для социальной сети?

#база_данных #сервер #кэширование


Мы написали социальную сеть, в которую ожидается огромное количество посетителей.
Мы решили использовать memory cache для нее. В нашей социальной сети мы используем
комбинации серверов Windows и Linux. Память должна быть установлена ​​на Linux сервере.
Если у вас есть опыт работы с кэш-памятью, подскажите, пожалуйста, которая является
лучшим выбором для такого типа задач? И еще что вы думаете о RADIS, MongoDB, Hibernate
или Memcache?    


Ответы

Ответ 1



Вам надо сначала понять, сколько данных и какие данные вы хотите кешировать! Отсюда сразу станет ясно преимущества и недостатки того или иного решения. Так как непонятно, что Вы хотите кешировать, то напишу от себя (проверено на редис): все статичные шаблоны, используемые для генерирования динамических страниц и данных сложите в кеш (сократите на файловых операциях). Что касается базы данных, то какое бы вы решение ни выбрали, у вас туда войдут только справочники (неизменяемые или редко изменяемые), к примеру кладр, для выбора адреса. Ни в коем случае не ложите туда изменяемые данные или растущие от количества посетителей (уников). На этапе старта будете прыгать от счаться, а впоследствии все упадет мертвым грузом (головные боли, ночи программирования напролет и т.д.). Что еще можно положить (все то, что вешает базу и надолго, но опять же с учетом, что это не будет расти в памяти). Все это легко объясняется, прочитав концепцию (на примере редис): все данные хранятся в памяти. А сколько у Вас памяти (8 гб или супер сервер 16 или распределенная сеть из нескольких серваков (16 или 8*количество серверов + широкий канал между ними))? P.S.: Что касается redis: если Вы хотите использовать расширенный функционал по обработке данных, то несомненно его. Если просто key-value, то любой.

Написание прокси-сервера для чайника

#сервер #proxy #кэширование #прокси


В прошлом вопросе (Вопрос) я выяснил , что для запроса погоды мне нужен прокси сервер,
который будет кэшировать данные с погодного сервера. Писать сервер придется мне самому,
но до этого ни с чем подобным не сталкивался (серверной частью). Писать решил на python
3. Можете ли ткнуть в литературу или дать ссылки как можно реализовать такой кэширующий
сервер, и правильно ли я вообще выбрал python?
    


Ответы

Ответ 1



«По-науке» эта конструкция называется «Обратный прокси» (reverse proxy). У вас есть некоторый backend-сервер, который генерирует какие-то полезные данные, и есть frontend-сервер, который кеширует на себе редкоизменяемые данные. Такая схема чаще используется, для кеширования локальных ресурсов какого-нибудь сайта, чтобы не гонять данные лишний раз, через основной backend-сервер. В вашем случае backend-сервером будет погодный сервер. Если, логику формирования запросов клиенты возьмут на себя, то проще будет использовать некий уже готовый и отлаженный web-сервер. В принципе, тут подойдет любой (nginx, lighttpd, apache, Ваш собственный). Чаще всего для таких целей используют nginx. Он весьма шустр и достаточно прост в настройке. Вот, например, настройки для nginx: http://reviewsignal.com/blog/2013/08/29/reverse-proxy-and-cache-server-with-nginx/ http://ashep.org/2011/nginx-obratnyj-proksi-server/#.V6ECut_XfmE Официальная документация: https://www.nginx.com/blog/nginx-caching-guide/ В итоге у вас получится что-то вроде: events { worker_connections 8096; multi_accept on; use epoll; } http { proxy_cache_path /tmp/cache levels=1:2 keys_zone=cache:60m max_size=1G; server { listen 80; server_name your-proxy-server-name.com; location / { proxy_pass http://any-weather-server.com; proxy_redirect off; proxy_set_header Host $host; proxy_cache STATIC; proxy_cache_valid 200 1d; proxy_cache_use_stale error timeout invalid_header updating \ http_500 http_502 http_503 http_504; } } } Тут надо будет внимательно отнестись к заголовкам, которые ожидает сервер погоды от вас. Вероятно, вам придется немножко поколдовать с proxy_ignore_headers proxy_hide_headers proxy_set_headers Подобную проблему обсуждают тут: https://stackoverflow.com/questions/9230812/nginx-as-cache-proxy-not-caching-anything Заголовки, вам придется настраивать в любом случае, в том числе и если frontend-сервер будете писать сами. Если писать самому, я думаю, было бы проще найти некоторое готовое решение, и его переиспользовать. Например, достаточно просто это сделать с помощью tornado. А в качестве кеша использовать наример memcached или redis. https://stackoverflow.com/questions/16524545/how-to-write-a-web-proxy-in-python

воскресенье, 2 февраля 2020 г.

Заливка большого файла на WEB сервер методом POST python

#python #сервер #http #post


Помогите разобраться в чем проблема.
Хочу залить файл на сервер, использую библиотеку requests.
Маленький файл льется отлично, с большим файлом беда - не уходит.
Код:

import requests
r = requests.get('запорос на урл')
upload_url = r['урл сервера']
file = {'video_file': ('1.mp4', open('S:/1.mp4', 'rb'))}
r2 = requests.post(upload_url, files=file)


ответ питона 

Traceback (most recent call last):
  File "S:/charm/projects/2.py", line 13, in 
    r2 = requests.post(upload_url, files=file)
  File "S:\charm\projects\venv\lib\site-packages\requests\api.py", line 112, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "S:\charm\projects\venv\lib\site-packages\requests\api.py", line 58, in request
    return session.request(method=method, url=url, **kwargs)
  File "S:\charm\projects\venv\lib\site-packages\requests\sessions.py", line 494,
in request
    prep = self.prepare_request(req)
  File "S:\charm\projects\venv\lib\site-packages\requests\sessions.py", line 437,
in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "S:\charm\projects\venv\lib\site-packages\requests\models.py", line 308, in
prepare
    self.prepare_body(data, files, json)
  File "S:\charm\projects\venv\lib\site-packages\requests\models.py", line 496, in
prepare_body
    (body, content_type) = self._encode_files(files, data)
  File "S:\charm\projects\venv\lib\site-packages\requests\models.py", line 159, in
_encode_files
    fdata = fp.read()
MemoryError


Повторю, маленькие файлы грузит отлично.
Что не так?
    


Ответы

Ответ 1



Попробуйте использовать requests-toolbelt: # pip install requests-toolbelt from requests_toolbelt import MultipartEncoder # pip install requests import requests upload_file = open('S:/1.mp4', 'rb') payload = MultipartEncoder({'1.mp4': upload_file}) rs = requests.post('', data=payload , headers={'Content-Type': payload.content_type}) print(rs)

Ответ 2



Если сервер может напрямую файл принимать (в http message-body), то достаточно файл как data передать: import requests with open('1.mp4', 'rb') as file: requests.post(url, data=file)

Ответ 3



Чтобы послать файл на сервер, используя multipart/form-data Сontent-Type как
html-элементом в браузере делают, можно pycurl использовать: import pycurl c = pycurl.Curl() c.setopt(c.URL, url) c.setopt(c.HTTPPOST, [('file', (c.FORM_FILE, filename))]) c.perform() c.close()

среда, 29 января 2020 г.

Сервер и Thread не уживаются

#cpp #сервер #многопоточность


Собираю маленький игровой сервер и никак не мог понять, почему он иногда не работает,
почти один и тот же код в разных проектах. И вот методом скурпулезного выколупывания
вычислил, что если закоментить , то сервер работает. Кто-нибудь может объяснить
почему? Где конфликт и как с этим бороться?
#define MAX_SLOTS 400
#define _CRT_SECURE_NO_WARNINGS
#include
#include
//#include 
#include
using namespace std;
#pragma comment(lib, "WS2_32.lib")
#pragma comment (lib, "mswsock.lib")

#define PORT 11112
#define SERVER "127.0.0.1"

int main()
{
    setlocale(LC_ALL, "Russian");
    WSAData WSADat; // Свойства WinSock (результат функции WSAStartup)
    WSAStartup(0x0202, &WSADat); // Инициализация WinSock
    SOCKET  Socket;

    Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (!Socket)cout << "soket no create" << endl;
    sockaddr_in socketAddr;
    socketAddr.sin_family = AF_INET;
    socketAddr.sin_port = htons(PORT);
    socketAddr.sin_addr.s_addr = 0;
    bind(Socket, (struct sockaddr*)&socketAddr, sizeof(socketAddr));
    listen(Socket, SOMAXCONN);

    SOCKET client_socket;
    sockaddr_in clientAddr;
    int client_addr_size = sizeof(clientAddr);

    // цикл извлечения запросов на подключение из очереди

    while ((client_socket = accept(Socket, (sockaddr *)&clientAddr, &client_addr_size)))
    {
        printf("ghghgf");
    }
    WSACleanup();
    return 0;
}
    


Ответы

Ответ 1



Пролог В целом, я разобрался с сим безобразием. Нашел рабочую студию и потестил, минут 15 заняло. :) Настелим соломки В целом да, accept срабатывает, потому что он возвращает -1. WSAGetLastError говорит 10022. Согласно документации это "неверно настроенный сокет, например, пытаемся делать accept на сокете, для которого не сделали listen". Смотрим на listen - он-то вызывается! Но мы-то знаем, что он возвращает -1 в случае ошибки, а ТС не добавил подобных проверок. Добавляем где-то так: int err = listen(Socket, SOMAXCONN); if (err == -1) { int c = WSAGetLastError(); printf("error = %d\n", c); return 1; } Запускаем. Снова 10022. Комментируем #include - все нормально. Интереснее. Страсти накаляются Значит, неверно сработал предыдущий вызов функции для сокета. А это bind. Проделаем с ним подобное listen. И тут ждет засада - код не компилируется!!! Но документация утверждает, что там все нормально - int bind(...). Снова комментируем #include - все работает. Раскомментируем назад. Переходим на функцию bind и жмем F12 (перейти на декларацию функции). Но мы почему-то в модуле functional. Виновник найден Тут все стает на свои места. Файл thread через вложенные include подтянул functional. А в нем действительно есть функция bind. Да, ее параметры не совсем подходят, но компилятор как-то разрулил. Что делать? Просто напишите вызов функции двоеточиями в начале: ::bind(Socket, (struct sockaddr*)&socketAddr, sizeof(socketAddr)); ::listen(Socket, SOMAXCONN); Теперь будет вызываться нужная функция. Выводы Если функция что-то возвращает, всегда проверяйте результат. И все будет хорошо.

Как задать свой адрес Java сервера на сокетах?

#java #сервер #сокет #localhost


Есть простенький Java сервер на сокетах. Сервер запускается на локальной машине,
поэтому для доступа к нему нужно использовать адрес localhost. Как сделать доступ к
серверу не по имени localhost, а по какому-нибудь другому имени, например example.com
    


Ответы

Ответ 1



Вариант 1. Доступ к серверу нужен только с локальной машины. В этом случае достаточно внести изменения в файл %windir%\System32\drivers\etc\hosts, вписав в него строку 127.0.0.1 example.com Вариант 2. Доступ к серверу нужен с нескольких машин из локальной сети. В этом случае нужно чтобы сервер слушал не только адрес 127.0.0.1, но и адрес, указанный в настройках сетевой карты. Впрочем, можно не заморачиваться и слушать все адреса (0.0.0.0). На остальных машинах нужно также внести изменения в файл hosts. Вариант 3. Нужен доступ из сети Интернет. Это самый сложный случай. Для начала нужен "белый" статический IP-адрес. Этот адрес должен быть либо у сервера, либо у какого-либо устройства, способного "пробрасывать" нужные порты на ваш сервер. Далее у какого-либо регистратора покупаем доменное имя example.com и вносим в настройки этого доменного имени так называемую A-запись, в которой и будет указан "белый" статический IP-адрес.

Ответ 2



Если я правильно понял,в файле hosts у тебя должно быть следующее: 127.0.0.1 localhost добавь такую же строку и поменяй localhost на то, что тебе нужно

Как понять нагрузку на сервер?

#linux #сервер #centos #веб_сервер #статистика


может кто-то объяснить как понять вот эти цифры?

то что они показывают нагрузку на 1 минуту, 5 минут и 15 минут - знаю

а что означает например 0.67?

у нас 2 процессора по 12 ядер каждый

до какого значения должно быть максимум нагрузка чтобы чтобы сервер работал нормально?
    


Ответы

Ответ 1



Показатель Load Average показывает, сколько в среднем процессов в системе стояло в очереди на выполнение и выполнялось в каждом из трёх указанных промежутков времени. Здесь «стоит в очереди на выполнение» означает, что процесс не находится в состоянии "sleep" и не ожидает завершения операции ввода-вывода, но и не является выполняющимся в данный квант процеесорного времени. То есть ему не мешает стать выполняющимся ничего, кроме того факта, что процессор в данный момент занят выполнением другого процесса. Например, если на иначе ничем не занятой одноядерной системе запустить три процесса, занимающихся активными вычислениями чего-либо (то есть не задействующих ввод-вывод), то показатель LA будет находиться в районе чуть выше 3.00. Что́ есть «сервер работает нормально» обычно точно не известно, поэтому, как уже отметили в комментарии, надо проводить нагрузочное тестирование. Иногда и при достаточно низких показателях LA, но при сильной нагрузке на диск производительность сервера начинает проваливаться заметно раньше теоретического «LA / кол-во ядер > 1», но я обычно рассматриваю именно это значение (то есть когда LA больше, чем количество ядер/HT-потоков) как предельное, при достижении которого процессор сервера явно нуждается в апгрейде (или ПО — в оптимизации). Или, по-другому выражаясь, неизвестно, будете ли вы отмечать тормоза при LA < 24, но то, что при LA > 24 вы их точно будете отмечать — это к бабке не ходи.

Ответ 2



htop + F2 (Load +) Средние значения нагрузки в Linux — это «средние значения нагрузки системы», показывающие потребность в исполняемых потоках (задачах) в виде усреднённого количества исполняемых и ожидающих потоков. Это мера нагрузки, которая может превышать обрабатываемую системой в данный момент а что означает например 0.67? (нагрузку ,была на 15 мин назад ) Load Average — среднее значение загруженности системы за период времени (в дальнейшем LA). Три значения показывают усреднённую нагрузку за последние 1, 5 и 15 минут. LA является одним из самых спорных показателей. Можно найти множество противоречивых статей, какое значение считать нормальным. Обычно принимается, что значение 0 это простой ядра, а значение 1 это полная нагрузка ядра. Оценить показатель средней нагрузки можно только зная количество ядер в системе. Узнать сколько ядер доступно можно командой: dmidecode -t processor | grep "Core Enabled:" Core Enabled: 6 Core Enabled: 6 Видим, что на данной системе находится 12 физических ядер (6+6). Соответственно, нормальный показатель LA должен быть менее 12. Смотри atop

Плюсы и минусы создания сервера на своем компьютере

#сервер #хостинг


Не могу найти хорошего хостинга, тот дорогой, а тот не подходит. Решил рискнуть поставить
на компьютер сервер, не могли бы вы написать плюсы и минусы этой затеи.    


Ответы

Ответ 1



Плюсы: Ты сам себе хозяин. Много места для твоих проектов. Минусы: Постоянный шум компьютера. Расходы на электричество. Убиваешь свое железо. Очень затратно. Нужно постоянно мониторить, обслуживать сервер. Постоянный онлайн, нужны средства на оплату трафика (если он не безлимитный) Я бы не советовал заниматься данным мазохизмом, не пожалей пару баксов и возьми себе нормальный хостинг, меньше геморроя будет. Я бы посоветовал jino.ru. В любом случае это обойдется тебе дешевле, чем свой сервер. И я сомневаюсь что ты будешь использовать всю мощь своего сервера.

Ответ 2



Плюсы имеются при выполнении двух условий: если есть ненужный компьютер, если есть бесплатный быстрый интернет. Минусы: никакой поддержки (владелец уехал в отпуск - сервер упал), никакой надежности (отключили электричество в подъезде, сервер упал), никакой скорости (обычная домовая сеть), это не так уж и дешево (посчитайте, сколько стоит электричество и трафик). Для более-менее серьезных проектов домашний сервер неприемлим из-за вышеуказанных минусов. Хороших хостингов, вообще говоря, много.

Ответ 3



Во всяком случае, домашний сервер - это замечательный способ стать хорошим сисадмином.

Ответ 4



Если не подходят хостинги, так можно же виртуальный сервер арендовать, если у буржуйской компании, то это не сильно дорого. Я думаю дешевле обойдётся, чем именно свой домашний сервер.

пятница, 24 января 2020 г.

Mysql entity framework - Не удалось найти запрошенного поставщика данных

#mysql #сервер #entity_framework #развертывание


Имеется Web API приложение использующее сервер баз данных MySQL. На девелоперской
машине работает прекрасно. Перенёс приложение на сервер и после обращения к странице
вылетает исключение:

{
    ClassName: "System.ArgumentException",
    Message: "Указанный поставщик хранилища не найден в конфигурации или недопустим.",
    Data: null,
    InnerException: - {
    ClassName: "System.ArgumentException",
    Message: "Не удалось найти запрошенного поставщика данных .Net Framework. Возможно
он не установлен.",
    Data: null,
    InnerException: null,
    HelpURL: null,
    StackTraceString: " в System.Data.EntityClient.EntityConnection.GetFactory(String
providerString)",
    RemoteStackTraceString: null,
    RemoteStackIndex: 0,
    ExceptionMethod: "8 GetFactory System.Data.Entity, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089 System.Data.EntityClient.EntityConnection System.Data.Common.DbProviderFactory
GetFactory(System.String)",
    HResult: -2147024809,
    Source: "System.Data.Entity",
    WatsonBuckets: null,
    ParamName: null
    },
    HelpURL: null,
    StackTraceString: " в System.Data.EntityClient.EntityConnection.GetFactory(String
providerString) в System.Data.EntityClient.EntityConnection.ChangeConnectionString(String
newConnectionString) в System.Data.Entity.Internal.LazyInternalConnection.TryInitializeFromAppConfig(String
name, AppConfig config) в System.Data.Entity.Internal.LazyInternalConnection.Initialize()
в System.Data.Entity.Internal.LazyInternalConnection.CreateObjectContextFromConnectionModel()
в System.Data.Entity.Internal.LazyInternalContext.InitializeContext() в System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type
entityType) в System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() в System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
в System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider()
в System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate)
в MMSBDWebApplication.Models.UserModel.Login(String login, String password) в MMSBDWebApplication.Controllers.v1.UserController.Test()",
    RemoteStackTraceString: null,
    RemoteStackIndex: 0,
    ExceptionMethod: "8 GetFactory System.Data.Entity, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089 System.Data.EntityClient.EntityConnection System.Data.Common.DbProviderFactory
GetFactory(System.String)",
    HResult: -2147024809,
    Source: "System.Data.Entity",
    WatsonBuckets: null,
    ParamName: null
}


Конфигурационный файл:




  
    
    
Структура файлов полностью идентичны, как на сервере так и на девелоперской машине. Все библиотеки на месте. В чём может быть еще проблема?


Ответы

Ответ 1



Проблему решил, установив MySql Connector

четверг, 23 января 2020 г.

Как настроить маршрутизацию для двух сетевых карт с внешними ip?

#ubuntu #сервер #ip #маршрутизация


Имеется сервер с двумя сетевыми картами. В обе карты заходят два внешних IP (разные
подсети и маски).

Как сделать, чтобы извне их можно было пинговать одновременно? 

Прописываю маршрут route add -net 0.0.0.0 netmask 0.0.0.0 gw x.x.x.x dev p1p1, пинг
на первую сетевую идет, на вторую — нет, и наоборот.
    


Ответы

Ответ 1



первое, что я бы порекомендовал — удалить пакет network-manager: он облегчает настройку сети в тривиальных ситуациях и лишь мешает в нетривиальных. настройка маршриутизации для разных нетривиальных случае хорошо описана в документе, известном под названием lartc. есть и переводы на русский, например на opennet. в частности, про настройку маршрутизации для двух провайдеров написано в разделе 4.2. есть неплохая (на вид) пошаговая инструкция по настройке балансировки между двумя провайдерами (тремя несколько разными способами).

пятница, 10 января 2020 г.

Как и сколько соединений открывать из приложения с сервером БД mysql?

#cpp #mysql #сервер #сокет


Есть многопоточный сервер на с++, который работает с mysql базами.
Проблема в том, что открытие одного соединения на одного клиента не подходит из-за
большой нагрузки на сервер, а использование одного соединения с базой на все приложение
чревато большими проблемами. Подскажите как решить эту проблему.    


Ответы

Ответ 1



Обычно в таких случаях используют пул соединений (connection pool). Суть его в том, что к базе открывается ограниченное число соединений (например, 10). Каждый раз, когда клиент пытается подключиться к базе, мы выдаём ему соединение из пула. После оекончания работы с базой (отсоединения клиента) соединение возвращается в пул, но не закрывается, а по приходу нового запроса отдаётся следующему клиенту. Плюсы такого подхода - не нужно тратить время на переоткрытие соединений с базой. Минусы - ограниченное число одновременных подключений к базе, сложности реализации. На вашем месте я бы не стал писать пул самостоятельно, а поискал бы готовые реализации в Интернете (сам я, к сожалению, не пользовался подобным в C++, поэтому ничего конкретного посоветовать не могу).

понедельник, 6 января 2020 г.

WebSocket - Как правильно хранить соединения?

#javascript #nodejs #сервер #websocket


Стало непонятно:

при каждом обновлении страницы у пользователя, на сервере создается новый объект
соединения.. 

Вопрос: Как держать этот объект актуальным?

Пришло в голову хранить это соединение в БД и при создании нового соединения, обновлять
значение из этой БД для определенного пользователя... то есть, есть некая структура:

user_id | socket
     34 |  {obj}


есть пользователь с идентификатором 34, у него есть свой объект соединения ws, который
храниться в socket, и как я уже говорил, - при каждом создании нового соединения, будет
обновляться значения из поля socket

скажите правильно ли это?

P.S. Для сайта вопросов-ответов
    


Ответы

Ответ 1



Пришло в голову хранить это соединение в БД Хо-хо-о! Эм, нет, это плохая идея. Соединение вещь очень контекстная для конкретного процесса и её не стоит класть в общедоступное хранилище, т. к. если его заберёт оттуда другой процесс, он не получит работающего соединения, поскольку ОС выделяла ресурсы на это другому процессу. ...это при условии, если у вас получится объект соединения сериализовать в последовательность байт для записи в БД (база ведь хранит данные). А скорее всего, вся затея оборвётся уже на этом этапе, т. к. вы просто не сможете получить необходимых для воспроизведения данных даже в рамках того же процесса. Плюс надо иметь в виду, что пользователь может находиться на сайте с нескольких вкладок и/или даже устройств одновременно, и наверное, вам нужно уметь держать несколько активных соединений на одного пользователя сразу. Вы уже чувствуете этот дух приключений? Если вы работаете всего с одним процессом, то вы можете хоть в глобальном объекте их хранить. Нечто похожее socket.io и делает по умолчанию, а socket.io-express-session из ответа @Darth вам поможет быстрее сопоставлять пользователей и соединения. Но это ещё не конец истории, если ваше приложение работает в нескольких процессах. Потому что пользователь, подключившись к процессу, висит только на нём. Послать сообщение ему в соединение из другого процесса вашего же приложения будет невозможно. Для этого придуман socket.io-adapter (абстрактный) и его реализации, например socket.io-redis, дающий связь между процессами приложения через Redis. В этом случае свои соединения каждый процесс всё равно хранит где-то у себя, в глобальном объекте, но другие процессы даже при этом всё равно могут к ним обращаться.

Ответ 2



Воспользуйтесь модулем socket.io-express-session. Тогда вы сможете пользоваться всеми преимуществами сессий и вам не надо будет придумывать велосипед, для того чтобы каждый раз передать id юзера при переподключении

четверг, 2 января 2020 г.

Технология tcp/ip сервера

#cpp #linux #сервер #unix


У меня есть сервер написанный на C++ для *UNX, основанный на "неблокирующих сокетах
с использованием select" - Пример данный реализации есть в интернете, я использовал
эту конструкцию для своего сервера и хочу удостоверится оптимальная ли логика работы
сервера для моей задачи.

Задача: Что должен делать мой сервер:

1) Принимать клиентов СТРОГО по авторизации и держать с ними соединение.

2) Выполнять действия по команде клиента (Запрос в бд, чтение запись в файл, и т.д)

3) Передавать файлы клиенту по его запросу. 

Число клиентов от 15 000 тысяч.

Пример конструкции на которой основан моей сервер.

int main()
{
    int listener;
    struct sockaddr_in addr;
    char buf[1024];
    int bytes_read;

    listener = socket(AF_INET, SOCK_STREAM, 0);
    if(listener < 0)
    {
        perror("socket");
        exit(1);
    }

    fcntl(listener, F_SETFL, O_NONBLOCK);

    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425);
    addr.sin_addr.s_addr = INADDR_ANY;
    if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("bind");
        exit(2);
    }

    listen(listener, 2);

    set clients;
    clients.clear();

    while(1)
    {
        // Заполняем множество сокетов
        fd_set readset;
        FD_ZERO(&readset);
        FD_SET(listener, &readset);

        for(set::iterator it = clients.begin(); it != clients.end(); it++)
            FD_SET(*it, &readset);

        // Задаём таймаут
        timeval timeout;
        timeout.tv_sec = 15;
        timeout.tv_usec = 0;

        // Ждём события в одном из сокетов
        int mx = max(listener, *max_element(clients.begin(), clients.end()));
        if(select(mx+1, &readset, NULL, NULL, &timeout) <= 0)
        {
            perror("select");
            exit(3);
        }

        // Определяем тип события и выполняем соответствующие действия
        if(FD_ISSET(listener, &readset))
        {
            // Поступил новый запрос на соединение, используем accept
            int sock = accept(listener, NULL, NULL);
            if(sock < 0)
            {
                perror("accept");
                exit(3);
            }

            fcntl(sock, F_SETFL, O_NONBLOCK);

            clients.insert(sock);
        }

        for(set::iterator it = clients.begin(); it != clients.end(); it++)
        {
            if(FD_ISSET(*it, &readset))
            {
                // Поступили данные от клиента, читаем их
                bytes_read = recv(*it, buf, 1024, 0);

                if(bytes_read <= 0)
                {
                    // Соединение разорвано, удаляем сокет из множества
                    close(*it);
                    clients.erase(*it);
                    continue;
                }

                // Отправляем данные обратно клиенту
                send(*it, buf, bytes_read, 0);
            }
        }
    }

    return 0;
}


Авторизация и приём команд происходит в блоке 

for(set::iterator it = clients.begin(); it != clients.end(); it++)
    {
        if(FD_ISSET(*it, &readset))
        {
            // Поступили данные от клиента, читаем их
            bytes_read = recv(*it, buf, 1024, 0);

            if(bytes_read <= 0)
            {
                // Соединение разорвано, удаляем сокет из множества
                close(*it);
                clients.erase(*it);
                continue;
            }
           /* Проверяем что за команда и дальнейшие действия с ней */
        }


Если от клиента пришла команда загрузки файла, то сервер создаёт новый поток для
отправки файла.
Команды и файлы отправляются через один порт что не очень хорошо.

Вопросы:

1) Подойдёт ли данная конструкция сервера для реализации моей задачи?

2) Какие ещё есть варианты сервера для реализации моей задачи? (Можно и с потоками
там форк или аналоги)

Приоритеты: Обычно тут идёт выбор между производительностью и ресурсами, я предпочитаю
выбор производительности и надёжности сервера.

Готов к критики новым идеям и технологиям в рамках моей темы, но не личности (Шутка).
    


Ответы

Ответ 1



если Вы планируете работать с 15000 пользователей одновременно, то этот код работать не будет. В целом, написание серверов, которые держут 10к пользователей одновременно - уже не такая тривиальная задача. Но Ваш код будет держать одновременно не более 1024 пользователей (на самом деле где то 900-950, нужно глубже код копать). Вся суть в select. Он просто не умеет больше (там просто массив на 1024 элемента). Но главное, что нужно понимать, что это значит не то, select умеет управлять 1024 дескрипторами, а дескрипторами, номера которых меньше 1024. Если нужно много клиентов, то первое, что нужно сделать, это заменить select на poll (замена на самом деле не очень сложная, но работать будет лучше, хотя на больших наборах медленнее - poll тратит 8 байт на сокет). Если нужно ещё быстрее - есть epoll и подобные вещи. Следующая ошибка - Вы читаете с помощью recv, но похоже надеетесь, что все данные придут сразу. Это очень распространенная ошибка. Если с одной стороны отправить send на 100 байт, то с другой стороны может прочитаться как 100 байт одновременно, а может и 20, а вторым пакетом 80. То есть, данные могут разрываться как угодно, гарантируется только порядок байт и то, что байты не будут "утеряны произвольно". Поэтому, прочитав данные, нужно проанализировать буфер. Если там данных недостаточно, то ждать следующего чтения, которым дописать данные в конец буфера и снова анализировать. Вполне возможно, что после этого в буфере будет вся первая команда и начало второй. Или даже первая, вторая и начало третей. Точно также с командой send. Она не гарантирует, что все данные будут отправлены. Она возвращает кол-во байт, которые были отправлены. Поэтому нужно организовывать досылку данных.

Как подключить 2-й выделенный IP

#linux #apache #сервер #ip #vds


Приветствую, есть VDS и 2 выделенных IP, один давали с покупкой VDS (и сейчас доступ
по нём открыт), а 2-й купил дополнительно. 

Как мне подключить 2-й IP адрес к этому VDS, что бы при запросе на него открывались
файлы, к примеру, из директории /var/www/site2/ не подключая к доменам? 
И доступ к директориям должен быть непосредственно по IP.

Спасибо.
    


Ответы

Ответ 1



Для начала вам нужно назначить этот IP вашем сетевому интерфейсу. Как это делается - зависит от дистрибутива. Это либо файл /etc/network/interfaces для Debian/Ubuntu, либо /etc/sysconfig/network-scripts/ifcfg-* для CentOS/Fedora. Вы же знаете какая у вас ОС? Посмотрите её документацию. Далее вам нужно сказать про этот IP веб-серверу. Если в директории Listen не указан конкретный IP - то Apache слушает все имеющиеся адреса. Если вас это устраивает - оставляйте, в противном случае впишите лишь новый адрес, если вы хотите что бы обращения принимались лишь на него. Далее - у вас уже есть VirtualHost который настроен на директорию /var/www/site2/ или нет? Если нет, создайте его, указав примерно такое: > DocumentRoot "/var/www/site2/" <остальные_директивы_по_вкусу> В конце не забудьте применить новую конфигурацию.

Ответ 2



Похоже, вам нужен виртуальный хост, привязанный к IP. В конфигурации Apache httpd добавляете раздел ServerAdmin webmaster@www1.example.com DocumentRoot "/var/www/site2/" ServerName www1.example.com ErrorLog "/www/logs/www1/error_log" CustomLog "/www/logs/www1/access_log" combined Разумеется, подправив адреса и имена файлов в соответствии с вашими.

вторник, 31 декабря 2019 г.

Почему происходит утечка памяти?

#c_sharp #net #сервер #сокет #память


Есть метод который делает скриншот экрана каждые 20 мс и отправляет его клиенту.
Но после нескольких минут работы программа сжирает всю память, хотя вроде бы не должна.
Где происходит утечка памяти? 

private static async void Send(Socket handler)
    {
        await Task.Run(async () =>
        {
            try
            {
                while (true)
                {
                    ImageSource image = ScreenCapture.CopyScreen();
                    byte[] message = ImageSourceToBytes(new JpegBitmapEncoder(), image);
                    handler.Send(message);
                    await Task.Delay(20);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Сервер: " + ex.Message);
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }
        });

    }



  Методы работы с изображениями:


public static byte[] ImageSourceToBytes(BitmapEncoder encoder, ImageSource imageSource)
    {
        byte[] bytes = null;
        var bitmapSource = imageSource as BitmapSource;

        if (bitmapSource != null)
        {
            encoder.Frames.Add(BitmapFrame.Create(bitmapSource));

            using (var stream = new MemoryStream())
            {
                encoder.Save(stream);
                bytes = stream.ToArray();
            }
        }

        return bytes;
    }

 public static class ScreenCapture
{
    public static BitmapSource CopyScreen()
    {
        var left = Screen.AllScreens.Min(screen => screen.Bounds.X);
        var top = Screen.AllScreens.Min(screen => screen.Bounds.Y);
        var right = Screen.AllScreens.Max(screen => screen.Bounds.X + screen.Bounds.Width);
        var bottom = Screen.AllScreens.Max(screen => screen.Bounds.Y + screen.Bounds.Height);
        var width = right - left;
        var height = bottom - top;

        using (var screenBmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
        {
            using (var bmpGraphics = Graphics.FromImage(screenBmp))
            {
                bmpGraphics.CopyFromScreen(left, top, 0, 0, new System.Drawing.Size(width,
height));
                return Imaging.CreateBitmapSourceFromHBitmap(
                    screenBmp.GetHbitmap(),
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    BitmapSizeOptions.FromEmptyOptions());
            }
        }
    }
}


UPDATE. Добавлен скриншот профайлера.

    


Ответы

Ответ 1



Проблема в том, что если вы вызываете функцию Bitmap.GetHbitmap, то вам необходимо вручную вызывать функцию DeleteObject из gdi32.dll для хэндлера, который вернула GetHbitmap. В противном случае действительно будет утечка. Вот немного модифицированный класс ScreenCapture: public class ScreenCapture : IDisposable { [DllImport("gdi32.dll")] private static extern bool DeleteObject(IntPtr hObject); private IntPtr hBitmap = IntPtr.Zero; private bool disposed; public BitmapSource CopyScreen() { if (disposed) throw new ObjectDisposedException(typeof(ScreenCapture).FullName); var left = Screen.AllScreens.Min(screen => screen.Bounds.X); var top = Screen.AllScreens.Min(screen => screen.Bounds.Y); var right = Screen.AllScreens.Max(screen => screen.Bounds.X + screen.Bounds.Width); var bottom = Screen.AllScreens.Max(screen => screen.Bounds.Y + screen.Bounds.Height); var width = right - left; var height = bottom - top; using (var screenBmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { using (var bmpGraphics = Graphics.FromImage(screenBmp)) { bmpGraphics.CopyFromScreen(left, top, 0, 0, new System.Drawing.Size(width, height)); hBitmap = screenBmp.GetHbitmap(); return Imaging.CreateBitmapSourceFromHBitmap( hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } } } public void Dispose() { if (!disposed) { if (hBitmap != IntPtr.Zero) { DeleteObject(hBitmap); hBitmap = IntPtr.Zero; } disposed = true; } } } Код отправки в сокет: while (true) { byte[] message = null; using (var capture = new ScreenCapture()) { ImageSource image = capture.CopyScreen(); message = ImageSourceToBytes(new JpegBitmapEncoder(), image); } handler.Send(message); await Task.Delay(20); }