UDP сообщения не приходят с первого раза - C#
Формулировка задачи:
Мне надо сделать прогу, которая при запуске кидает широковещательный опрос, есть ли сервер, если ответа не приходит, значит нет, и она становится сервером. Если же сервер есть, то он получает это сообщение и в ответ кидает сообщение "вот он я, сервер", и тот становится как бы клиентом.
Я сделал, что при нажатии на кнопку кидается бродкаст (вроде бы), запускается нить, ожидающая ответа, через нек время эта нить вырубается, если овтета всё ещё нет. Если ответ был, то пишется, что это клиент. Если же ответа не было, то пишется, что это сервер, и запускается нить, принимающая сообщения, и дающая ответ на них.
Так вот, запускаю я 2 экземпляра этой проги на двух компах. На первом жму старт, он становится сервером, на втором жму старт, он становится сервером. Если отключиться-подключиться, то же самое. Если же на втором остаться, сервером, а отключиться-подключиться на первом, то первый станет сервером, но если опять отключитсья-подключиться, то первый становится клиентом (т. е. теперь уже правильно работает). И если дальше отключать-подключать первый, то он будет всегда становиться сервером. Если же опять отключить их обоих, а потом подключить любой, а потом подключать-отключать противоположный, то этот противоположный будет становиться в первый раз сервером, а все последующие разы клиентом.
Помогите кто-нибудь, в чём тут прикол? Я там некоторое время менял всякое, как-то сделал, чтобы для каждой отправки создавался новый UDPClient и закрывался потом, и оно стало всё правильно работать по-началу, а потом стало всегда выкидывать исключения про то, что нельзя больше одного сокета использовать единовременно.
button2_click - кнопка подключения и отключения.
wait_response - ожидание ответа при попытке найти сервер
server_listen - поток, если прога стала сервером, принимающий запросы на подключение и дающий ответы
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Windows.Forms; using System.Net; using System.Net.Sockets; namespace LabRab2TVPiS { public partial class Form1 : Form { public Form1() { InitializeComponent(); } bool connected = false; bool server = false; int port; string serverIP; UdpClient client; List<string> ip_clients_list = new List<string>(); Thread listenThread; AutoResetEvent startEvent=new AutoResetEvent(false); private void button2_Click(object sender, EventArgs e) { if (connected) { connected = false; button2.Text = "Начать работу"; label8.Text = "здрастє"; if (server) listenThread.Abort(); client.Close(); } else { client = new UdpClient(port); button2.Enabled = false; string myHost = Dns.GetHostName(); IPHostEntry listHost = Dns.GetHostByName(myHost); string myIP = listHost.AddressList[0].ToString(); richTextBox1.Text += myIP + "\n"; IPAddress broadcast = IPAddress.Parse(myIP.Remove(myIP.LastIndexOf('.')) + ".255"); byte[] sendbuf = Encoding.ASCII.GetBytes("c"+myIP); IPEndPoint endPoint = new IPEndPoint(broadcast, port=Convert.ToInt16(textBoxPort.Text)); Thread waitThread = new Thread(wait_response); waitThread.Start(null); client.Send(sendbuf, sendbuf.Length, endPoint); bool received = waitThread.Join(4000); if (received) { label8.Text = "Це клієнт"; server = false; } else { label8.Text = "Це сервер"; waitThread.Abort(); listenThread = new Thread(server_listen); listenThread.Start(null); server = true; } button2.Text = "Отключиться"; connected = true; button2.Enabled = true; } } void wait_response(object obj) { while (true) { IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, port); byte[] bytes = client.Receive(ref groupEP); string str = Encoding.ASCII.GetString(bytes, 0, bytes.Length); if (str[0] == 'C') { serverIP = str.Remove(0, 1); break; } } } void server_listen(object obj) { while (true) { IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, port); byte[] bytes = client.Receive(ref groupEP); string str=Encoding.ASCII.GetString(bytes, 0, bytes.Length); if (str[0] == 'c') { ip_clients_list.Add(str.Remove(0, 1)); string myHost = Dns.GetHostName(); IPHostEntry listHost = Dns.GetHostByName(myHost); string myIP = listHost.AddressList[0].ToString(); IPAddress broadcast = IPAddress.Parse(ip_clients_list.Last()); byte[] sendbuf = Encoding.ASCII.GetBytes("C" + myIP); IPEndPoint endPoint = new IPEndPoint(broadcast, port); client.Send(sendbuf, sendbuf.Length, endPoint); } } } } }
Решение задачи: «UDP сообщения не приходят с первого раза»
textual
Листинг программы
using System; using System.Net; using System.Net.Sockets; using System.Threading; namespace ConsoleApplication183 { class Program { private const int port = 33444; static void Main(string[] args) { var udp = new UdpClient(port, AddressFamily.InterNetwork); udp.MulticastLoopback = false; IPEndPoint serverIP = null; var counter = 10; while(counter-- > 0) { //отправляем броадкаст udp.Send(new byte[] { 13 }, 1, new IPEndPoint(IPAddress.Broadcast, port)); //принимаем ответ if (udp.Available > 0) { var bytes = udp.Receive(ref serverIP); //проверяем ответ if (bytes.Length == 1 && bytes[0] == 14) break;//ответ успешно получен serverIP = null; } Thread.Sleep(100); } if (serverIP == null) { Console.WriteLine("This is server"); //начинаем цикл сервера StartServer(udp); } else Console.WriteLine("This is client, server addr: {0}", serverIP); Console.ReadLine(); } private static void StartServer(UdpClient udp) { while (true) { if (udp.Available > 0) { IPEndPoint remoteClient = null; var bytes = udp.Receive(ref remoteClient); Console.WriteLine("Received from " + remoteClient); //это броадкаст запрос? if (bytes.Length == 1 && bytes[0] == 13) //отправляем ответ udp.Send(new byte[] {14}, 1, remoteClient); } Thread.Sleep(10); } } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д