Простейшие коды клиент-сервера UDP - C#
Формулировка задачи:
Собственно, вопрос избитый уверен. Помогите, плиз, разобраться.
Пишу контрольную.
Простейшие коды клиент-сервера UDP:
Клиент:
Сервер:
Вроде все хорошо, однако, при подключении более одного клиента видно, что сервер отправляет сообщение (не широковещательное) а именно тому клиенту от которого получил сообщение.
Как сделать так, чтоб сервер отсылал в сеть сообщения всем клиентам.
Подключаю клиенты прямо с локалхоста. При отладке вижу, что отличаются порты.
Уверен, что проблема в том, что я чего-то недопонимаю. В поиске был - толи чего-то опять упустил, либо просто не нашел подходящей инфы.
Не пинайте, плиз сильно - помогите советом.
Спасибо.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class Udp_Client
{
public static void Main()
{
byte[] data = new byte[1024];
string input, stringData;
//Ввод IP-адреса сервера
Console.Write("Укажите IP-адрес сервера: ");
string addr = Console.ReadLine();
//Если адрес пустой - принимаем за локалхост
if (addr == "") addr = "127.0.0.1";
//Создание нового UDP-клиента и установка удаленного узла по умолчанию
UdpClient server = new UdpClient(addr, 9050);
//создаем конечную точку по адресу сокета. Т.е. будем "слушать" порты
//и контролировать все сетевые интерфейсы
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
//Отправляем серверу сообщение о подключении
string welcome = "Клиент успешно подключился!";
data = Encoding.UTF8.GetBytes(welcome);
server.Send(data, data.Length);
//От сервера придут данные, типа "Подключение успешно"
data = server.Receive(ref sender);
//Обеспечиваем их отображение на экране
Console.Write("Сообщение принято от {0}:", sender.ToString());
stringData = Encoding.UTF8.GetString(data, 0, data.Length);
Console.WriteLine(stringData);
//Бесконечный цикл.
while (true)
{
//Объявляем новый массив под пришедшие данные.
data = new byte[1024];
//Ожидаем ввода с клавиатуры (строки) и заносим в переменную input
Console.Write("\r\n>");
input = Console.ReadLine();
//Перевод отсылаемой строки в байты
data = Encoding.UTF8.GetBytes(input);
//Отсылаем серверу строку (переведенную в байты)
server.Send(data, data.Length);
//Если пришла команла exit - выходим из цикла (далее - закрываем сокет и т.д.)
if (input == "exit") break;
//Получение данных...
data = server.Receive(ref sender);
//Перевод принятых байтов в строку
stringData = Encoding.UTF8.GetString(data, 0, data.Length);
Console.Write("<");
//Отображение на экране принятой строки (размер файла)
Console.WriteLine(stringData);
}
//После выхода из цикла...
Console.WriteLine("Остановка клиента...");
//Закрываем UDP-соединение
server.Close();
}
}using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
public class UDP_Server
{
public static void Main()
{
int recv;
byte[] data = new byte[1024];
//Сетевая конечная точка в виде адреса и номера порта
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
//Создание нового сокета (схема адресации, тип сокета, протокол)
//параметр AddressFamily задает схему адресации. В нашем случае это адреса IPv4
//параметр SocketType указывает, какой тип сокета применяется.
//Datagram - поддерживает двусторонний поток данных. Не гарантируется, что этот поток будет последовательным,
//надежным, и что данные не будут дублироваться. Важной характеристикой данного сокета является то,
//что границы записи данных предопределены.
//последний параметр, ProtocolType, задает тип протокола
Socket SrvSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
//Связываем новый сокет с локальной конечной точкой
SrvSock.Bind(ipep);
Console.WriteLine("Ожидаем соединения с клиентом...");
//создаем конечную точку по адресу сокета. Т.е. будем "слушать" порты
//и контролировать все сетевые интерфейсы
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
//Получаем конечную удаленную точку
EndPoint Remote = (EndPoint)(sender);
//Получаем сообщение от клиента (типа, "Клиент успешно подключился!")
recv = SrvSock.ReceiveFrom(data, ref Remote);
//Отображаем сообщение о успешно подключенном клиенте
Console.Write("Сообщение получено от {0}:", Remote.ToString());
Console.WriteLine(Encoding.UTF8.GetString(data, 0, recv));
//Отправляем клиенту сообщение об успешном подключении
string welcome = "Подключение к серверу успешно!";
data = Encoding.UTF8.GetBytes(welcome);
SrvSock.SendTo(data, data.Length, SocketFlags.None, Remote);
//Бесконечный цикл.
while (true)
{
//Объявляем новый массив под пришедшие данные.
data = new byte[1024];
//Получение данных...
recv = SrvSock.ReceiveFrom(data, ref Remote);
//Перевод принятых байтов в строку
string str = Encoding.UTF8.GetString(data, 0, recv);
//Если пришла команда выхода
//Завершаем работу сокета и программы...
if (str == "exit") break;
Console.WriteLine("Получили данные: " + str);
//Записываем в переменную size новый размер файла (после процедуры prntofile)
double size = prntofile(str);
//Отображаем форматированное сообщение
string input = "Строка успешно записана!\nНовый размер файла: " + size + " байт.";
Console.WriteLine(">" + input + "\n");
//Перевод отсылаемой строки в байты
data = Encoding.UTF8.GetBytes(input);
//Отсылаем серверу строку (переведенную в байты)
SrvSock.SendTo(data, data.Length, SocketFlags.None, Remote);
}
}
//Процедура записи в файл и вычисления размера
public static double prntofile(string str)
{
//Определяем имя файла
string fil = "Mystr_Srv.txt";
StreamWriter sw;
FileInfo fi = new FileInfo(fil);
//Открываем файл на appendtext
sw = fi.AppendText();
//Записываем в файл строку
sw.WriteLine(str);
//Закрываем файл.
sw.Close();
//Вычисляем размер файла (в байтах).
double size = fi.Length;
//Возвращаем размер файла.
return size;
}
}Решение задачи: «Простейшие коды клиент-сервера UDP»
textual
Листинг программы
Console.WriteLine(stringData);