Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.72/25: Рейтинг темы: голосов - 25, средняя оценка - 4.72
Java, C# - Expert
69 / 69 / 12
Регистрация: 09.08.2011
Сообщений: 284
1

Передача сообщения от клиентов к серверу Socket

17.03.2013, 11:35. Показов 4836. Ответов 10
Метки нет (Все метки)

Доброго времени суток, сидел целые 2 сутки думал разберусь сам... но не тут то было... Суть проблемы:
Надо написать службу которая через Socket будет ловить SQL запросы и взаимодействовать с базой, саму реализацию взаимодействия я сделал, все работает корректно, но тут я перешел к Socketу и все... понеслась, не могу сделать передачу сообщения и все, почти все смог сделать, и присоединение клиента и отсоединение (отлавливание этих моментов и вывод сообщений), но вот саму передачу сделать не могу, вот мой код, скажите что тут надо сделать, что-бы ловилось сообщение и писалось в richTextBox1

Класс Listener.cs
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
using System;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
 
namespace Server
{
    internal class Listener
    {
        private Socket s;
 
        public bool Listening { get; private set; }
 
        public int Port { get; private set; }
 
        public Listener(int port)
        {
            Port = port;
            s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
 
        public void Start()
        {
            if (Listening)
                return;
 
            s.Bind(new IPEndPoint(0, Port));
            s.Listen(0);
 
            s.BeginAccept(CallBack, null);
 
            Listening = true;
        }
 
        public void Stop()
        {
            if (!Listening)
                return;
            s.Close();
            s.Dispose();
            s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
 
        public void CallBack(IAsyncResult ar)
        {
            try
            {
                var socket = s.EndAccept(ar);
                if (SocketAccepted != null)
                {
                    SocketAccepted(socket);
                }
                s.BeginAccept(CallBack, null);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: " + ex.Message);
            }
        }
 
        public delegate void SocketAcceptedHandler(Socket e);
 
        public event SocketAcceptedHandler SocketAccepted;
    }
}
Server.cs
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
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Windows.Forms;
 
namespace Server
{
    public partial class Form1 : Form
    {
        private static Listener l;
        private static List<Socket> sockets;
        public Form1()
        {
            InitializeComponent();
            l = new Listener(5003);
            sockets = new List<Socket>();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            l.SocketAccepted += l_SocketAccepted;
            l.Start();
        }
 
        void l_SocketAccepted(Socket e)
        {
            richTextBox1.Text = string.Format("New connection: {0}\n{1}\n==============", e.RemoteEndPoint, DateTime.Now);//кстати тут выбивает попытку доступа к объекту из потока в котором он не был создан.
            sockets.Add(e);
        }
    }
}
Client.cs
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
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
 
namespace Client
{
    public partial class Form1 : Form
    {
        private Socket s;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            s.Connect("127.0.0.1", 5003);
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            var text = Encoding.ASCII.GetBytes(textBox1.Text);
            s.Send(text);
        }
    }
}

Заранее спасибо.

Добавлено через 7 часов 18 минут
Тема все еще актуальна...
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.03.2013, 11:35
Ответы с готовыми решениями:

Несколько клиентов к одному серверу через Socket
У меня не получается подключить больше одного клиента к одному серверу. Для тестирования использую...

Как серверу выборочно посылать сообщения одному из клиентов?
сервер // Get port from player // scanf(&quot;%5d&quot;, &amp;port); // Create a new socket to listen...

ServerSocket передача файлов от клиентов серверу
Нужна помощь! Есть приложение для win. Сервер - клиент для передачи файлов. Работает это все дело...

Передача сообщения серверу
Добрый день форумчане! Имеется модуль WiFi(ESP8266) с поднятым на нем TCP сервером. Но ноуте...

10
1047 / 878 / 229
Регистрация: 15.06.2012
Сообщений: 3,488
Записей в блоге: 1
17.03.2013, 17:32 2
Цитата Сообщение от IceSqueez Посмотреть сообщение
//кстати тут выбивает попытку доступа к объекту из потока в котором он не был создан.
SocketAccepted вызывается в CallBack, который в свою очередь работает в отдельном (асинхронном) потоке. Обычно в такое ситуации используют Invoke (Вызов функции в исходном потоке, посмотрите более детально в интернете).

C#
1
2
3
4
5
6
7
8
9
10
void l_SocketAccepted(Socket e)
        {
            richTextBox1.Invoke(new Action(delegate
            {
                richTextBox1.Text = string.Format("New connection: {0}\n{1}\n==============",
                    e.RemoteEndPoint, DateTime.Now);
            }));
            //кстати тут выбивает попытку доступа к объекту из потока в котором он не был создан.
            sockets.Add(e);
        }
Выводить сообщение об ошибке непосредственно в классе - очень плохая идея. Лучше просто закрывать соединение и генерировать событие об ошибке. Я вот про этот участок кода.
C#
1
2
3
4
catch (Exception ex)
{
  MessageBox.Show("Error: " + ex.Message);
}
Где метод принимающий данные на сервер? Или в чем проблема?
1
Java, C# - Expert
69 / 69 / 12
Регистрация: 09.08.2011
Сообщений: 284
17.03.2013, 19:03  [ТС] 3
С этим я уже разобрался, но я не знаю как сделать приём данных на сервере... что и где написать что-бы был метод типа: "Я принял текст что с ним делать ?", что-бы я в этом методе мог генерировать SQL запрос и отправить его к базе (это я знаю как сделать мне надо сам метод для приёма текста).

Уже не знаю что делать... голова кругом идет..)) через пару дней сдача курсовой, а я не могу в Sockete разобраться...
0
1047 / 878 / 229
Регистрация: 15.06.2012
Сообщений: 3,488
Записей в блоге: 1
17.03.2013, 19:28 4
Цитата Сообщение от IceSqueez Посмотреть сообщение
но я не знаю как сделать приём данных на сервере...
Метод recive вам в помощь.

Дабы особо не трындеть, вот библиотека, для передачи данных (корявая немного, но рабочая 100%). Всё что нужно - два соединенных сокета (вы уже это сделали) и создать свой класс-обертку, для данных сообщения, что-то на подобие такого:

C#
1
2
3
4
5
6
7
8
9
10
11
[Serializable]
public class MyMessage : Message
{
private string _sqlCommandString;
 
public MyMessage(string str)
{sqlCommandString = str;}
 
public string SqlCommandString 
{ get {return this.sqlCommandString: }}
 }
Далее всё очень просто - на клинте отправляем через public void Send(Message message) наше сообщение. На сервере делаем подписку на public event EventHandler<MessageEventArgs> getMessage; и обрабатываем все полученные сообщения (имейте ввиду, что обработка будет выполнятся в отдельном потоке, ибо используется асинхронный метод приема сообщений). И что хорошо - работает в обоих направлениях.
1
Вложения
Тип файла: zip NekoChat.NetworkManager.zip (44.2 Кб, 35 просмотров)
45 / 45 / 9
Регистрация: 19.11.2012
Сообщений: 124
17.03.2013, 19:34 5
Ну во 1-х, по поводу строки
C#
1
s.Listen(0);
метода Start. Меня смущает этот 0. Или у вас приложение не многоклиентское?
И в строке
C#
1
s.Bind(new IPEndPoint(0, Port));
меня так же смущает 0 на месте IP адреса.

Во 2-х, просто посылать сообщение методом Send (если это некая текстовая строка) не самая лучшая идея, нужно проверять все ли данные отправились, то есть написать свою функцию отправки, которая будет выглядеть примерно так: (пишу свою ф-кцию и на особую политкорректность не претендую):

C#
1
2
3
4
5
6
7
    static void sendMessage(Socket s, string message)
    {
        int messageLength = -1;
        byte[] msgToSent = Encoding.UTF8.GetBytes(message);
        while (messageLength != msgToSent.Length)
            messageLength = s.Send(msgToSent, 0, msgToSent.Length, SocketFlags.None);
    }
Проблема в этой функции может возникнуть тогда, когда данные не могут передаться, то есть получим зависание программы, но никто не мешает вам её доработать =)

В 3-х, при приеме сообщения, всяческие проверки тоже не будут лишними (пишу так же свою ф-кцию, возможно она кривая, но вполне работает):
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static string receiveMessage(Socket s)
    {
        if (s.Poll(1000000, SelectMode.SelectRead) == false)
            return "ERROR";
        string result = "";
        while (result == "" || result == " ")
        {
            int buffCnt = s.Available;
            int recCnt = 0;
            byte[] msg = new byte[buffCnt];
            while (recCnt != buffCnt)
                recCnt = s.Receive(msg, 0, buffCnt, SocketFlags.None);
            result = "";
            result = Encoding.UTF8.GetString(msg);
        }
        return result;
    }
1
1047 / 878 / 229
Регистрация: 15.06.2012
Сообщений: 3,488
Записей в блоге: 1
17.03.2013, 19:44 6
fictiont, в точку! Я когда писал чат, у меня было около дюжины разнотипных сообщений, причем их длина колебалась от 10байт, до 10Кбайт. А учитывая, что сервер был многоклиентский, отправлять "по частям вызывая десять раз метод Send" нельзя. Именно из-за этого мне пришлось написать общую обертку для сообщений и нахимичить класс для отправки/приема сообщений.
1
Java, C# - Expert
69 / 69 / 12
Регистрация: 09.08.2011
Сообщений: 284
17.03.2013, 20:28  [ТС] 7
Спасибо ребята, очень помогли, только у меня вопрос возник:
C#
1
s.Listen(0);
а что тут не так ??


C#
1
s.Bind(new IPEndPoint(0, Port));
А это я написал просто для теста (ибо тестирую на локалхосте)
на данный момент это уже переписано на сопоставление IP клиента (локального).
0
45 / 45 / 9
Регистрация: 19.11.2012
Сообщений: 124
17.03.2013, 20:36 8
Цитата Сообщение от IceSqueez Посмотреть сообщение
Спасибо ребята, очень помогли, только у меня вопрос возник:
C#
1
s.Listen(0);
а что тут не так ??
Мм.. просто что здесь будет при подключении более чем одного клиента?
0
1047 / 878 / 229
Регистрация: 15.06.2012
Сообщений: 3,488
Записей в блоге: 1
17.03.2013, 20:46 9
Цитата Сообщение от fictiont Посмотреть сообщение
Мм.. просто что здесь будет при подключении более чем одного клиента?
если последовательно, то ровным счетом ничего. и если мне не изменяет память, то ноль означает что нет ограничений на очередь.
1
45 / 45 / 9
Регистрация: 19.11.2012
Сообщений: 124
17.03.2013, 20:48 10
Цитата Сообщение от Wolfdp Посмотреть сообщение
если последовательно, то ровным счетом ничего. и если мне не изменяет память, то ноль означает что нет ограничений на очередь.

Ок, просто не был уверен в нуле. Было предположение, что он не пускает никого в очередь.
Последовательно не считается. =)
0
Java, C# - Expert
69 / 69 / 12
Регистрация: 09.08.2011
Сообщений: 284
18.03.2013, 19:49  [ТС] 11
Так все вроде-бы получается... осталась одна проблема, не могу установить службу моего проекта захожу в VS 2012 Promt и пишу:

C:\Program Files (x86)\Microsoft Visual Studio 11.0>installUtil.exe /i MachineEm
ulator
(MachineEmulator) это название проекта со службой.
на что мне отвечают:

C:\Program Files (x86)\Microsoft Visual Studio 11.0>installUtil.exe /i С:\MachineEm
ulator
Microsoft (R) .NET Framework Installation utility, версия 4.0.30319.17929
(c) Корпорация Майкрософт (Microsoft Corp.). Все права защищены.

Возникло исключение при инициализации установки:
System.IO.FileNotFoundException: Невозможно загрузить файл или сборку "file:///C
:\MachineEmulator" или один из
зависимых от них компонентов. Не удается найти указанный файл..

перепробывал все что можна, и к самой службе (bin\debug\MachineEmulator.exe), и к проекту и к солюшину, всегда тот-же ответ, какой путь там надо прописывать ?)))))

Добавлено через 22 часа 23 минуты
На правах "Up'а"
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.03.2013, 19:49

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Передача сообщения от клиента к серверу, сокеты
Хочу передать сообщение от клиента к серверу и вывести это сообщение. Как это сделать? сервер...

Socket несколько клиентов
Здравствуйте! Пишу прогу состоящую из двух серверов, смысл которой принять инфу от клиента на один...

Socket авторизация клиентов (Нужен совет)
Интересует где лучше хранить логин и пароль а так же доп инфу о пользователе на сервере, что бы...

Алгоритм обработки клиентов сервером (Socket)
Здравствуйте, друзья. Я всю голову сломал над тем, как правильно устроить общение клиента с...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.