Пишу первую прогу клиент-сервер с помощью Remoting

 
0
 
.NET
ava
CityAC | 18.09.2007, 23:19
Суть:
Серверная прога на сервере подключается к базе данных(тут вопросов пока нет)
Клиенты - админмашина(через интрефейс клиентской проги осуществляет наполнение базы данных -
(имеется в виду в ручную)через серверную прогу
- диспетчера(реальные люди) в режиме реального времени через интрефейс клиентской проги
постоянно обращаются к базе через серверную программу (считывают данные, и постоянно обновляют
таблицу журнала принятых звонков).

Посоветовали при интенсивном обмене данных использовать Remoting. Скачал простенький пример - вроде кое-что понятно - ковыряюсь.
Текущий вопрос: В примере клиент серверу отправлял тесктовые сообщения. Как можно организовать обмен данными sql таблицы?
Comments (25)
ava
Experimenter | 19.09.2007, 06:13 #
Цитата


Как можно организовать обмен данными sql таблицы?


Также как в примере, только в прокси-классе объявляешь методы, выполняющие запросы к БД, в клиентском приложении вызываешь эти самые методы...
ava
CityAC | 19.09.2007, 21:39 #
Как узнать IP клиента в REmoting?
ava
Experimenter | 20.09.2007, 09:23 #
На все 100 не уверен, но посмотри:
System.Net.NetworkInformation и System.Net.HttpListener.HttpListenerRequest
и еще, слышал, что клиент не обязан свой айпишник сообщать серверу, поэтому, мне думается, лучше использовать авторизацию
ava
CityAC | 20.09.2007, 09:42 #
Наверно откажусь от Remoting в пользу XML сериализации.
Меня убедили не использовать каркас.
Только вот что не могу понять.
Объект DataSet можно сериализовать, а на DataRow ругается.(вроде как (мой перевод)в этом типе не присутствует коструктор без параметров) - что это значит?
Но если даже передаватьобъект DataSet, то как это делается?
Везде примеры сериализации в xml файл. А как его пустить по сетевому потоку? Типа как в NetworkStream при бинарной
сериализации?

Может я не ту сторону смотрю. Короче говоря нужно с сервера отправить клиенту строку из базы SQL
Строка получается в формате DataRow я ее вытягиваю из из объекта DataSet

DataSet ds ......
......
int lastRow = ds.Tables["tx_person1"].Rows.Count;
DataRow dr = ds.Tables["tx_person1"].Rows[lastRow - 1];


Какая ф-ция возвращает объект Stream, который используется в XML сериализации?
Как например это делается в следующем коде для NetworkStream

tcpc = new TcpClient(host_textBox.Text, int.Parse(port_textBox.Text));
//get a Network stream from the server
NetworkStream nts = tcpc.GetStream();
ava
Experimenter | 20.09.2007, 10:44 #
Цитата


Какая ф-ция возвращает объект Stream, который используется в XML сериализации?


WebRequest.GetRequestStream();
XmlTextWriter запишет твои данные хоть в какой стрим, файловый или сетевой... Данные можно сериализовать в XmlTextWriter , или напрямую в сетевой стрим.
ava
CityAC | 20.09.2007, 11:03 #
Цитата (Experimenter @ 20.9.2007, 10:44 findReferencedText)
WebRequest.GetRequestStream();


Stream stream = WebRequest.GetRequestStream();

Ошибка: An object reference is required for the nonstatic field, method, or property 'System.Net.WebRequest.GetRequestStream()'
Вообщето я в локальной сети данные передаю.
А эта ф-ция для записи данных в Интернет ресурс
Какой класс вызывает эту ф-цию для локалки ?

ava
CityAC | 20.09.2007, 11:44 #
Цитата (Experimenter @ 20.9.2007, 10:44 findReferencedText)
XmlTextWriter запишет твои данные хоть в какой стрим, файловый или сетевой

А как называется сетевой стрим?
ava
Experimenter | 20.09.2007, 11:54 #
CityAC, без бутылки не разберешься, код в студию...
Цитата


Вообщето я в локальной сети данные передаю.


Сетевой обмен даже на единственной отключенной от сетки машине между двумя приложениями можно организовать через System.Net (на localhost, к примеру)
Цитата


Ошибка: An object reference is required for the nonstatic field, method, or property 'System.Net.WebRequest.GetRequestStream()'


Извини, что не разжевал, WebRequest напрямую не используют:

HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(url);

вот так надо.
ava
CityAC | 20.09.2007, 12:13 #

DataSet ds = new DataSet();
// SqlDataAdapter da = new SqlDataAdapter(query, MyConnection);
SqlDataAdapter da = new SqlDataAdapter(query2, MyConnection);
da.Fill(ds, "tx_person1");

int lastRow = ds.Tables["tx_person1"].Rows.Count;
DataRow dr = ds.Tables["tx_person1"].Rows[lastRow - 1]; //нужно дальше передать эту строку


Как это сделать ума не приложу
Следующая строка не катит. Ну не хочет он создавать XmlSerializer для объекта DataRow

XmlSerializer ser = new XmlSerializer(typeof(DataRow));



XmlSerializer ser = new XmlSerializer(typeof(DataSet));


Uri ourUri = new Uri("http://localhost/");
HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(ourUri);
Stream str = webreq.GetRequestStream();// ошибка во время выполнения Cannot send a content-body with this verb-type.


ava
Experimenter | 20.09.2007, 13:10 #
Цитата


Ну не хочет он создавать XmlSerializer для объекта DataRow


Как это ни печально, DataRow не подлежит сериализации, так как не имеет публичного конструктора. С сериализацией только на первый взгляд все просто, на самом деле там много подводных камней. Но можно сериализовать DataSet или DataTable
ava
CityAC | 20.09.2007, 13:27 #
Ну насчет DAtaRow - да, я залез в дебри- но нашел выход.
Создаю DataSet,помещая в него не всю таблицу а только нужную строку и затем передаю ее в составе DataSet.
а что насчет этой ошибки?
Цитата (CityAC @ 20.9.2007, 12:13 findReferencedText)


код C#

XmlSerializer ser = new XmlSerializer(typeof(DataSet));           

 Uri ourUri = new Uri("http://localhost/);          

  HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(ourUri);Stream str = webreq.GetRequestStream();// ошибка во время выполнения ошибка во время выполнения Cannot send a content-body with this verb-type.

ava
Experimenter | 20.09.2007, 13:32 #
Цитата


ошибка во время выполнения Cannot send a content-body with this verb-type.



webreq.Method = "POST";
webreq.ContentType = "text/xml";

Так попробуй, и если не поможет, поиграйся со свойствами webreq, их у него много, полезных и бесполезных.
ava
CityAC | 20.09.2007, 13:49 #
спасибо за ответы Пока ничего не получилось - буду пробовать дальше.
Последний совет помог!!!
ava
Experimenter | 20.09.2007, 13:56 #
Цитата


спасибо за ответы Пока ничего не получилось - буду пробовать дальше.


ты скромничаешь, выкладывай, какие ошибки, помогу тебе как многодетный отец многодетному отцу. Чем смогу, конечно...
ava
CityAC | 20.09.2007, 14:18 #
Цитата (Experimenter @ 20.9.2007, 13:56 findReferencedText)
помогу тебе как многодетный отец многодетному отцу.

У меня бабушка родом из Давлеканово.
Был там в 5 лет у прабабки. Так что может мы еще и родственники - мир тесен говорят.
ava
CityAC | 20.09.2007, 15:11 #
Ну что едем дальше.

Поток создается, в него загружается XML таблица (таблица с одной строкой), (если можно сериализовать таблицу, то зачем DataSet! - понял по твоей подсказке)

А как на стороне клиента организовать запрос?

added later:
Цитата (Experimenter @ 20.9.2007, 14:13 findReferencedText)
почитай на досуге

Покой нам только снится Так что буду читать прям щас.
ava
Experimenter | 20.09.2007, 17:54 #
Ну если времени нет, то можно вообще без сериализации обойтись, главное, чтоб сервер клиентские запросы распознавал правильно

Клиент, которым я часто пользуюсь для тестирования сетевых приложений:

Stream s;
HttpWebRequest webreq;
HttpWebResponse webresp;
string response = "";
string request = "OPERATION WITH DATA";

try
{
webreq = (HttpWebRequest)WebRequest.Create("http://127.0.0.1:9999");
webreq.AuthenticationLevel = AuthenticationLevel.None;
// если есть прокси:
// webreq.Proxy = new WebProxy("proxyaddress", 1819);
// webreq.Proxy.Credentials = new NetworkCredential("Login", "Password");
webreq.Method = "POST";
webreq.ContentType = "text/plain"; // в твоем случае "text/xml"
webreq.KeepAlive = false;
webreq.Timeout = 100000; // 100000 мс - это дефолт, поэтому можно пропустить

StreamWriter sw = new StreamWriter(webreq.GetRequestStream(), Encoding.GetEncoding(1251));
sw.Write(strBuffer);
// или в твоем случае XmlTextWriter, тогда serializer.Serialize(xmlWriter, dataTable);
sw.Flush();
sw.Close();

Console.WriteLine("Request was sended");
webresp = (HttpWebResponse)webreq.GetResponse();
Console.WriteLine(webresp.StatusCode);
Console.WriteLine(webresp.Headers);
Console.WriteLine(webresp.CharacterSet.ToString());

s = webresp.GetResponseStream();
sr = new StreamReader(s, Encoding.GetEncoding(1251));
response = sr.ReadToEnd();
Console.WriteLine("RESPONSE:\r\n" + response);
sr.Close();
s.Close();

FileStream fs = new FileStream(AppDomain.CurrentDomain.BaseDirectory + "\\" + "response.txt", FileMode.OpenOrCreate);
sw = new StreamWriter(fs, Encoding.GetEncoding(1251));
sw.Write(webresp.Headers.ToString());
sw.Write(response.Replace("\n", "\r\n"));
sw.Flush();
sw.Close();
}
catch (Exception webex)
{
response = "ERROR!!! Description: " + webex.Message + "\r\n" + webex.StackTrace;
}
finally
{
webreq = null;
webresp = null;
sw = null;
sr = null;
s = null;
}

Вот вроде бы и все...
ava
CityAC | 20.09.2007, 19:02 #

Uri ourUri = new Uri("http://127.0.0.1:9999");// если прописываю порт, то ошибка "не могу соединится с удпленным хостом
// без порта проходи это место, но правда не знаю еще работает это или нет
HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(ourUri);
webreq.Method = "POST";
webreq.ContentType = "text/xml";
Stream streamTab = webreq.GetRequestStream();

TextWriter writerTab = new StreamWriter(streamTab);
serTab.Serialize(writerTab, temp);
writerTab.Close();


Это сервер - готов отправлять.
ava
Experimenter | 20.09.2007, 19:14 #
Цитата


если прописываю порт, то ошибка "не могу соединится с удпленным хостом


Ясен перец, не пройдет, надо чтоб сервер слушал тот порт. Это ж пример!!!
Цитата


Это сервер - готов отправлять.


Это клиент! Или я недоврубился?

added later:
На сервере HttpListener поднимают
ava
CityAC | 20.09.2007, 19:25 #
Называется ПРИЕХАЛИ!
клиента я написал такого как ты мне прислал (тот что ты используешь для тестирования сетевых приложений)
Тогда получается как написать на стороне сервера?
Че то я в край запутался.

На сервере формируется таблица с одной строкой.И эту таблицу нужно отправить на клиента
А если клиент редактирует эту строку, то ее нужно будет отправить назад на сервер

Получается что клиент должен слушать сервер и сервер должен слушать клиента.
ava
Experimenter | 20.09.2007, 20:03 #
Клиент это тот, кто шлет запросы
Сервер - тот, кто их обрабатывает и отсылает ответы
На Сервере обычно ставят асинхронный слухач. Эх...
Есть тоже пример, но он сырой, додумай сам

public class MyServer
{
static void Main()
{
MyServer myserv = new MyServer("http://127.0.0.1:9999/");
}

public MyServer(string prefix)
{
if (HttpListener.IsSupported)
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add(prefix);
listener.Start();
Console.WriteLine("Listening...");
while (true)
{
IAsyncResult iar = listener.BeginGetContext(new AsyncCallback(Start), listener);
iar.AsyncWaitHandle.WaitOne();
}
}
else Console.WriteLine("HttpListener is not supported by this System");
}

static void Start(IAsyncResult iar)
{
HttpListener listener = iar.AsyncState as HttpListener;
HttpListenerContext hlc = listener.EndGetContext(iar);
HttpListenerRequest hlReq = hlc.Request;
...
}
}

В данном случае HttpListenerRequest - это данные, пришедшие от клиента, у него тоже есть стрим (свойство InputStream).
В ответ нужно клиенту отправить OutputStream класса:

HttpListenerResponse hlResp = hlc.Response;

В данном случае это два простейших приложения (с Клиентом), их еще нужно шлифовать и шлифовать под себя.
Доходчиво?
ava
Experimenter | 20.09.2007, 20:19 #
Три добавления:
1. Чтобы упростить задачу нужно к HttpWebRequest прилепить свойство ContentLength, в котором указываешь длину сообщения, на Сервере тогда можно задать массив байтов с этой длиной, чтоб слить данные из InputStream'а. Мне думается, так проще
2. Опять же, чтоб упростить задачу, вместо того, чтоб сериализовать таблицу с одной строкой, не проще ли эти данные слить в стринг с разделителями, например "[email protected]@data3"? Хотя это дело вкуса.
3. Не знаю, что приходит от клиента, но если мало данных (ок. 200 байт), тогда можно GET-запросы отправлять, еще проще...
ava
CityAC | 21.09.2007, 02:10 #
Качнул книгу .NET сетевое программирование для профессионалов.
Почитал про работу сокетов и асинхронное программирование. Все стало на свои места.
Надо было с этого начать, чтоб не пугать людей своими вопросами.
Завтра, вернее сегодня приду на работу, буду этот ворох, что нагородил в проге разгребать. Специально дома на инете сидел, чтоб вникнуть в суть(на работе ремонт офиса, интернета нет).
Спасибо тебе Экспериментатор, как говорится направил, вывел в люди smile
ну, пора и спать.
ava
artechve | 26.09.2007, 15:45 #
Коллеи! подкиньте пож-та ссылок и примеров трехуровневых приложений.
и где можно почитать обзор как правильно делать 3L посредством .NET

я хочу сделать 3L - приложение на .NET , но при этом не испольховать WEBServices, а только MTS/COM+
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
advanced
Submit