// Main.cs created with MonoDevelop
// User: pronin-ae at 14:24 29.08.2009
//
// Пример сервера-концентратора.
//По запросу клиенту передается структура данных клиенту
//
using System;
using System.IO;
using System.Threading;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using Asutp.Data;
namespace Asutp.AsyncServer
{
//---------------------------------------------------------------
// класс обслуживания клиентов
class ClientHandler
{
private Socket sock;
private byte[] readBuffer; // буфер приемный
int byteRead;
private byte[] writeBuffer; // буфер на передачу
int byteWrite;
private NetworkStream networkStream;
private AsyncCallback callbackRead;
private AsyncCallback callbackWrite;
private dataFunc DataFunc;
// конструктор
public ClientHandler(Socket socketForClient, dataFunc DataF)
{
int Len=1024;
sock=socketForClient;
DataFunc=DataF;
readBuffer=new byte[Len];
writeBuffer=new byte[Len];
networkStream = new NetworkStream(socketForClient);
callbackRead=new AsyncCallback(this.OnReadComplete); // это асинхронный reader
callbackWrite=new AsyncCallback(this.OnWriteComplete); // это асинхронный writer
}
// запуск асинхронного чтения
public void StartRead()
{
networkStream.BeginRead(readBuffer,0,readBuffer.Length,callbackRead,null);
}
// что-то в сетях приплыло
private void OnReadComplete(IAsyncResult ar)
{
byteRead = networkStream.EndRead(ar); // прочитаем что пришло
if (byteRead>0)
{
// что-то есть
string s=System.Text.Encoding.ASCII.GetString(readBuffer,0,byteRead);
Console.WriteLine("Получено от клиента {0} байт",byteRead);
Console.WriteLine("{0}",s);
// запуск асинхронного writer, ответим
byteWrite=0;
Answer(); // подготовка ответа (заполнение writebuffer и вычисление byteWrite)
networkStream.BeginWrite(writeBuffer,0,byteWrite,callbackWrite,null);
}
else
{
// окончание сеанса работы с сокетом
Console.WriteLine("Read connection dropped");
networkStream.Close();
sock.Close();
networkStream=null;
sock=null;
}
}
// закончена пересылка данных клиенту
private void OnWriteComplete(IAsyncResult ar)
{
networkStream.EndWrite(ar);
Console.WriteLine("Write complete");
networkStream.BeginRead(readBuffer,0,readBuffer.Length,callbackRead,null);
}
// формирование ответа на запрос:
// что хотят: анализируем readBuffer
// отвечаем: заполнение writeBuffer и вычисление byteWrite
void Answer()
{
// echo();// пример ответа типа "эхо"
// Console.WriteLine("Answer()");
sendData();//пример ответа передачи структуры данных
}
//пример ответа передачи структуры данных клиенту
// сериализируем структуру и заполняем результатом буфер асинхронной передачи
void sendData()
{
// Console.WriteLine("sendData()");
DataFunc.BinWrite(ref this.writeBuffer,ref this.byteWrite);
}
// пример ответа типа "эхо"
void echo(){
for(int i=0;i<byteRead;i++) {
writeBuffer
=readBuffer;
}
byteWrite=byteRead;
}
}
//----------------------------------------------------------------
//----------------------------------------------------------------
// пример сервера
class AsyncServer
{
public dataFunc DataFunc;
bool stopServer=false;
int PORT=65000;
// функция сбора данных от контроллеров и их обслуживание
void DoCollect() {
Console.WriteLine("Data Collector Thread start");
while(!stopServer)
{
DataFunc.WriteData(); // пишем данные на сервер
DataFunc.PrintData(); // данные сервера для отладки
Thread.Sleep(1000); // пока 1 с, чтобы не мелькало
}
Console.WriteLine("Data Collector Thread stop");
}
// main
public static void Main(string[] args)
{
AsyncServer app = new AsyncServer();
app.Run();
// Console.WriteLine("Bye Server");
}
void Run()
{
ConfigParse();
// создадим экземпляр данных сервера, проинициализируем и покажем их
DataFunc = new dataFunc();// создадим экземпляр данных сервера
// создадим поток, который собирает данные контроллеров на сервер
Thread thread = new Thread(DoCollect);
thread.Name = "DataCollector";
thread.Start();
Console.WriteLine("Start Server. Port: {0}",PORT);
TcpListener tcpListener = new TcpListener(PORT); // создаем слушателя
tcpListener.Start(); // нехай нюхает
for(;
{
Socket sock = tcpListener.AcceptSocket();
if(sock.Connected)
{
// клиент подключен, создаем экземпляр читателя и начинаем общаться с клиентом
Console.WriteLine("Client connected");
ClientHandler handler = new ClientHandler(sock, DataFunc);
handler.StartRead(); // что ему от меня надо ?
}
}
}
// Парсим файл Server.cnf
void ConfigParse()
{
string str;
FileStream fin;
try {
fin= new FileStream("Server.cnf",FileMode.Open);
}
catch(FileNotFoundException) {
Console.WriteLine("File Server.cnf not found");
return;
}
StreamReader str_fin = new StreamReader(fin);
while((str=str_fin.ReadLine()) != null)
{
// Console.WriteLine(str);
str = str.Trim(); // удаляем пробелы в начале и конце строки
if((str.Length>0) && (str[0]!='#')) // удаляем строки комментариев
{
char [] sep = {' ','=',' ',';'}; // разбиваем строку на части
string[] pars;
pars = str.Split(sep);
// удаляем пустые строки через коллекцию
ArrayList al=new ArrayList();
for(int i=0; i<pars.Length;i++)
al.Add(pars);
M1:
foreach(string s in al) {
if(s.Length==0) {
al.Remove(s);
goto M1; // C# позволяет делать такую чушь без последствий
}
}
// Console.WriteLine("{0} {1}",al[0],al[1]);
switch ((string)al[0]) {
case "PORT":
try {
PORT=Int32.Parse((string)al[1]);
}
catch (FormatException) {
Console.WriteLine("Error PORT");
}
catch (OverflowException) {
Console.WriteLine("Error PORT");
}
break;
default:
break;
} //switch
}//if
}
str_fin.Close();
}
}
//-----------------------------------------------------------------
}