Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.90/30: Рейтинг темы: голосов - 30, средняя оценка - 4.90
5 / 5 / 3
Регистрация: 16.08.2012
Сообщений: 53
1

Получение XML данных по TCP порту

16.08.2012, 12:19. Показов 5870. Ответов 12
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте,

Пишу приложение, которое будет получать XML-данные по TCP, а затем писать эти данные в базу данных.
Нашёл в интернете пример как отправлять и принимать XML по TCP-порту. Использовал его в своём приложении. XML отправляется, принимается, парсится и пишется в базу только, если прописать сам XML-код в тексте программы. А надо, чтобы программа открывала соединение на указанном порту и прослушивала этот порт, ожидая XML-сообщения от любого приложения (например отправки сообщения по телнету), а затем писала бы это сообщение в базу. Вопрос, как это сделать? Можете ли привести пример кода? Или дать ссылку на реализацию подобной программы. C# знаю слабо, поэтому желательны примеры кода
Отправляю то что пока у меня получилось. Спасибо!

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Xml;
 
 
namespace ConsoleApplication2
{
    class XMLBlaster
    {
        Thread myThread;
 
        public XMLBlaster()
        {
            myThread = new Thread(Start);
        }
 
        public void Begin()
        {
            myThread.Start();
        }
 
        //This will listen for a connection on port 12345, and send a tiny XML document
        //to the first person to connect.
        protected void Start()
        {
            TcpListener tcp = new TcpListener(IPAddress.Any, 12345);
            tcp.Start(1);
 
            TcpClient client = tcp.AcceptTcpClient();
 
            StreamWriter data = new StreamWriter(client.GetStream());
 
            data.Write(@"<element1>data1</element1>
<element2>data3</element2>
<element3>data3</element3>
<element4>data4</element4>");
 
            data.Close();
            client.Close();
        }
    }
 
 
    class Program
    {
        static void Main(string[] args)
        {
            //this sets up the server we will be reading
            XMLBlaster server = new XMLBlaster();
            server.Begin();
 
            //this is the important bit
 
            //First, create the client
            TcpClient tcp = new TcpClient(AddressFamily.InterNetwork);
 
            //Next, connect to the server. You probably will want to use the prober settings here
            tcp.Connect(IPAddress.Loopback, 12345);
 
            //Since byte manipulation is ugly, let's turn it into strings
            StreamReader data_in = new StreamReader(tcp.GetStream());
            string content = data_in.ReadToEnd();
            //And, just read everything the server has to say
            // Console.WriteLine(content);
 
            using (XmlReader reader = XmlReader.Create(new StringReader(content)))
            {
                reader.ReadToFollowing("element1");
                string element1 = reader.ReadElementContentAsString();
                reader.ReadToFollowing("element2");
                string element2 = reader.ReadElementContentAsString();
                reader.ReadToFollowing("element3");
                string element3 = reader.ReadElementContentAsString();
                reader.ReadToFollowing("element4");
                string element4 = reader.ReadElementContentAsString();
                System.Data.SqlClient.SqlConnection sqlConnection1 =
                new System.Data.SqlClient.SqlConnection("My datasource");
                System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
                cmd.CommandType = System.Data.CommandType.Text;
                cmd.CommandText = "My insert SQL-statement";
                cmd.Connection = sqlConnection1;
                sqlConnection1.Open();
                cmd.ExecuteNonQuery();
                sqlConnection1.Close();
 
            }
 
            //when we're done, close up shop.
            data_in.Close();
            tcp.Close();
 
            //this is just to pause the console so you can see what's going on.
            //Console.WriteLine("Press any key to continue...");
            //Console.ReadKey(false);
 
        }
    }
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.08.2012, 12:19
Ответы с готовыми решениями:

Получение данных из TCP пакета
Вот код: #include &lt;conio.h&gt; #include &lt;stdio.h&gt; #include &lt;winsock2.h&gt; #define MAX_PACKET_SIZE ...

Получение данных из контроллера по TCP
Здравствуйте! У меня есть анализатор мощности, который меряет напряжение, у него есть Ethernet и...

Синхронное получение данных TCP IP
Салют, комрады! Может кто сталкивался с такой проблемкой при работе с данными через TCP IP....

Tcp client отправка и получение данных
Здравствуйте, подскажите пожалуйста что делаю не так. Пишу приложение для android, необходимо...

12
310 / 206 / 44
Регистрация: 15.02.2012
Сообщений: 605
16.08.2012, 18:05 2
http://msdn.microsoft.com/ru-r... lient.aspx

http://msdn.microsoft.com/ru-r... lient.aspx

Здесь в каждой из этих тем в конце есть по полному примеру реализации TCP-клиента и TCP-сервера.

Достаточно скопировать в два проекта и заменить переменную server на ip-адрес и можно пользоваться
0
5 / 5 / 3
Регистрация: 16.08.2012
Сообщений: 53
16.08.2012, 21:11  [ТС] 3
jivot, Спасибо! Почитаю. А Вы две одинаковые ссылки скинули. Вторая на tcp server должна быть?
0
310 / 206 / 44
Регистрация: 15.02.2012
Сообщений: 605
16.08.2012, 21:15 4
Пардон

сервер:
http://msdn.microsoft.com/ru-r... tener.aspx

клиент:
http://msdn.microsoft.com/ru-r... lient.aspx
1
5 / 5 / 3
Регистрация: 16.08.2012
Сообщений: 53
17.08.2012, 17:50  [ТС] 5
jivot, Спасибо! Заработало! То что нужно!
Сейчас вот пытаюсь сделать, чтобы TCP Server работал, как виндовая служба и также нужно реализовать многопоточность, чтобы данные от клиентов обрабатывались параллельно, а не последовательно.
Взял код из примера http://msdn.microsoft.com/ru-r... tener.aspx, добавил туда парсинг XML и запись в БД и поместил это в метод
C#
1
protected override void OnStart(string[] args)
.
Но в итоге моя служба повисает в состоянии "В процессе запуска", но при этом она в процессах виндоуса есть и работает. Т.е. парсит сообщения от клиента и пишет их в базу.
Вот пока разбираюсь с тем, что мешает ей перейти в состояние "Работает".
0
310 / 206 / 44
Регистрация: 15.02.2012
Сообщений: 605
18.08.2012, 11:19 6
А сервер реализован где? В процедуре OnStart?

Если да, тогда конечно он там будет крутиться, обрабатывать данные, но служба будет думать, что она ещё не запустилась
0
5 / 5 / 3
Регистрация: 16.08.2012
Сообщений: 53
18.08.2012, 11:26  [ТС] 7
jivot, Да, всё разобрался в чём дело было.
Сервер реализовал в отдельном методе и в процедуре OnStart запустил его в отдельном потоке, и всё нормально заработало
Теперь хочу сделать, чтобы мой сервер мог получать данные одновременно с нескольких клиентов.
Можно как-нибудь переделать этот код: http://msdn.microsoft.com/ru-r... ener.aspx?
Я так понимаю нужно передать каждый TcpClient в отдельный поток? Как это сделать?
0
310 / 206 / 44
Регистрация: 15.02.2012
Сообщений: 605
18.08.2012, 12:01 8
Ну можно например асинхронный вызов метода ...

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private delegate void tcpDelegate(TcpClient client);     // делегат
 
private void ServerThread()
{
     ...
     TcpClient client = server.AcceptTcpClient();   
     tcpDelegate newClientRun = new tcpDelegate(InsertIntoBase); // экземпляр делегата     
     newClientRun.BeginInvoke(client, null, null);  // асинхронный вызов
     ...
}
 
private void InsertIntoBase(TcpClient client)
{
     // запись в базу
}
... но вот организовать безопасный доступ потоков к базе ... тут надо подумать
1
5 / 5 / 3
Регистрация: 16.08.2012
Сообщений: 53
20.08.2012, 12:31  [ТС] 9
jivot,
Т.е. если я правильно понял, то тут создаётся отдельный поток на запись в базу и новый клиент может подключиться к серверу не дожидаясь завершения записи в базу данных?
0
310 / 206 / 44
Регистрация: 15.02.2012
Сообщений: 605
20.08.2012, 13:46 10
Что-то вроде того ...

можно использовать маркер блокировки

C#
1
2
3
4
5
6
7
private void InsertIntoBase(TcpClient client)
{
     lock (this)
     {
          // запись в базу
     }
}
тогда поток не даст доступ другим потокам к методу, пока не завершит работу с ним ...

ну или любые другие понравившиеся методы синхронизации потоков
0
5 / 5 / 3
Регистрация: 16.08.2012
Сообщений: 53
20.08.2012, 14:15  [ТС] 11
jivot,
У меня вот что пока получилось:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Xml;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Net;
 
namespace WindowsService1
{
 
 
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
            if (!System.Diagnostics.EventLog.SourceExists("MySource"))
            {
                System.Diagnostics.EventLog.CreateEventSource(
                    "MySource", "MyNewLog");
            }
            eventLog1.Source = "MySource";
            eventLog1.Log = "MyNewLog";
 
        }
 
        protected override void OnStart(string[] args)
        {
            System.Threading.Thread newThread =
    new System.Threading.Thread(tcpserver);
            newThread.Start();
 
        }
 
        protected override void OnStop()
        {
            eventLog1.WriteEntry("In OnStop");
            TcpListener server = null;
            // Set the TcpListener on port 13000.
            Int32 port = 13000;
            IPAddress localAddr = IPAddress.Parse("127.0.0.1");
 
            // TcpListener server = new TcpListener(port);
            server = new TcpListener(localAddr, port);
 
            // Stop listening for client requests.
            server.Stop();
 
        }
 
        private delegate void tcpDelegate(String data);     // делегат
        private void tcpserver()
    {
        TcpListener server = null;
        try
        {
        // Set the TcpListener on port 13000.
        Int32 port = 13000;
        IPAddress localAddr = IPAddress.Parse("127.0.0.1");
 
        // TcpListener server = new TcpListener(port);
        server = new TcpListener(localAddr, port);
 
        // Start listening for client requests.
        server.Start();
 
        // Buffer for reading data
        Byte[] bytes = new Byte[512];
        String data = null;
 
        // Enter the listening loop.
        while (true)
        {
 
            // Perform a blocking call to accept requests.
            // You could also user server.AcceptSocket() here.
            TcpClient client = server.AcceptTcpClient();
            //Console.WriteLine("Connected!");
 
            data = null;
 
            // Get a stream object for reading and writing
            NetworkStream stream = client.GetStream();
 
            int i;
 
            // Loop to receive all the data sent by the client.
            while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
            {
                // Translate data bytes to a ASCII string.
                data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                tcpDelegate td = InsertIntoBase;
                IAsyncResult asynchRes = td.BeginInvoke(data, null, null);
                // Process the data sent by the client.
                data = data.ToUpper();
                byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
                // Send back a response.
                stream.Write(msg, 0, msg.Length);
 
            }
 
            // Shutdown and end connection
            client.Close();
        }
        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: {0}", e);
        }
    }
 
        static void InsertIntoBase(String data)
        {
            // запись в базу
 
            using (XmlReader reader = XmlReader.Create(new StringReader(data)))
            {
                reader.ReadToFollowing("element1");
                string element1 = reader.ReadElementContentAsString();
                reader.ReadToFollowing("element2");
                string element2 = reader.ReadElementContentAsString();
                reader.ReadToFollowing("element3");
                string element3 = reader.ReadElementContentAsString();
                reader.ReadToFollowing("element4");
                string element4 = reader.ReadElementContentAsString();
                System.Data.SqlClient.SqlConnection sqlConnection1 =
                new System.Data.SqlClient.SqlConnection("My datasource");
                System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand();
                cmd.CommandType = System.Data.CommandType.Text;
                cmd.CommandText = "My insert SQL-statement";
                cmd.Connection = sqlConnection1;
                sqlConnection1.Open();
                cmd.ExecuteNonQuery();
                sqlConnection1.Close();
 
            }
        }
 
    }
 
}
Т.е. я передаю строку полученную по сети в асинхронно вызванный метод, затем эта строка парсится и пишется в базу.
В случае с маркером блокировки не понял: зачем блокировать доступ другим потокам к методу для записи в базу? Ведь в этом случае получается последовательная обработка данных, по одному клиенту, а не одновременные подключения и запись сразу с нескольких клиентов?
И, кстати, подключения самих клиентов будут происходить последовательно? Т.е. если в один момент времени решат подключиться сразу 50 клиентов, то они всё равно ведь будут подключаться один за другим, а не все сразу?
0
310 / 206 / 44
Регистрация: 15.02.2012
Сообщений: 605
20.08.2012, 15:01 12
Хм ... что значит "подключаться одновременно"? ... Сервер работает, получает подключение от одного клиента, отправляет его в отдельный поток, берет следующее подключение - отправляет в другой поток.

Подключаются они последовательно конечно ... но обсчитываются потом параллельно в разных потоках.

а, ну в вашем случае блокировка не нужна, SQL Server сам расставит очередь записи и конфликтов быть не должно
1
5 / 5 / 3
Регистрация: 16.08.2012
Сообщений: 53
20.08.2012, 15:56  [ТС] 13
Спасибо! Да я думал, что сразу одновременно все клиенты подключатся и начнут отправлять данные в базу . Хотя это и незачем, всё равно два запроса на вставку данных в таблицу в один момент времени не смогут выполняться. SQL Server один за другим их будет выполнять.
Так-то всё готово вроде. Спасибо за помощь!

Добавлено через 9 минут
Цитата Сообщение от jivot Посмотреть сообщение
Сервер работает, получает подключение от одного клиента, отправляет его в отдельный поток, берет следующее подключение - отправляет в другой поток.
Только у меня в отдельный поток получается что отправляется не клиент, а полученное сообщение от этого клиента...
0
20.08.2012, 15:56
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.08.2012, 15:56
Помогаю со студенческими работами здесь

Как происходит получение данных через протокол TCP
Имеется клиент-серверное приложение: using System; using System.Collections.Generic; using...

Сообщения по TCP порту
Добрый день, есть задача слушать определенный TCP порт, по нему приходят сообщения с устройства,...

Получение Данных Из Xml
Друзья! Нужна помощь и всякие мысли на тему разработки приложения. Ситуация: Имеется SQL база в...

Получение данных из XML
Добрый день! Есть XML файл с информацией. Вот небольшой фрагмент его кода: &lt;TextAssetInfo&gt; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru