- Регистрация
- 26.01.2015
- Сообщения
- 90
- Реакции
- 344
- Баллы
- 53
Всем доброго дня!
В этой статье я бы хотел Вам рассказать о таком протоколе передачи данных как TCP/IP и как его можно использовать в своих проектах.
Чуть чуть теории
Переводя определение с википедии, можно сказать что этот протокол позволяет серверу и клиенту установить один общий буффер данных, в который любая из сторон может вписывать информацию, а другая получить уведомление об этом и прочитать ее + TCP гарантирует доставку всех пакетов без потерь в отличии от UDP.
Ближе к делу
В моем примере сервером будет выступать шаблон ZP, а клиентом станет мобильное приложение.
Хотя на самом деле клиента можно написать и на другом шаблоне и обмениваться данными между ними даже если они физически находятся в двух разных уголках планеты =)
Для создания шаблона- сервера нам понадобится библиотека Interop.NATUPNPLib (во вложении). Она необходима для того чтобы пробросить порт через ваш локальный IP адрес и роутер, который имеет внешний IP адрес, чтобы вы смогли подключаться к своему проекту через интернет, а не только находясь в одной локальной сети.
Добавляем ссылку на библиотеку в шаблон и начинаем кодить:
Во вкладке общего кода у вас должны быть следующие using
Объявляем нужные нам переменные:
Первый метод для получения своего локального адреса
Далее метод для получения статуса соединения
Самый важный метод - запуск сервера и старт ожидания соединения
Как можно увидеть в этом методе мы устанавливаем соединение нашего сокета (можно сказать что это канал передачи данных) с удаленным сокетом, который захочет к нам подключиться
Метод передачи сообщения
Грубо говоря мы просто взяли текст, перевели его в массив байтов и отправили по сокету
Отправка файла, а в нашем случае мы будем отправлять каптчу
Тут по сложнее. В коде можно увидеть две отправки пакета байтов, первым я передаю флаг в виде слова "isFile" + размер файла, который я собираюсь передать. Далее ожидаю ответа от клиента и уже отправляю чистый файл, переведенный в массив байтов. Зачем такой кастыль?) Да потому что стандартный метод передачи файла по сокету почему то убивает PM, поэтому я решил сделать вот так. Да и везде говорят что при таком подходе быстрее файл передается чем уже готовым методом =)
Ну и последний метод закрытия соединения
Суть написания клиента
В первую очередь на клиенте нужно произвести соединение с сервером:
Для того чтобы дождаться и получить данные от сервера делаем так
Отправка данных от клиента к серверу
Таким образом на выходе получаем следующее:
Как видно в демонстрации на телефоне у меня обычное мобильное соединение, а на ПК домашний WIFI, данные передаются достаточно быстро=)
Исходники клиента можете скачать или посмотреть тут (Xamarin):
https://bitbucket.org/serkser70/clientzp
Запакованый APK клиента (форум не принимает apk файлы, залил на яндекс):
https://yadi.sk/d/6PBUMW4K3N9rzD
Библиотека:
https://yadi.sk/d/bVgw5GPl3N9ryh
На этом все =)
Я понимаю что для некоторых эта статья покажется слишком мудреной и сложной, но тем не менее искренне верю, что кому то это откроет новый взгляд на построение своих проектов и поможет реализовать крутые идеи!
А для новичков это не лишнее доказательство безграничных возможностей ZennoPoster!
Всем огромное спасибо за внимание! Я очень рад снова участвовать в этом конкурсе!=)
В этой статье я бы хотел Вам рассказать о таком протоколе передачи данных как TCP/IP и как его можно использовать в своих проектах.
Чуть чуть теории
Переводя определение с википедии, можно сказать что этот протокол позволяет серверу и клиенту установить один общий буффер данных, в который любая из сторон может вписывать информацию, а другая получить уведомление об этом и прочитать ее + TCP гарантирует доставку всех пакетов без потерь в отличии от UDP.
Ближе к делу
В моем примере сервером будет выступать шаблон ZP, а клиентом станет мобильное приложение.
Хотя на самом деле клиента можно написать и на другом шаблоне и обмениваться данными между ними даже если они физически находятся в двух разных уголках планеты =)
Для создания шаблона- сервера нам понадобится библиотека Interop.NATUPNPLib (во вложении). Она необходима для того чтобы пробросить порт через ваш локальный IP адрес и роутер, который имеет внешний IP адрес, чтобы вы смогли подключаться к своему проекту через интернет, а не только находясь в одной локальной сети.
Добавляем ссылку на библиотеку в шаблон и начинаем кодить:
Во вкладке общего кода у вас должны быть следующие using
Код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;
Объявляем нужные нам переменные:
Код:
static NATUPNPLib.UPnPNAT upnpnat = new NATUPNPLib.UPnPNAT();
static IPAddress ipAd;
static TcpListener listener;
static Socket socket;
Первый метод для получения своего локального адреса
Код:
public static IEnumerable<IPAddress> GetLocalIPAddress()
{
return Dns.GetHostEntry(Dns.GetHostName()).AddressList.Where(f=> f.AddressFamily == AddressFamily.InterNetwork);
}
Далее метод для получения статуса соединения
Код:
public static bool IsConnected(this Socket sockets)
{
try
{
return !(sockets.Poll(1, SelectMode.SelectRead) && sockets.Available == 0);
}
catch (SocketException) { return false; }
}
Самый важный метод - запуск сервера и старт ожидания соединения
Код:
public static bool StartConnection()
{
string ipAddres = string.Empty;
if (GetLocalIPAddress().Any()) //получаем свой локальный ip адрес
ipAddres = GetLocalIPAddress().First().ToString();
else
return false;
ipAd = IPAddress.Parse(ipAddres);
listener = new TcpListener(ipAd, 20903);
listener.Start();// запуск сервера
// делаем проброс порта через роутер
NATUPNPLib.IStaticPortMappingCollection mappings = upnpnat.StaticPortMappingCollection;
if(mappings !=null)
mappings.Add(20903, "TCP", 20903, ipAddres, true, "Port for ZennoPoster"); //если требуется пробрасываем порт
new Thread(()=> socket = listener.AcceptSocket()).Start(); // ожидание подключения в фоновом потоке
return true;
}
Как можно увидеть в этом методе мы устанавливаем соединение нашего сокета (можно сказать что это канал передачи данных) с удаленным сокетом, который захочет к нам подключиться
Метод передачи сообщения
Код:
//метод отправки сообщения клиенту
public static bool SendMessage(string text)
{
if(socket ==null)
return false;
try{
byte[] bytes = Encoding.GetEncoding(1251).GetBytes(text);
socket.Send(bytes);
return true;
}
catch{return false;}
finally{
if(!socket.IsConnected() && socket != null)
{StopConnection();
StartConnection();
}
}
}
Отправка файла, а в нашем случае мы будем отправлять каптчу
Код:
//метод отправки файла клиенту
public static string SendCaptcha(string filePath)
{
if(socket ==null)
return "";
try{
byte[] bytes = Encoding.GetEncoding(1251).GetBytes("isFile "+File.ReadAllBytes(filePath).Length);
socket.Send(bytes);
socket.Receive(bytes);
socket.Send(File.ReadAllBytes(filePath));
bytes = new byte[1024];
int lenght= socket.Receive(bytes);
return Encoding.GetEncoding(1251).GetString(bytes);
}catch{return "";}
finally{
if(!socket.IsConnected() && socket != null)
{StopConnection();
StartConnection();
}
}
}
Ну и последний метод закрытия соединения
Код:
//метод остановки соединения
public static void StopConnection()
{
try{
if(socket!= null)
socket.Disconnect(true);
if(listener!= null)
listener.Stop();
NATUPNPLib.IStaticPortMappingCollection mappings = upnpnat.StaticPortMappingCollection;
mappings.Remove(20903, "TCP");
}catch{}
}
Суть написания клиента
В первую очередь на клиенте нужно произвести соединение с сервером:
Код:
IPEndPoint ipep =
new IPEndPoint(IPAddress.Parse("Внешний ip сервера"), 20903);
Socket server = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
await server.ConnectAsync(ipep);
Для того чтобы дождаться и получить данные от сервера делаем так
Код:
byte[] data = new byte[1024]; //готовим массив, куда будет сложен ответ
int lenght = socket.Receive(data); //наполняем этот массив, одновременно получая его длину
string text = Encoding.GetEncoding(1251).GetString(data, 0, lenght);// переводим массив в строку
Отправка данных от клиента к серверу
Код:
byte[] dataBytes = Encoding.GetEncoding(1251).GetBytes("текст который передаем");
socket.Send(dataBytes); //отправляем
Таким образом на выходе получаем следующее:
Исходники клиента можете скачать или посмотреть тут (Xamarin):
https://bitbucket.org/serkser70/clientzp
Запакованый APK клиента (форум не принимает apk файлы, залил на яндекс):
https://yadi.sk/d/6PBUMW4K3N9rzD
Библиотека:
https://yadi.sk/d/bVgw5GPl3N9ryh
На этом все =)
Я понимаю что для некоторых эта статья покажется слишком мудреной и сложной, но тем не менее искренне верю, что кому то это откроет новый взгляд на построение своих проектов и поможет реализовать крутые идеи!
А для новичков это не лишнее доказательство безграничных возможностей ZennoPoster!
Всем огромное спасибо за внимание! Я очень рад снова участвовать в этом конкурсе!=)
- Номер конкурса статей
- Седьмой конкурс статей
- Тема статьи
- Другое
Вложения
Последнее редактирование:




.