Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Помогите понять

40K
21 апреля 2009 года
AL4X
12 / / 21.04.2009
Вот код многопользовательского чата.

Непугайтесь кода, я хочу только понять как работают некоторые методы
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Chinwag
{
class Chinwag {
//------------------------------------------------------------------------------------------------------------------
//--------------------------------------MAIN
static void Main(string[] args) {

Console.WriteLine("Create 'client' or 'server' ?");
string type = Console.ReadLine();

switch (type) {
case "client":
ChinwagClient client = new ChinwagClient();
Console.WriteLine("Enter ip address as x.x.x.x :");
string ipa = Console.ReadLine();
Console.WriteLine("Enter your name:");
string name = Console.ReadLine();
Console.WriteLine("OK, CLIENT RUN:");
Console.WriteLine("OK, Now you can write text:");
client.Run(ipa,name);
break;
case "server":
ChinwagServer server = new ChinwagServer();
server.Listen();
Console.WriteLine("OK, SERVER RUN:");
Console.WriteLine("OK, Now you can wait connection and then write text:\n");
server.Run();
break;
}
}
};
//------------------------------------------------------------------------------------------------------------------
//--------------------------------------CLIENT
class ChinwagClient {
bool Running;
Socket ServerConn;
byte[] SocketBuffer = new byte[1024];
string OurName;

// Это очень похоже на метод Listen() сервера, кроме того, что вместо BeginConnect() мы используем BeginAccept()
void DoConnect(string ipaddress) {
IPEndPoint remoteep = new IPEndPoint(IPAddress.Parse(ipaddress), 32768);
ServerConn = new Socket(AddressFamily.InterNetwork, SocketType. Stream, ProtocolType.Tcp);
ServerConn.BeginConnect(remoteep, new AsyncCallback(OnClientConnect), ServerConn);
}
// Следующий метод запускается, когда новый клиент успешно подключается к серверу

public void OnClientConnect(IAsyncResult ar)
{
ServerConn = (Socket)ar.AsyncState;

// А это новый – вам необходимо вызвать BeginReceive(), если хотите получить текст
if (ServerConn.Connected)
{
ServerConn.BeginReceive(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, OnSocketReceive, ServerConn);
}
}

// Что-то пришло!
void OnSocketReceive(IAsyncResult ar)
{
// Вызываем EndReceive() и перехватываем возвращаемое значение, чтобы увидеть, сколько байтов было послано
int bytes = ServerConn.EndReceive(ar);
//if (Running == false) return;
// Теперь готовимся к приему следующего содержимого
ServerConn.BeginReceive(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, OnSocketReceive, ServerConn);

// Данные сокета копируются в SocketBuffer (массив байтов, созданных нами ранее) – этот код преобразует байты в строку,пригодную для вывода
string text = Encoding.ASCII.GetString(SocketBuffer, 0, bytes);
Console.WriteLine(text);
}
// Пересылка текста по проводам противоположна его приему: нам необходимо преобразовать введенную строку в байты
public void SendText(string text)
{
// Это шикарный способ сборки строки из переменных
text = string.Format("<{0}> {1}", OurName, text);
ServerConn.Send(Encoding.ASCII.GetBytes(text));
}
public void Run(string myIP,string myNAME)
{
OurName = myNAME;
DoConnect(myIP); // Соединяемся с локальным сервером
string input;
Console.Write("<------------------------->\n");
while (true)
{
input = Console.ReadLine();
SendText(input);
if (input == "close") CloseCl();
}
}
public void CloseCl()
{
ServerConn.Close();
}
};
//-------------------------------------------------------------------------------------------------------------------
//--------------------------------------SERVER
class ChinwagServer
{
Socket OurServerConn; // это сокет, который мы будем слушать
List<Socket> RemoteConns = new List<Socket>(); // Это сокеты, соответствующие нашим клиентам
byte[] SocketBuffer = new byte[1024]; // Это пригодится позднее, а пока пропустите!
public void Run()
{
while (true)
{
// Запускается навсегда и ничего не делает
Thread.Sleep(Timeout.Infinite);
}
}
public void Listen()
{
// Слушаем порт 32768 для всех IP-адресов
IPEndPoint local_ep = new IPEndPoint(IPAddress.Any, 32768);

// Создаем сокет и связываем его с портом
OurServerConn = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

OurServerConn.Bind(local_ep);

// Теперь начинаем слушать, с очередью ожидания до 10 соединений
OurServerConn.Listen(10);

// Готовы к принятию новых соединений
OurServerConn.BeginAccept(new AsyncCallback(OnIncomingConnection), OurServerConn);
}
// Это вызывается, как только возникнет соединение
void OnIncomingConnection(IAsyncResult ar)
{
Console.WriteLine("OK, A new client connect to your server !");
Socket client = ((Socket)ar.AsyncState).EndAccept(ar);
RemoteConns.Add(client);
// Это немного новое – нам необходимо быть готовым к приему данных от клиентов
client.BeginReceive(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, OnSocketReceive, client);
OurServerConn.BeginAccept(new AsyncCallback(OnIncomingConnection), OurServerConn);
}
// Клиент отослал текст!
void OnSocketReceive(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState;
// Это то же самое, что и в коде клиента
int bytes = client.EndReceive(ar);
client.BeginReceive(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, OnSocketReceive, client);

string text = Encoding.ASCII.GetString(SocketBuffer, 0, bytes);
Console.WriteLine(text);
// за исключением этой части: нам необходимо отправить текст всем другим клиентам
SendToAll(client, text);
}
void SendToAll(Socket cl, string t)
{
foreach (Socket nextS in RemoteConns)
{
if (nextS.Equals(cl) != true)
nextS.Send(Encoding.ASCII.GetBytes(t));
}
}

};

};

Вопросы--------------------------
1) Как правильно завершить работу (сервер\клиент) как отключится.

Меня терзают сомнения о работе таких методов ..., из-за того что в их описание говорится что-то о "Асинхронный вызов синхронных методов".
Если можно объясните своими словами.
2) Как работают методы:
------------------
ServerConn.BeginReceive(SocketBuffer, 0, SocketBuffer.Length, SocketFlags.None, OnSocketReceive, ServerConn);

параметры мне понятны, я хочу понять сам механизм работы.
Как я понял он запускает новый поток в котором ждет получения определенного количества байт
3-параметр SocketBuffer.Length - Число принимаемых байтов.

После чего вызывает метод OnSocketReceive который закрывает этот поток и получает принятые данные.
int bytes = ServerConn.EndReceive(ar);

------------------

// Теперь начинаем слушать, с очередью ожидания до 10 соединений
OurServerConn.Listen(10);
Тоже в отдельном потоке?

OurServerConn.BeginAccept(new AsyncCallback(OnIncomingConnection), OurServerConn);

Слушает, есть ли новое подключение в очереди.
Если в очереди кто-то есть, то он его принимает.
Тоже в отдельном потоке?

------------------
и метод ран
public void Run()
{
while (true)
{
// Запускается навсегда и ничего не делает
Thread.Sleep(Timeout.Infinite);
}
}
Создает новый поток и ставит в спячку для него время, зачем?

У меня все, прошу помочь!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог