Шаг 187 - TCPListener

В C# появилась такая знатная возня как TCPListener и TCPClient. Остановимся на TCPListener так как второй особого интереса не представляет. В SDK написано, что он предоставляет вроде как TCP сервисы на более высоком абстрактом уровне, чем Socket. У этого класса есть три конструктора.

этот инициализирует "слушалку" на указанном порту
public TcpListener(int);
этот производит инициализацию со локальной endpoint
public TcpListener(IPEndPoint);
ну, а этот  на указанном адресе и порту
public TcpListener(IPAddress, int);

Итак, нам нужно для начала узнать IP адреса компьютера, можно конечно было сделать по нормальному, но там долго возится, поэтому мы пойдём другим путём. Есть такой класс DNS, служит для распознавания имён и наоборот для преобразования адресов в имена. Получим имя нашего компьютера, для этого вызовем статический метод этого класса GetHostName(), после нам осталось только получить IP адреса нашего компьютера вызвав Resolve(), этот метод возвращает массив IP адресов для распознанного имени. У меня это два адреса к примеру.

gif/187_1.gif (2277 b)

Далее создадим класс TCPWorker для функции, которая будет выполняться в отдельном потоке. Далее на нужно, чтобы если мы хотим по пасть по следующему адресу http://10.100.101.160 мы увидели некую страничку, я сделал чтобы клиенту отсылалась, страничка с информацией которую послал его броузер. Итак, создадим наш листенер:

myListener = new TcpListener(new IPEndPoint(IPAddress.Parse(ip), 80));

Здесь создаётся на 80 порту, хотя вы можете любой порт указать если хотите, только не забудьте тогда по этому порту обращаться. Далее нам нужен класс Encoding для преобразования строки из Unicode(string в формате unicode) в массив байт, причём символы должны быть в ASCII.

Encoding ASCII = Encoding.ASCII;

Вызываем теперь метод Start иначе, потом получим ошибку

myListener.Start();

и ждём пока к нам кто - нибудь не приконектится

mySocket = myListener.AcceptSocket();

Функция AcceptSocket возвращает сокет, когда кто-то приконекчивается к нам. Но есть одно "НО", всё хорошо пока к нам кто-то постоянно ломится, однако если никого нет, то эта функция будет в глубоком "дауне", даже если мы закроем окошко:

gif/187_2.gif (8851 b)

Даже если мы сделаем Abort потоку всё равно, поток будет висеть. Поэтому я вызываю Pending() для того, чтобы узнать если ждущие соединения запросы, если да то функция возвращает true иначе false. Далее всё просто получаем данные которые нам послал клиент, вызвав Receive метод нашего сокета.

int bytecount = mySocket.Receive(recv);

ну, а дальше посылаем данные клиенту

string SendString = "HTTP/1.0 200 OK\x0d\x0aServer: FirstSteps/0.1\x0d\x0a\x0d\x0a";
mySocket.Send(ASCII.GetBytes(SendString));
SendString = "Socket example" + ASCII.GetString(recv, 0, bytecount);
SendString += "";
mySocket.Send(ASCII.GetBytes(SendString));

Обратите внимание на ASCII.GetString(recv, 0, bytecount) здесь мы получаем данные которые мы получили(в виде строки) иначе нам туда запахнется весь массив. Получили мы следующие.

gif/187_3.gif (7654 b)

По нормальным делам нужно было бы наверно, для каждого конекта запускать отдельный поток, но я этого делать не стал(лень :)). Да и если будут проблемы, то остановите сервис IIS Admin Service или PWS, в зависимости от того что у вас стоит.


Загрузить проект | Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Leonid Molochniy - 25.11.2001