- •Тверской государственный технический университет
- •Организация удаленного взаимодействия с помощью сокетов.
- •1. Теоретическая часть.
- •1.1. Введение.
- •1.2. Создание приложения сервера с помощью потоковых сокетов.
- •1.3. Создание приложения клиента с помощью потоковых сокетов.
- •1.4. Взаимодействие между клиентом и сервером.
- •1.4.1. Реализация сервера.
- •1.4.2. Реализация клиента.
- •1.5. Клиент-серверное взаимодействие без установки соединения.
- •1.5.1. Пример организация взаимодействия.
- •1.5.1.1. Серверная часть.
- •1.5.1.2. Клиентская часть.
- •1.6. Пример многопоточного взаимодействия между приложениями
- •1.6.1. Реализация серверной части.
- •1.6.2. Реализация клиентской части.
- •1.6.3. Реализация класса клетки игрового поля.
- •2. Указания к выполнению лабораторной работы
- •2.1. Задание на лабораторную работу
- •2.2. Содержание отчета по лабораторной работе
- •Литература:
1.4.2. Реализация клиента.
Программный код клиента, использующий для взаимодействия с сервером потоковый сокет, может выглядеть следующим образом:
// Настройка клиента, считывающего и отображающего информацию,
// получаемую от сервера
using System;
using System.Drawing;
using System.Collection;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;
using System.Net.Sockets;
using System.IO;
// Соединение с сервером
public class Client : System.Windows.Forms.Form
{
TextBox inputTextBox, displayTextBox;
NetworkStream output;
BinaryWriter writer;
BinaryReader reader;
string message = "";
Thread readThread;
Container Components = null;
public Client() // Конструктор по умолчанию
{
InitializeComponent();
readThread = new ThreadStart(RunClient));
readThread.Start();
}
[STAThread]
static void Main() { Application.Run(new Client()); }
protected void Client_Closing(object sender, CancelEventArg e)
{ Environment.Exit(Environment.ExitCode); }
// отправляет введенный пользователем тест на сервер
protected void inputTextBox_KeyDown(object sender, KeyEventArg e)
{
if(e.keyCode == Keys.Enter)
{
Writer.Write("CLIENT>>> " + inputTextBox.Text);
displayTextBox.Text += "\r\nCLIENT>>> " + inputTextBox.Text;
inputTextBox.Clear();
}
}
// Соединение с сервером и отображение текста, сгенерированного сервером
public void RunClient()
{
TcpClient client;
displayTextBox.Text += "Попытка установить соединение\r\n";
// Создание сокета для отправки данных на сервер
// Шаг 1: Создание сокета и соединение с сервером
client = new TcpClient();
client.Connect("localhost", 5000);
// Шаг 2: Получение потока для работы с сокетом
Output = client.GetStream();
// Создание объектов для записи и считывания в потоке
writer = new BinaryWriter(output);
reader = new BinaryReader(output);
displayTextBox.Text += "\r\nПолучил потоки для ввода и вывода\r\n";
inputTextBox.readOnly = false;
do
{
// Шаг 3: Фаза обработки
message = reader.readString();
displayTextBox.Text += "\r\n" + message;
}
while(message != "SERVER>>> TERMINATE");
displayTextBox.Text += "\r\nОтключение соединения.\r\n";
// Шаг 4: Закрытие соединения
writer.Close();
reader.Close();
output.Close();
client.Close();
Application.Exit();
}
}
Подобно объекту сервера, объект клиента создает в своем конструкторе поток для обработки всех входящих сообщений. Его метод RunClient() соединяется с объектом сервера, получает от него данные и отправляет и отправляет на сервер свою информацию (при нажатии пользователем на клавишу <ENTER>. На шаге 1, для установления соединения, создается объект типа TcpClient, а затем вызывается его метод Connect(). В данном случае первым аргументом этого метода является имя сервера "localhost", означающее, что серверное приложение, размещено на той же самой машине, что и клиент. Имя localhost еще называют IP-адресом обратной связи и эквивалентно IP-адресу 127.0.0.1. Это значение направляет передачу данных на IP-адрес отправителя.
Вторым аргументом метода Connect() является номер порта сервера. Этот номер должен совпадать с номером порта, на котором сервер ожидает соединения от клиента.
Объект Client использует класс NetworkStream для передачи данных на сервер и для их получения с сервера. Клиент получает класс NetworkStream путем обращения к методу GetStream класса TcpClient (шаг 2). Цикл do/while повторяется до тех пор, пока не получит сообщения о прекращении соединения ("SERVER>>> TERMINATE"). Для получения с сервера текстового сообщения используется метод ReadString класса BinaryReader (шаг 3). После чего отображаются сообщения и закрываются объекты BinaryWriter, BinaryReader, NetworkStream и TcpClient (шаг 4).
Когда пользователь клиентского приложения вводит строку в текстовое поле и нажимает на клавишу <Enter> , то обработчик этого события inputTextBox_KeyDown считывает строку из текстового поля и отправляет ее серверу с помощью метода BinaryWriter.Write(). Следует отметить, что в данном случае объект сервера получает запрос на соединение, обрабатывает его, закрывает и ожидает следующего. В реальном приложении сервер получил бы запрос на соединение, установил его для обработки в виде отдельного потока и ожидал бы новых соединений. Отдельные потоки, обрабатывающие существующие соединения, могут продолжать свою работу, в то время как объект сервера ожидает новых запросов на соединение.