Работаем с сокетами в C# по UDP-протоколу

И немного рекламы: Приточная вентиляция в доме http://dav.kiev.ua/ru/vent/ventiljacija.html: вытяжная вентиляция

Для наглядности напишем два приложения, которые будут общаться друг с другом. Одно будет сервером, другое клиентом. Общаться они будут по UDP протоколу.

Клиентское приложение

Начнем с клиента… Создаем консольный проект. В проекте пишем две функции, одна из которых будет «слушать» и «отвечать» на запросы. Назовем ее Listen.

//Для клиента
publiс void Listen()
{
	int recv; //храним размер полученных данных
	byte data = new byte[1024]; //данные, которые будут передаваться или приниматься

	//создаем новый сокет
	//параметр AddressFamily задает схему адресации. В нашем случае это адреса IPv4
	//параметр SocketType указывает, какой тип сокета применяется.
	//В данном случае SocketType.Dgram это ненадежные сообщения, но для примера хватит.
	//Тем более, что Dgram поддерживает протокол UDP
	//последний параметр, ProtocolType, задает тип протокола
	Socket mysocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

	//создаем конечную точку по адресу сокета. Т.е. будем "слушать" порт 9051 и контролировать все сетевые интерфейсы
	IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9051);
	mysocket.Bind(ipep); //привязываем точку к нашему сокету

	//создаем еще одну точку
	IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);

	//определяем сетевой адрес
	EndPoint Remote = (EndPoint)(sender);

	//отправляем первое сообщение нашему серверу
	string text = "Hello"; //текст сообщения
	data = Encoding.ASCII.GetBytes(text); //переводим строку в байты

	//отправляем на указанны адрес
	//первый параметр это сами данные в виде массива байт
	//второй параметр, какая длиная сообщения должна быть передана.
	//Если указать меньше, то передаст только то число символов, сколько укажете
	//третий параметр указывает поведение сокета при приеме и получении данных. В нашем случае ничего...
	//четвертый парамерт задает адрес и порт сервера, которому нужно отправить сообщение
	//что делает функция _getHost, смотрите чуть ниже...
	//в данном примере используется бродкастовый адрес подсети 192.168.15.255,
	//если мы не знаем по какому адресу находится сервер. Порт подставляем любой (1111), он все равно будет перезаписан в функции _getHost
	//Использование функции SendTo позволяет заранее не соединяться с сервером
	mysocket.SendTo(data, data.Length, SocketFlags.None, _getHost("192.168.15.255:1111"));

	//запускаем бесконечный цикл, который будет принимать и отправлять данные
	while (true)
	{
		data = new byte[1024];
		//принимаем данные от сервера. recv содержир размер, т.е. количество принятых символов
		recv = mysocket.ReceiveFrom(data, ref Remote);
		//в данном примере сервер шлет сообщение, которое разделено ":"
		//разбираем его в массив
		//функция Encoding.ASCII.GetString переводит массив байт в строку
		string[] args = Encoding.ASCII.GetString(data, 0, recv).ToLower().Split(':');
	    foreach(string item in args)
		{
			Console.WriteLine("Сервер отправил " + item);
		}
		//отправим ответ что мы получили. Например, первый элемент массива
		data = Encoding.ASCII.GetBytes(args[0]);

		//Remote содержит адрес, с которого пришло сообщение. Ему его назад и отправляем
		mysocket.SendTo(data, data.Length, SocketFlags.None, _getHost(Remote.ToString()));
	}
}

//функция _getHost
private EndPoint _getHost(string text)
{
	//вырезаем из строки только IP адрес формата IPv4
	string host = text.Remove(text.IndexOf(":"), text.Length - text.IndexOf(":"));

	//создаем объект адреса. Переменная host уже имеет вид [0-255].[0-255].[0-255].[0-255]
	IPAddress hostIPAddress = IPAddress.Parse(host);

	//создаем конечную точку. В нашем случае это адрес сервера, который слушает порт 9050
	IPEndPoint hostIPEndPoint = new IPEndPoint(hostIPAddress, 9050);
	EndPoint To = (EndPoint)(hostIPEndPoint);
	return To;
}
Сервер

Приложение сервер также будет состоять из двух функций, но не будет отправлять запрос с приветствием. Просто будет слушать и в зависимости от принятых данных отправлять сообщения.
Внимание! Порт, который слушает сервер — 9050. Отправляет он на 9051. Это в нашем случае.
Создаем новое консольное приложение для сервера и смотрим код:

//Для сервера
publiс void Listen()
{
	int recv; //храним размер полученных данных
	byte data = new byte[1024]; //данные, которые будут передаваться или приниматься

	Socket mysocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

	//В отличие от клиента "слушаем" порт 9050
	IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
	mysocket.Bind(ipep); //привязываем точку к нашему сокету
	IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
	EndPoint Remote = (EndPoint)(sender);

	//запускаем бесконечный цикл, который будет принимать и отправлять данные
	while (true)
	{
		data = new byte[1024];
		//принимаем данные от клиента. recv содержир размер, т.е. количество принятых символов
		recv = mysocket.ReceiveFrom(data, ref Remote);
		string message = Encoding.ASCII.GetString(data, 0, recv);
		switch(message)
		{
			case "Hello" : //на ответ от клиента Hello, шлем ответ ОК
				data = Encoding.ASCII.GetBytes("ОК:Сервер найден!");
				break;
		}
		//Remote содержит адрес, с которого пришло сообщение. Ему его назад и отправляем
		mysocket.SendTo(data, data.Length, SocketFlags.None, _getHost(Remote.ToString()));
	}
}

//функция _getHost для сервера отличается только портом. Вместо 9050, отправлять всегда будем на 9051
private EndPoint _getHost(string text)
{
	//вырезаем из строки только IP адрес формата IPv4
	string host = text.Remove(text.IndexOf(":"), text.Length - text.IndexOf(":"));

	//создаем объект адреса. Переменная host уже имеет вид [0-255].[0-255].[0-255].[0-255]
	IPAddress hostIPAddress = IPAddress.Parse(host);

	//создаем конечную точку. В нашем случае это адрес сервера, который слушает порт 9051
	IPEndPoint hostIPEndPoint = new IPEndPoint(hostIPAddress, 9051);
	EndPoint To = (EndPoint)(hostIPEndPoint);
	return To;
}

Заключение

В статье описан самый простой и базовый пример работы с сокетами. Здесь главное — понять суть дела.

Популярность: 96%

Теги: , ,

Если у вас возникли вопросы, вы можете оставить их в комментариях

Комментарии к статье

16 Ответов на “Работаем с сокетами в C# по UDP-протоколу”

Оставить комментарий

(обязательно)

(обязательно)