Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.93/15: Рейтинг темы: голосов - 15, средняя оценка - 4.93
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
1

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

08.04.2019, 16:28. Показов 2833. Ответов 19

Author24 — интернет-сервис помощи студентам
Задание такое:
Написать программу, которая будет автоматически находить свои запущенные экземпляры в локальной сети и подключаться к ним для передачи текстовых сообщений.

Есть у кого-нибудь идеи? Как это реализовать?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.04.2019, 16:28
Ответы с готовыми решениями:

Необходимо создать приложение, которое будет автоматически обновляться с API
Мне необходимо создать сайт, который извлекает данные из биржи по API. Мне нужно чтобы серверная...

Разработать приложение, которое будет автоматически выдавать случайные фразы
Помогите пожалуйста решить задачи по php, завтра екзамен!!!(наброски, предложения, я в этом чайник)...

Доступ к файлу Write и Read (Серверное приложение которое будет принимать данные из сети и записывать в XML)
Коротко о том, что хочу сделать.Серверное приложение которое будет принимать данные из сети и...

Комп перестал видеть сетевую карту и сетевое подключение к локальной сети
комп перестал видеть сетевую карту и сетевое подключение к локальной сети, в диспечере оборудования...

19
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
23.05.2019, 13:58 2
Лучший ответ Сообщение было отмечено kzkmrf2010 как решение

Решение

Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
Написать программу, которая будет автоматически находить свои запущенные экземпляры в локальной сети и подключаться к ним для передачи текстовых сообщений.
Будем использовать UDP протокол для передачи данных.
Для построения списка клиентов - каждый экземпляр будет регулярно отправлять пустые сообщения (heartbeat).
Для отправки/приема сообщения будем использовать асинхронные методы BeginReceive/EndReceive и BeginSend/EndSend из UdpClient.

Сначала создадим класс Host, который будет хранить информацию об удаленном хосте (IP адрес и время получения последнего heartbeat):
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    /// <summary>
    /// Keep data of remote host
    /// </summary>
    class Host
    {
        public IPAddress IP { get; set; }
        public DateTime LastHeartbeat { get; set; }
 
        public void OnHeartbeatReceived()
        {
            LastHeartbeat = DateTime.Now;
        }
 
        public override string ToString()
        {
            return IP.ToString();
        }
    }
Далее, создадим класс Server, который будет инкапсулировать прием/отправку сообщений через UDP, а также будет автоматически отправлять heartbeat:
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
    /// <summary>
    /// UDP server/client with auto heartbeats
    /// </summary>
    class Server
    {
        private const int HEARTBEAT_INTERVAL = 1000;
 
        public int Port = 45450;
        public event Action<IPEndPoint, byte[]> MessageReceived = delegate { };
 
        private UdpClient udp;
 
        /// <summary>
        /// Start
        /// </summary>
        public void Start()
        {
            //start udp client
            udp = new UdpClient(Port);
            //start receive messages
            udp.BeginReceive(OnReceived, null);
            //start heartbeat loop (in background thread)
            ThreadPool.QueueUserWorkItem(HeartbeatLoop);
        }
 
        /// <summary>
        /// Send message (broadcast)
        /// </summary>
        public void SendMessageAsync(byte[] bytes)
        {
            SendMessageAsync(bytes, new IPEndPoint(IPAddress.Broadcast, Port));
        }
 
        /// <summary>
        /// Send message to remote host
        /// </summary>
        public void SendMessageAsync(byte[] bytes, IPEndPoint endPoint)
        {
            //send async
            udp.BeginSend(bytes, bytes.Length, endPoint, OnSent, null);
        }
 
        private void OnSent(IAsyncResult ar)
        {
            //finsh sending
            udp.EndSend(ar);
        }
 
        private void OnReceived(IAsyncResult ar)
        {
            //receve bytes
            var remote = new IPEndPoint(IPAddress.Broadcast, Port);
            var bytes = udp.EndReceive(ar, ref remote);
 
            //fire event
            MessageReceived(remote, bytes);
 
            //start receive next message
            udp.BeginReceive(OnReceived, null);
        }
 
        private void HeartbeatLoop(object state)
        {
            //infinity loop
            while (true)
            {
                //wait
                Thread.Sleep(HEARTBEAT_INTERVAL);
 
                //send broadcast empty message
                udp.Send(new byte[0], 0, new IPEndPoint(IPAddress.Broadcast, Port));
            }
        }
    }
Для отправки сообщения реализован асинхронный метод SendMessageAsync (два варианта - широковещательная отправка и отправка конкретному адресату), а для приема сообщений - событие MessageReceived.

Также сделаем высокоуровневый класс Controller, который будет хранить в себе сервер, список удаленных хостов, будет принимать сигналы heartbeat и строить список онлайн хостов. Также этот класс будет содержать методы для отправки сообщения и событие приема сообщений:
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
    class Controller
    {
        const int DEAD_INTERVAL = 3000;
        const int CHECK_DEAD_INTERVAL = 1000;
 
        private object locker = new object();
 
        public Server Server { get; private set; }
        public List<Host> Hosts { get; private set; } = new List<Host>();
 
        public event Action<IPAddress, string> MessageReceived = delegate { };
        public event Action HostsChanged = delegate { };
 
        public void Start()
        {
            //start server
            Server = new Server();
            Server.MessageReceived += ServerMessageReceived;
            Server.Start();
 
            //start main loop
            ThreadPool.QueueUserWorkItem(RemoveDeadHostsLoop);
        }
 
        public void SendMessage(string message)
        {
            var bytes = Encoding.UTF8.GetBytes(message);
            Server.SendMessageAsync(bytes);
        }
 
        private void ServerMessageReceived(IPEndPoint remote, byte[] bytes)
        {
            //is heartbeat?
            if (bytes.Length == 0)
                OnHeartbeatReceived(remote.Address);
            else
            {
                //is message
                var str = Encoding.UTF8.GetString(bytes);
                MessageReceived(remote.Address, str);
            }
        }
 
        private void OnHeartbeatReceived(IPAddress remoteIP)
        {
            //find host
            var host = Hosts.FirstOrDefault(h => h.IP.Equals(remoteIP));
 
            //not found => create new host
            if (host == null)
            {
                //new host
                host = new Host() { IP = remoteIP };
                lock (locker)
                    Hosts.Add(host);
 
                //fire event
                HostsChanged();
            }
 
            //update heartbeat of host
            host.OnHeartbeatReceived();
        }
 
        private void RemoveDeadHostsLoop(object state)
        {
            while (true)
            {
                Thread.Sleep(CHECK_DEAD_INTERVAL);
 
                var deadTime = DateTime.Now.AddMilliseconds(-DEAD_INTERVAL);
                var count = 0;
 
                lock (locker)
                    count = Hosts.RemoveAll(h => h.LastHeartbeat < deadTime);
 
                //fire event
                if (count > 0)
                    HostsChanged();
            }
        }
    }
Теперь остается только создать главную форму, и связать объект Controller с контролами формы:
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
    public partial class MainForm : Form
    {
        private Controller controller;
 
        public MainForm()
        {
            InitializeComponent();
 
            controller = new Controller();
            controller.HostsChanged += Controller_HostsChanged;
            controller.MessageReceived += Controller_MessageReceived;
            controller.Start();
        }
 
        private void Controller_MessageReceived(IPAddress remote, string message)
        {
            if (InvokeRequired)
            {
                Invoke((MethodInvoker)(()=> { Controller_MessageReceived(remote, message); }));
                return;
            }
            tbMessages.AppendText(remote + Environment.NewLine + message + Environment.NewLine);
        }
 
        private void Controller_HostsChanged()
        {
            ftHosts.Build(controller.Hosts);
        }
 
        private void btSendMessage_Click(object sender, EventArgs e)
        {
            controller.SendMessage(tbNewMessage.Text);
            tbNewMessage.Clear();
        }
 
        private void tbNewMessage_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                btSendMessage.PerformClick();
        }
    }
Приложение готово:
Сетевое приложение, которое будет автоматически находить свои запущенные экземпляры в локальной сети
Вложения
Тип файла: zip WindowsFormsApplication406.zip (105.0 Кб, 10 просмотров)
2
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
23.05.2019, 17:24  [ТС] 3
Storm23, а что надо сделать для переработки этого решения под tcp протокол?
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
23.05.2019, 22:50 4
Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
а что надо сделать для переработки этого решения под tcp протокол?
Для этого нужно изначально точно формулировать задачу.
1
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
23.05.2019, 22:53  [ТС] 5
Storm23, извините, решение полностью соответствует задаче, просто нужна реализация на tcp
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
23.05.2019, 23:55 6
TCP совершенно не подходит для этой задачи, по крайней мере в одиночку
единственный вариант это банально сканировать диапазон сети и стучаться к каждому адресу, это жутко неэффективно и бессмысленно
1
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
24.05.2019, 00:02  [ТС] 7
m0nax, к сожаление, задание по tcp, подходит или нет, не мне решать(
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
24.05.2019, 00:28 8
Лучший ответ Сообщение было отмечено kzkmrf2010 как решение

Решение

Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
переработки этого решения под tcp протокол
По аналогии с классом Server, создаем класс ClientServerTCP:

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
    class ClientServerTCP
    {
        private TcpListener listener;
 
        public int Port = 45451;
        public event Action<IPEndPoint, byte[]> MessageReceived = delegate { };
 
        public void Start()
        {
            //start tcp listener
            listener = new TcpListener(Port);
            //start receive tcp incoming connections
            listener.Start();
            listener.BeginAcceptTcpClient(OnIncomingConnection, null);
        }
 
        private void OnIncomingConnection(IAsyncResult ar)
        {
            //finish accept incoming connection
            var tcp = listener.EndAcceptTcpClient(ar);
 
            //start receive next message
            listener.BeginAcceptTcpClient(OnIncomingConnection, null);
 
            //receive message
            using (var stream = tcp.GetStream())
            using (var br = new BinaryReader(stream))
            {
                //read data size
                var size = br.ReadInt32();
                //read data
                var data = br.ReadBytes(size);
                //fire event
                MessageReceived(tcp.Client.RemoteEndPoint as IPEndPoint, data);
            }
        }
 
 
        /// <summary>
        /// Send message to remote host (via TCP)
        /// </summary>
        public void SendMessageAsync(byte[] bytes, IPAddress remote)
        {
            //send async
            var tcp = new TcpClient();
            tcp.BeginConnect(remote, Port, (ar) => OnTCPConnected(ar, tcp, bytes), null);
        }
 
        private void OnTCPConnected(IAsyncResult ar, TcpClient tcp, byte[] bytes)
        {
            //finish connect
            tcp.EndConnect(ar);
 
            //send
            using (var stream = tcp.GetStream())
            using (var bw = new BinaryWriter(stream))
            {
                //send data size
                bw.Write(bytes.Length);
                //send data
                bw.Write(bytes);
            }
        }
    }
Он содержит асинхронный сервер, который может принимать TCP сообщения, и содержит метод SendMessageAsync, который может отправлять сообщения по TCP на удаленный порт.

В класс Controller добавляем поле ClientServerTCP и стартуем его при старте контроллера, аналогично старту Server.
Также в класс Controller добавляем метод SendMessage который будет передавать данные по TCP на конкретный хост.

Теперь класс Controller может передавать как широковещательные сообщения по UDP, так и сообщения на определенный хост по TCP.
Нахождение клиентов друг друга по прежнему делается через heartbeats по UDP.

Далее, немного изменяем интерфейс. Создадим чекбокс Broadcast. Если Broadcast = false, то сообщение будет отправляться по TCP на хост, выделенный в списке слева. Если же Broadcast = true, то сообщения будут отправляться всем клиентам по UDP.

Сетевое приложение, которое будет автоматически находить свои запущенные экземпляры в локальной сети
Вложения
Тип файла: zip WindowsFormsApplication406 (2).zip (144.0 Кб, 8 просмотров)
1
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
24.05.2019, 17:14  [ТС] 9
Цитата Сообщение от Storm23 Посмотреть сообщение
Нахождение клиентов друг друга по прежнему делается через heartbeats по UDP.
А есть возможность сделать нахождение по tcp?
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
24.05.2019, 17:55 10
Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
А есть возможность сделать нахождение по tcp?
Ну вам уже выше писали, что TCP не подходит для таких дел. Можно как-то извращаться, но UDP в данном случае - оптимальный вариант. То, что вашему преподу хочется странного - не повод делать плохие вещи.
1
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
28.05.2019, 20:27  [ТС] 11
Storm23,
Цитата Сообщение от Storm23 Посмотреть сообщение
public event Action<IPEndPoint, byte[]> MessageReceived = delegate { };
Можно подробнее описать эту строчку? Инкапсулирует метод...Для чего она вообще нужна?

Добавлено через 21 минуту
Storm23,
Цитата Сообщение от Storm23 Посмотреть сообщение
IAsyncResult ar
И почему где-то нам надо знать состояние асинхронной операции, а где-то null?

Добавлено через 33 минуты
Storm23,
Цитата Сообщение от Storm23 Посмотреть сообщение
tcp.BeginConnect(remote, Port, (ar) => OnTCPConnected(ar, tcp, bytes), null);
Можно как-нибудь подробнее расписать эту строку?

Добавлено через 7 минут
Storm23,
Цитата Сообщение от Storm23 Посмотреть сообщение
private object locker = new object();
Для чего нам lock?

Добавлено через 49 секунд
Цитата Сообщение от Storm23 Посмотреть сообщение
lock (locker)
здесь

Добавлено через 21 минуту
Цитата Сообщение от Storm23 Посмотреть сообщение
var host = Hosts.FirstOrDefault(h => h.IP.Equals(remoteIP));
и какие два ip мы сравниваем?
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
29.05.2019, 23:10 12
Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
Можно подробнее описать эту строчку? Инкапсулирует метод...Для чего она вообще нужна?
Для того что бы не проверять событие на null при его вызове. Смотрите здесь https://stackoverflow.com/ques... -of-c#9282

Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
И почему где-то нам надо знать состояние асинхронной операции, а где-то null?
Я не знаю о чем вы, приводите фрагменты кода.

Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
Можно как-нибудь подробнее расписать эту строку?
Я не знаю, что там непонятного. Мы просим tcpclient приконектится к удаленному порту. Когда он приконектится - вызовется метод OnTCPConnected. Для понимания конструкции с "=>" читайте про лямбды в C#.

Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
Для чего нам lock?
Потому, что когда мы работаем с асинхронными сокетами, все события происходят в разных потоках. Поэтому нужно использовать синхронизации при доступе к общим ресурсам.

Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
и какие два ip мы сравниваем?
Здесь ищется Host, IP которого равен remoteIP.

kzkmrf2010,
Все ответы на ваши вопросы можно найти в учебнике C#.
1
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
30.05.2019, 14:40  [ТС] 13
Storm23, спасибо большое за ваши ответы.
Как можно разбить программу на две части. Т.е. сервер udp отправляет запрос по локальной сети (один раз) "кто здесь?". Клиенты отвечают ему "я здесь" и отправляют серверу свой ip. Дальше формируется список ip. После клиенты находятся в режиме ожидания "слушают"(на tcp). Сервер уже по tcp отправляет каждому клиенту сообщение, например, "я тебя вижу".

Добавлено через 4 часа 27 минут
Storm23, благодаря Вам, я стала намного лучше разбираться с клиент-серверными приложениями. Начали интересовать различные варианты. Извините, что задаю так много вопросов.
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
30.05.2019, 14:58 14
Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
я стала намного лучше разбираться с клиент-серверными приложениями
Ну вот и отлично, значит вам не составит труда самостоятельно доработать приложение как вам нужно.
0
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
30.05.2019, 18:14  [ТС] 15
Storm23, нуу если бы мне это не составило труда, я б здесь не просила...

Добавлено через 49 минут
Storm23, вы сможете помочь еще раз?
0
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
01.06.2019, 20:44  [ТС] 16
Storm23, Вроде как справилась, единственное вылетает ошибка "Подключение не установлено, т.к. конечный компьютер отверг запрос на подключение 192.168.0.2:45450"
Если несложно, посмотрите код пожалуйста.

Сервер:
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
class Host
    {
        public IPAddress IP { get; set; }
        public override string ToString()
        {
            return IP.ToString();
        }
    }
    class Server
    {
        public int port = 45450;
        private object locker = new object();
        public List<Host> Hosts { get; private set; } = new List<Host>();
 
        public delegate void Action(IPEndPoint ip, byte[] bytes);
        public event Action MessageReceived;
 
        public delegate void Action2();
        public event Action2 HostsChanged;
 
        Client client = new Client();
        private UdpClient udp;
 
        public void StartUDP()
        {
            udp = new UdpClient(port);
            //начинаем получение пустого сообщения
            udp.BeginReceive(OnReceived, null);
            ThreadPool.QueueUserWorkItem(HeartbeatLoop);
            MessageReceived += ServerMessageReceived;
        }
        //отправляем пустое сообщение по udp
        private void HeartbeatLoop(object state)
        {
            udp.Send(new byte[0], 0, new IPEndPoint(IPAddress.Broadcast, port));
        }
        private void OnReceived(IAsyncResult ar)
        {
            IPEndPoint remote = new IPEndPoint(IPAddress.Broadcast, port);
            byte[] bytes = udp.EndReceive(ar, ref remote);
            //событие
            MessageReceived(remote, bytes);
            //начинаем получение следующего сообщения
            udp.BeginReceive(OnReceived, null);
        }
 
        private void ServerMessageReceived(IPEndPoint remote, byte[] bytes)
        {
            if (bytes.Length == 0)
                OnHeartbeatReceived(remote.Address); return;
        }
        private void OnHeartbeatReceived(IPAddress remoteIP)
        {
            //ищем хост
            Host host = Hosts.FirstOrDefault(h => h.IP.Equals(remoteIP));
 
            //если не нашли слздаем новый хост
            if (host == null)
            {
                //new host
                host = new Host() { IP = remoteIP };
                lock (locker)
                    Hosts.Add(host);
 
                //событие
                HostsChanged();
            }
        }
        //отправка по tcp
        public void SendMessage(string message, IPAddress remote)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(message);
           Connect(bytes, remote);
        }
        public void Connect(byte[] bytes, IPAddress remote)
        {
            TcpClient tcp = new TcpClient();
            tcp.BeginConnect(remote, port, (ar) => OnTCPConnected(ar, tcp, bytes), null);
        }
        public void OnTCPConnected(IAsyncResult ar, TcpClient tcp, byte[] bytes)
        {
            tcp.EndConnect(ar);
 
            NetworkStream stream = tcp.GetStream();
            BinaryWriter bw = new BinaryWriter(stream);
            {
                bw.Write(bytes.Length);
                bw.Write(bytes);
            }
        }
    }
Клиент:
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
 class Client
    {
        private TcpListener listener;
 
        public int port = 45451;
        public delegate void Action(IPEndPoint ip, byte[] bytes);
        public event Action MessageReceived;
        public delegate void Action2(IPAddress ip, string msg);
        public event Action2 MessageReceived2;
 
        public void Start()
        {
            listener = new TcpListener(port);
            listener.Start();
            listener.BeginAcceptTcpClient(OnIncomingConnection, null);
            MessageReceived += ClientMessageReceived;
        }
 
        private void OnIncomingConnection(IAsyncResult ar)
        {
            TcpClient tcp = listener.EndAcceptTcpClient(ar);
 
            //начинаем получение следующего сообщения
            listener.BeginAcceptTcpClient(OnIncomingConnection, null);
 
            //получаем сообщение
            NetworkStream stream = tcp.GetStream();
            BinaryReader br = new BinaryReader(stream);
            {
                int size = br.ReadInt32();
                byte[] data = br.ReadBytes(size);
                MessageReceived(tcp.Client.RemoteEndPoint as IPEndPoint, data);
            }
        }
        private void ClientMessageReceived(IPEndPoint remote, byte[] bytes)
        {
            string str = Encoding.UTF8.GetString(bytes);
            MessageReceived2(remote.Address, str);
        }
    }
Форма:
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
public partial class MainForm : Form
    {
        Server server = new Server();
        Client client = new Client();
        public MainForm()
        {
            InitializeComponent();
            server.HostsChanged += HostsChanged;
            client.MessageReceived2 += AddMessageReceived;
            server.StartUDP();
            client.Start();
        }
 
        private void AddMessageReceived(IPAddress remote, string message)
        {
            if (InvokeRequired)
            {
                Invoke((MethodInvoker)(()=> { AddMessageReceived(remote, message); }));
                return;
            }
            tbMessages.AppendText(remote + "\n" + message + "\n");
        }
 
        private void HostsChanged()
        {
            ftHosts.Build(server.Hosts);
        }
 
        private void btSendMessage_Click(object sender, EventArgs e)
        {
                Host remote = ftHosts.SelectedNode as Host;
                if (remote == null) return;
                server.SendMessage(tbNewMessage.Text, remote.IP);
                tbMessages.AppendText("Sent to " + remote + " via TCP" + "\n" + tbNewMessage.Text + "\n");
                tbNewMessage.Clear();
        }
    }

Ошибка пропадает, и всё работает, если методы
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void Connect(byte[] bytes, IPAddress remote)
        {
            TcpClient tcp = new TcpClient();
            tcp.BeginConnect(remote, port, (ar) => OnTCPConnected(ar, tcp, bytes), null);
        }
        public void OnTCPConnected(IAsyncResult ar, TcpClient tcp, byte[] bytes)
        {
            tcp.EndConnect(ar);
 
            NetworkStream stream = tcp.GetStream();
            BinaryWriter bw = new BinaryWriter(stream);
            {
                bw.Write(bytes.Length);
                bw.Write(bytes);
            }
        }
перенести из класса Server в Client. Но хочется, чтобы было логично и отправка сообщений осуществлялась из класса Server....
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
02.06.2019, 09:51 17
Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
перенести из класса Server в Client. Но хочется, чтобы было логично и отправка сообщений осуществлялась из класса Server....
Во-первых, это совсем не логично. Клиент - это тот кто начинает обмен данными, Сервер - тот кто отвечает на запрос клиента.
Во-вторых, у вас тут нет разделения на клиенты и сервера, потому что у вас peer-to-peer. Оба хоста являются одновременно и клиентами и серверами.

Ну а ошибка понятно почему падает. Вы же зачем то кусок кода перенесли в другой класс, а там порт другой, вот оно и не может приконектится. У вас для UDP - должен быть порт 45450, а для TCP - 45451.
1
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
02.06.2019, 12:12  [ТС] 18
Цитата Сообщение от Storm23 Посмотреть сообщение
должен быть порт 45450, а для TCP - 45451.
слепня потому что, поэтому и не увидела. Последний вопрос, можно ли как-то прописать алгоритм, чтобы сервер по порядку подключался к найденным адресам и автоматически отправлял введенное сообщение, т.е. без выделения адреса вручную в FastTree.
0
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
02.06.2019, 15:38 19
Цитата Сообщение от kzkmrf2010 Посмотреть сообщение
Последний вопрос, можно ли как-то прописать алгоритм, чтобы сервер по порядку подключался к найденным адресам и автоматически отправлял введенное сообщение, т.е. без выделения адреса вручную в FastTree.
Конечно можно. У вас есть список Host, перебирайте их по одному и отправляйте каждому.
Хотя изначально оно же по UDP всем и отправляло, вы глупостью какой-то занимаетесь.
0
5 / 4 / 1
Регистрация: 28.11.2017
Сообщений: 38
02.06.2019, 15:40  [ТС] 20
Storm23, может и глупостью, но дано задание, которое надо выполнить... То что надо перебирать Host, я понимаю. Может подскажете каким способом.
0
02.06.2019, 15:40
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.06.2019, 15:40
Помогаю со студенческими работами здесь

Создать приложение, которое будет запускать Word
Помогите с работой в Word. Задание следующее: Создать приложение, которое будет запускать Word,...

Приложение, которое будет на ПК уведомлять об уведомлениях на телефоне
Как &quot;отлавливать&quot; уведомления всех приложений? Хочу сделать приложение, которое будет на ПК...

Приложение для анкетирования в локальной сети
Добрый день! Хочу попросить, чтобы вы мне подсказали, какие источники почитать и в каком...

Клиентское приложение + БД (ORACLE) в локальной сети
Каким образом можно реализовать данную схему: приложени android связывается и взаимодействует с БД,...

Generic Host Process for Win32 Services-обнаружена ошибка. Приложение будет закрыто. Приносим свои извинения
Добрый день, помогите, пожалуйста разобраться. По какой причине появляется окошко с надписью:...

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru