static void Main(string[] args) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(new string('_', 55) + "PROGRAMM" + new string('_', 55) + "\n"); Console.ResetColor(); choose : Console.WriteLine("Please choose which service to use - TCP(1) or UDP(2).If you want to change the protocol, write -other protocol- \n"); start : string ch = Console.ReadLine(); if (ch == "1") { try { TcpClient client = new TcpClient(); client.SendTimeout = 1000; client.Connect("127.0.0.1", 8001); byte[] data = new byte[256]; StringBuilder response = new StringBuilder(); NetworkStream stream = client.GetStream(); //Connection confirming do { int bytes = stream.Read(data, 0, data.Length); response.Append(Encoding.UTF8.GetString(data, 0, bytes)); }while (stream.DataAvailable); Console.WriteLine(response.ToString()); Console.WriteLine("Enter operations in this format : NUMBER space OPERATOR space NUMBER"); string message = String.Empty; do { if (message == "other protocol") { stream.Close(); client.Close(); goto choose; } message = Console.ReadLine(); byte[] data1 = Encoding.UTF8.GetBytes(message); stream.Write(data1, 0, data1.Length); StringBuilder result = new StringBuilder(); var data2 = new byte[256]; int bytes = stream.Read(data2, 0, data2.Length); result.Append(Encoding.UTF8.GetString(data2, 0, bytes)); Console.WriteLine("Result = " + result); }while (message != String.Empty); stream.Close(); client.Close(); } catch (Exception e) { Console.WriteLine("Something goes wrong...disconnected"); } } else if (ch == "2") { Console.Clear(); Console.WriteLine("WELCOME \nEnter operations in this format : NUMBER space OPERATOR space NUMBER"); //for sending UdpClient client = new UdpClient(); client.Connect("localhost", 1000); //for getting UdpClient udpClient = new UdpClient(); udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, 8001)); try { IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0); string message = String.Empty; //this object must be sent to the server string result = String.Empty; //this object must be received from server do { //Sending to Math server message = Console.ReadLine(); if (message == "other protocol") { client.Close(); goto choose; } var sendBytes = Encoding.ASCII.GetBytes(message); client.Send(sendBytes, sendBytes.Length); //Receiving result from math server var receiveBytes = udpClient.Receive(ref RemoteIpEndPoint); result = Encoding.ASCII.GetString(receiveBytes); Console.WriteLine("Result = " + result); }while (message != String.Empty); client.Close(); } catch (Exception e) { Console.WriteLine("Something goes wrong...disconnected"); return; } } else { goto start; } }
//Содерэит логику поиска сервера. Сервер может находиться на любом компьютере в локальной сети //И надо как-то выяснить, где именно. Поэтому мы опросим все комрьютеры, //И если на каком-то из них есть сервер, он даст о себе знать //Так же мы будем ждать сервер, если не можем его найти public void FindServer() { //Данные, которые мы будем рассылать в широковещательном UDP сообщении //Будем отсылвать 1 байт, просто потому что. В этом нет какой-то логики //Можем не отсылать данных вообще. //Так же в эту же переменнаю будут записаны данные, которые мы получим от сервера. //А именно - TCP порт сервера var data = new byte[] { 1 }; //Сервер, если он есть в локальной сети, слушает UDP сообщения на 5000 порту //Потому мы быдем отсылать сообшение всем, на порт 5000 var endPoint = new IPEndPoint(IPAddress.Broadcast, 5000); //Номер попытки нахождения сервера. То есть мы первый раз отправляем сообщение о поиске сервера int tryNum = 1; //Создаем формочку, которая будет отображать пользователю информацию, что мы 1 раз //Пытаемся подключиться к серверу. //Это нужно для того, чтобы в ситуации когда сервера нет, и мы пробуем найти его снова и снова, //Пользователь видел, что программа не висит, и все нормально var placeHolder = new PlaceHolderWrapper($"Finding server try #{tryNum}"); //Сохдаем объект для отправки и приема данных по протоколу UDP //ОС сама выберет порт, на котором будет работать этот клиент, потому не передаем //аргументов в конструктор var udpClient = new UdpClient(); //Устанавливаем, что данный клиент будет ждать сообщений только 1000 милисекунд //Если данных нет в течении 1000 секунд - будет брошено исключение //Сделано для того чтобы мы могли отослать новое сообщение, если на старое никто не ответил //Ведь сервер может быть запущен позже, чем клиент udpClient.Client.ReceiveTimeout = 1000; //Условно бесконечный цикл. Сам цикл будет работать вечно, но внутрянняя логика //Прервет его выполнение в необходимый момент while (true) { //Если код внутри блока try выбросит исключение, выполнение перейдет в блок catch //И мы сможем предпринять какие-то действия, обработать эту ситуацию //В данном случае, мы можем получить исключение времени ожидания, //Понять, что переходим на следующую итерацию, уведомить про это пользователя, //И послать новое сообщение try { //Отправляем сообщение длиной в 1 байт всем пк на порт 5000 udpClient.Send(data, data.Length, endPoint); //Ждем, когда сервер вернет нам свой порт. //Если сервер прислал порт, он будет записан в массив data в виде 4-х байт //В переменную endPoint запишется адресс сервера, откуда нам пришло сообщение //Это и есть адрес сервера. Ведь он отправит нам ответ data = udpClient.Receive(ref endPoint); //заканчиваем цикл while, мы получили TCP порт, так что пора к нему присоединяться break; } //В течении секунды не пришло сообщения catch { //Увеличиваем счетчик попыток на 1 tryNum++; //У нашей формы заглушки устанавливаем новый текст для отображения //Так, при каждой попытке мы увидим на консоли ее номер placeHolder.Content = $"Finding server try #{tryNum}"; } } //Отчищаем UDP клиента, он нам больше не понадобится //метод Dispose освободит занятый порт udpClient.Dispose(); //Получаем число, порт сервера, из байт, которые он нам прислал //Чило, а именно порт сервера, хранится в переменной типв=а int //Допустим, порт сервера это 5100 //По сети могут быть переданы только байты, потому данные биты (нули и единицы) //Разбиваются на 4 байта. Почему 4? int занимает 32 бита //А один байт занимает 8 бит. Соответственно любое число типа int может быть разбито на 4 байта //Нам же надо склеить эти байты обратно в int переменнную //BitConverter умеет отдавать байты для конкретного числа и создавать число из байт. //Смело пользуемся им int targetPort = BitConverter.ToInt32(data, 0); //Устанавливаем соединение с сервером. его IP адрес мы получили при получении UDP сообщения tcpClient.Connect(endPoint.Address, targetPort); //Запускаем метод ListenConnectioin, этот метод будет слушать данные от сервера, и вызывать //Событие о том, что пришел какой-то отсет от сервера. Все, кто захотят об этом узнать - узнают Task.Factory.StartNew(ListenConnection); }
public void Send(string text, string ip, int port) { ClientSend.Connect(new IPEndPoint(IPAddress.Parse(ip), port)); byte[] data = Encoding.ASCII.GetBytes(text); ClientSend.Send(data, data.Length); }