Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ПРВ_ответы2.doc
Скачиваний:
3
Добавлен:
20.12.2018
Размер:
566.27 Кб
Скачать

Принципы сокетов

Каждый процесс может создать слушающий сокет (серверный сокет) и привязать его к какому-нибудь порту операционной системы (в UNIX непривилегированные процессы не могут использовать порты меньше 1024). Слушающий процесс обычно находится в цикле ожидания, то есть просыпается при появлении нового соединения. При этом сохраняется возможность проверить наличие соединений на данный момент, установить тайм-аут для операции и т.д.

Каждый сокет имеет свой адрес. ОС семейства UNIX могут поддерживать много типов адресов, но обязательными являются INET-адрес и UNIX-адрес. Если привязать сокет к UNIX-адресу, то будет создан специальный файл (файл сокета) по заданному пути, через который смогут сообщаться любые локальные процессы путём чтения/записи из него (см. Доменный сокет Unix). Сокеты типа INET доступны из сети и требуют выделения номера порта.

Обычно клиент явно подсоединяется к слушателю, после чего любое чтение или запись через его файловый дескриптор будут передавать данные между ним и сервером.

using System;

using System.Collections.Generic;

using System.Net.Sockets;

using System.Net;

using System.Text;

using System.Threading;

using System.Diagnostics;

using System.Windows.Forms;

using System.IO;

using System.Runtime.Serialization.Formatters.Binary;

using System.Runtime.Serialization;

namespace MandelbrotSet_DC_Server

{

class Program

{

static List<EndPoint> list = null;

static Thread thread_rec, thread_keypressed;

static Socket server;

static EndPoint remote_ep;

static frmDraw frm;

static StreamWriter sw;

static void Main(string[] args)

{

#region get_server_ip

IPAddress server_ip;

string host_name = Dns.GetHostName();

IPHostEntry ipEntry = Dns.GetHostByName(host_name);

IPAddress[] addr = ipEntry.AddressList;

server_ip = addr[0];

#endregion

#region start_server

//server = null;

//remoteEP = null;

try

{

IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(server_ip.ToString()), 9060);

list = new List<EndPoint>();

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

server.Bind(localEP);

remote_ep = new IPEndPoint(IPAddress.Any, 0);

Console.WriteLine(DateTime.Now.ToString() + ":\nServer started.\nHost name:\t{0}\nServer IP:\t{1}", host_name, addr[0].ToString());

Console.WriteLine("'S':\tStart calculating.\n'Q':\tQuit.\n");

Console.Beep();

}

catch (Exception ex)

{

Console.WriteLine("{0}:\tError: {1}", DateTime.Now.ToString(), ex.Message);

}

#endregion

thread_rec = new Thread(new ThreadStart(rec));

thread_keypressed = new Thread(new ThreadStart(key_pressed));

thread_rec.Start();

thread_keypressed.Start();

}

static public byte[] pack(Object obj)

{

//object -> byte[]

MemoryStream fs = new MemoryStream();

BinaryFormatter formatter = new BinaryFormatter();

try

{

formatter.Serialize(fs, obj);

return fs.ToArray();

}

catch

{

return null;

}

finally

{

fs.Close();

}

}

static public object unpack(Byte[] buf)

{

//byte[] -> object

BinaryFormatter formatter = new BinaryFormatter();

MemoryStream stream = new MemoryStream(buf);

try

{

return formatter.Deserialize(stream);

}

catch

{

return null;

}

}

static void key_pressed()

{

ConsoleKeyInfo key;

while (true)

{

key = Console.ReadKey();

//

}

}

static void rec()

{

byte[] data;

int recv;

String message;

while (true)

{

data = new byte[1024];

recv = 0;

try

{

recv = server.ReceiveFrom(data, ref remote_ep);

}

catch (Exception ex)

{

Console.WriteLine("{0}:\tError: {1}", DateTime.Now.ToString(), ex.Message);

}

message = Encoding.ASCII.GetString(data, 0, recv);

//Console.WriteLine("{0}:\t{1}", DateTime.Now.ToString(), message);

switch (message)

{

case "@join":

if (!is_connected(remote_ep))

{

list.Add(remote_ep);

server.SendTo(Encoding.ASCII.GetBytes("@connected"), remote_ep);

Console.ForegroundColor = ConsoleColor.Green;

Console.WriteLine("{0}:\t{1} has connected. Connected count: {2}", DateTime.Now.ToString(), remote_ep.ToString(), list.Count);

}

else

{

server.SendTo(Encoding.ASCII.GetBytes("@notconnected"), remote_ep);

Console.ForegroundColor = ConsoleColor.Red;

Console.WriteLine("{0}:\t{1} is trying to connect again.", DateTime.Now.ToString(), remote_ep.ToString());

}

break;

case "@quit":

list.Remove(remote_ep);

Console.ForegroundColor = ConsoleColor.DarkYellow;

Console.WriteLine("{0}:\t{1} has disconnected.", DateTime.Now.ToString(), remote_ep.ToString());

break;

default:

try

{

int[] package_recieve = (int[])unpack(data);

if (package_recieve[0] < 0) Console.WriteLine("{0}:\t Stop calculating...", DateTime.Now.ToString());

else

{

sw.WriteLine("x: " + package_recieve[0] + ", y: " + package_recieve[1] + ", color_number: " + package_recieve[2]);

frm.draw(package_recieve[0], package_recieve[1], package_recieve[2]);

}

}

catch { }

break;

}

}

}

static bool is_connected(EndPoint ep)

{

string endp = ep.ToString(), tmp;

int j = 0;

while (endp[j++] != ':') ;

endp = endp.Substring(0, j - 1);

for (int i = 0; i < list.Count; i++)

{

tmp = list[i].ToString();

j = 0;

while (tmp[j++] != ':') ;

if (tmp.Substring(0, j - 1) == endp) return true;

}

return false;

}

}

}

TcpClient

Обеспечивает клиентские подключения для сетевых служб TCP.

System.Net.Sockets

Класс TcpClient обеспечивает простые методы для подключения, а также отправки и получения потоков данных в сети в синхронном блокирующем режиме.

Для того, чтобы объект TcpClient мог выполнить подключение и обмен данными, объект TcpListener или Socket, созданный с использованием протокола ProtocolType TPC, должен выполнять ожидание входящих запросов на подключение. Подключиться к данному слушателю можно одним из следующих двух способов:

  • Создать объект TcpClient и вызвать один из трех имеющихся методов Connect.

  • Создать объект TcpClient, используя имя узла и номер порта удаленного узла. Этот конструктор будет автоматически предпринимать попытки установления подключения.

Примечания для наследующих объектов

Чтобы отправлять и получать данные, используйте метод GetStream для получения объекта NetworkStream. Вызовите методы Write и Read объекта NetworkStream для отправки и получения данных с удаленного узла. Воспользуйтесь методом Close, чтобы освободить все связанные с объектом TcpClient ресурсы.

static void Connect(String server, String message)

{

try

{

// Create a TcpClient.

// Note, for this client to work you need to have a TcpServer

// connected to the same address as specified by the server, port

// combination.

Int32 port = 13000;

TcpClient client = new TcpClient(server, port);

// Translate the passed message into ASCII and store it as a Byte array.

Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

// Get a client stream for reading and writing.

// Stream stream = client.GetStream();

NetworkStream stream = client.GetStream();

// Send the message to the connected TcpServer.

stream.Write(data, 0, data.Length);

Console.WriteLine("Sent: {0}", message);

// Receive the TcpServer.response.

// Buffer to store the response bytes.

data = new Byte[256];

// String to store the response ASCII representation.

String responseData = String.Empty;

// Read the first batch of the TcpServer response bytes.

Int32 bytes = stream.Read(data, 0, data.Length);

responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);

Console.WriteLine("Received: {0}", responseData);

// Close everything.

stream.Close();

client.Close();

}

catch (ArgumentNullException e)

{

Console.WriteLine("ArgumentNullException: {0}", e);

}

catch (SocketException e)

{

Console.WriteLine("SocketException: {0}", e);

}

Console.WriteLine("\n Press Enter to continue...");

Console.Read();

}

TcpListener

Ожидает подключения от TCP-клиентов сети.

Класс TcpListener предоставляет простые методы, предназначенные для ожидания и приема в блокирующем синхронном режиме входящих запросов на подключения. Можно использовать объект TcpClient или Socket, чтобы подключиться к объекту TcpListener. Создайте объект TcpListener, используя объект IPEndPoint, локальный IP-адрес и номер локального порта или же только номер порта. Задайте значение Any для локального IP-адреса и значение 0 для номера локального порта, если необходимо, чтобы эти значения были присвоены основным поставщиком услуг. Если выбран этот вариант, можно воспользоваться свойством LocalEndpoint, чтобы определить присвоенные параметры после подключения сокета.

Используйте метод Start, чтобы начать ожидание входящих запросов подключения. Start будет ставить входящие подключения в очередь до вызова метода Stop или пока в очередь не будет поставлено MaxConnections подключений. Используйте для принятия подключения из входной очереди подключений метод AcceptSocket или AcceptTcpClient. Эти два метода будут выполнять блокирование. Если необходимо избежать блокирования, воспользуйтесь сначала методом Pending для того, чтобы определить, имеются ли в очереди доступные запросы на подключение.

Вызовите метод Stop, чтобы закрыть объект TcpListener.

using System;

using System.IO;

using System.Net;

using System.Net.Sockets;

using System.Text;

class MyTcpListener

{

public static void Main()

{

TcpListener server=null;

try

{

// Set the TcpListener on port 13000.

Int32 port = 13000;

IPAddress localAddr = IPAddress.Parse("127.0.0.1");

// TcpListener server = new TcpListener(port);

server = new TcpListener(localAddr, port);

// Start listening for client requests.

server.Start();

// Buffer for reading data

Byte[] bytes = new Byte[256];

String data = null;

// Enter the listening loop.

while(true)

{

Console.Write("Waiting for a connection... ");

// Perform a blocking call to accept requests.

// You could also user server.AcceptSocket() here.

TcpClient client = server.AcceptTcpClient();

Console.WriteLine("Connected!");

data = null;

// Get a stream object for reading and writing

NetworkStream stream = client.GetStream();

int i;

// Loop to receive all the data sent by the client.

while((i = stream.Read(bytes, 0, bytes.Length))!=0)

{

// Translate data bytes to a ASCII string.

data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);

Console.WriteLine("Received: {0}", data);

// Process the data sent by the client.

data = data.ToUpper();

byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);

// Send back a response.

stream.Write(msg, 0, msg.Length);

Console.WriteLine("Sent: {0}", data);

}

// Shutdown and end connection

client.Close();

}

}

catch(SocketException e)

{

Console.WriteLine("SocketException: {0}", e);

}

finally

{

// Stop listening for new clients.

server.Stop();

}

Console.WriteLine("\nHit enter to continue...");

Console.Read();

}

}

23

Message Passing Interface (MPI, интерфейс передачи сообщений) — программный интерфейс (API) для передачи информации, который позволяет обмениваться сообщениями между процессами, выполняющими одну задачу. Разработан Уильямом Гроуппом (англ.), Эвином Ласком (англ.) и другими.

MPI является наиболее распространённым стандартом интерфейса обмена данными в параллельном программировании, существуют его реализации для большого числа компьютерных платформ. Используется при разработке программ для кластеров и суперкомпьютеров. Основным средством коммуникации между процессами в MPI является передача сообщений друг другу. Стандартизацией MPI занимается MPI Forum. В стандарте MPI описан интерфейс передачи сообщений, который должен поддерживаться как на платформе, так и в приложениях пользователя. В настоящее время существует большое количество бесплатных и коммерческих реализаций MPI. Существуют реализации для языков Фортран 77/90, Си и Си++.

В первую очередь MPI ориентирован на системы с распределенной памятью, то есть когда затраты на передачу данных велики. В то время как OpenMP ориентирован на системы с общей памятью (многоядерные с общим кэшем). Обе технологии могут использоваться совместно, дабы оптимально использовать в кластере многоядерные системы.