Модераторы: gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Socket.Accept 
:(
    Опции темы
kosterorc
Дата 7.2.2007, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 7.2.2007

Репутация: нет
Всего: нет



ПРи ожидании подключения к сокету дальнейшая работа программы останавливается до тех пор пока не произойдет подключение, что фигово.
Решил проблему так:
Создаю и жду:
Код

byte[] addr = { 127, 0, 0, 1 };
IPAddress ipa = new IPAddress(addr);
IPEndPoint ep = new IPEndPoint(ipa, 12589);
Socket srv = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

srv.Blocking = false;
srv.Bind(ep);
srv.Listen(0);

bool conn = false;
Socket skt = null;
Console.WriteLine("Ожидание подключения...");


while (!conn)
{
     skt = Acpt(srv); // см. ниже
     conn = skt != null;
     Thread.Sleep(250);
     if (Console.KeyAvailable && Console.ReadKey().Key == ConsoleKey.Escape)
     break;
}

if (conn)
{
     Console.WriteLine("Подключено!");
     byte[] buff = new byte[255];
     int rcvd = skt.Receive(buff);
     Console.WriteLine("Принято " + rcvd + " байт");
     for (int i = 0; i < rcvd; i++)
     {
          Console.WriteLine(buff[i]);
     }
     skt.Close();
}
else
{
     Console.WriteLine("Не подключилось");
}
srv.Close();


Метод отвечающий за ожидание:
Код

private Socket Acpt(Socket srv)
{
     Socket skt;
     try
     {
          skt = srv.Accept();
     }
     catch (Exception)
     {
          skt = null;
     }
     return skt;
}


Есть ли какие-то более разумные варианты?
PM MAIL   Вверх
-Mikle-
Дата 8.2.2007, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 1
Всего: 59



А что тебе мешает в отдельном потоке ждать подключения?
Если не знаешь как или о чем я вообще, то я поясню с примером после твоего соответствующего топика...


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
Miller_time
Дата 9.2.2007, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 641
Регистрация: 8.9.2006
Где: Нижний Новгород

Репутация: нет
Всего: 1



Народ дайте простой пример подключения к удалённому компьюетеру ? под 2005 студио  smile 


--------------------
Мы делаем игрыЗДЕСЬ
PM MAIL WWW ICQ   Вверх
-Mikle-
Дата 9.2.2007, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 1
Всего: 59



Код

    // ожидает в отдельном потоке соединение клиентского компа
    // и генерит событие (в том же своем потоке), о таком факте
    public class ConnectionListener
    {
        TcpListener _tcplist;           // наш листенер
        ManualResetEvent _eventWork;    // объект "разморозки" потока

        public ConnectionListener(IPAddress addr, int port)
        {
            // без коментариев
            _tcplist = new TcpListener(addr, port);
            _eventWork = new ManualResetEvent(false);
        }

        // событие при соединении клиента
        public event EventHandler<ClientConnectEventArgs> ClientConnect;
        protected virtual void OnClientConnect(ClientConnectEventArgs e)
        {
            if (ClientConnect != null)
                ClientConnect(this, e);
        }

        public void Start()
        {
            _tcplist.Start();       // стартуем прослушку
            _eventWork.Reset();     // сбросим состояние
            
            // и запускаем нашу ф-ию в системном пуле потоков
            ThreadPool.QueueUserWorkItem(new WaitCallback(doWork), null);
        }

        public void Stop()
        {
            // сообщаем состояние для потока
            _eventWork.Set();

            // ждем завершения потока 5000 милисекунд
            // ставим такую задержку, чтоб не зависнуть навсегда.
            // мало-ли что может произойти... Windows то, глюковатый иногда :)
            // на практике на этом методе прога не висит долго, несколько миллисекунд
            _eventWork.WaitOne(5000, false);
            
            // остановим прослушку
            _tcplist.Stop();
        }

        // собственно сама ф-ия работающая в отдельном потоке, главнейшая в объекте!!! :)
        private void doWork(object state)
        {
            // пауза между повторами ожидания соединения
            const int sleep = 100;

            // пока состояние объекта в течении интервала "sleep" равно false, выполняем цикл
            while (!(_eventWork.WaitOne(sleep, false)))
            {
                // если есть запрос на подключение, то
                if (_tcplist.Pending())
                {
                    // вызываем событие
                    OnClientConnect(new ClientConnectEventArgs(_tcplist.AcceptSocket()));
                }
            }
        }
    }


и класс-аргумент для события:

Код

    // класс-аргумент для события о присоединении клиента.
    // содержит Socket присоединенного клиента и при необходимости, можно 
    // добавить еще всяких свойств, например время присоединения, с точностью 
    // до милисекунды :)
    public class ClientConnectEventArgs : EventArgs
    {
        public ClientConnectEventArgs(Socket client)
        {
            _client = client;
        }

        private readonly Socket _client;
        public Socket Client { get { return _client; } }
    }


и еще класс - пример использования:

Код

    // ВНИМАНИЕ!!! ЗАПРЕЩЕНО НАПРЯМУЮ КОПИРОВАТЬ ЭТОТ КЛАСС БЕЗ ДОРАБОТКИ :) :) :) !!!
    public class Server
    {
        ConnectionListener _connlist = null;

        public void Run()
        {
            if (_connlist != null) return;

            // слушаем HTTP-port
            _connlist = new ConnectionListener(IPAddress.Any, 8080);
            _connlist.ClientConnect += new EventHandler<ClientConnectEventArgs>(connectionListener_ClientConnect);
            _connlist.Start();
        }

        public void Stop()
        {
            if (_connlist == null) return;

            _connlist.Stop();
            _connlist = null;
        }

        private void connectionListener_ClientConnect(object sender, ClientConnectEventArgs e)
        {
            // УРА! К НАМ ПРИСОЕДИНИЛИСЬ!!!
            // Мы можем теперь все что угодно слать клиенту и получать от него тоже!!!
            // Спасибо Мелкософту за такую возможность!!! :) :) :)
            Socket client = e.Client;
            Console.WriteLine("Кто же соединился? хммм... а вот кто: {0}", client.RemoteEndPoint);
        }
    }


может пригодиться кому-нить...
вместо отдельного потока, если приложение с формой работает, можно вообще без всего такого обойтись, кинув таймер на форму и поместив в обработчик только условие if из doWork...
Хотя всем известно, что такой подход к архитектуре, не есть гуд...


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
Alexsar
Дата 9.2.2007, 23:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 96
Регистрация: 6.5.2005

Репутация: нет
Всего: 1



TO kosterorc
а что тебе мешает использовать асинхронные методы BeginAccept и EndAccept
вот примеры прог где всё выполняется в разных потоках

сервер
Код

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace AsyncServer
{
    class Program
    {
        public static byte[] buffer = new byte[1024];
        public static ManualResetEvent SocketEvent = new ManualResetEvent(false);
        public static string content = String.Empty;
        static void Main(string[] args)
        {
            Console.WriteLine("идентификатор потока ID: " + AppDomain.GetCurrentThreadId().ToString());
            byte[] bytes=new byte[1024];

            IPHostEntry ipHost = Dns.Resolve(Dns.GetHostName());
            IPAddress ipAdd = ipHost.AddressList[0];
            IPEndPoint endPoint = new IPEndPoint(ipAdd, 11000);

            Socket sListerner = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            sListerner.Bind(endPoint);
            sListerner.Listen(10);
            Console.WriteLine("ожидание соединения");
            AsyncCallback callback = new AsyncCallback(Acceptcallback);
            sListerner.BeginAccept(callback, sListerner);
            SocketEvent.WaitOne();
            Console.ReadLine();
        }
        public static void Acceptcallback(IAsyncResult ar)
        {
            Console.WriteLine("идентификатор потока Acceptcallback ID: " + AppDomain.GetCurrentThreadId().ToString());
            Socket sListern = (Socket)ar.AsyncState;
            Socket handler = sListern.EndAccept(ar);
            handler.BeginReceive(buffer, 0, buffer.Length, 0, new AsyncCallback(Receivecallback), handler);
        }
        public static void Receivecallback(IAsyncResult ar)
        {
            Console.WriteLine("идентификатор потока Receive ID: " + AppDomain.GetCurrentThreadId());
            Socket handler = (Socket)ar.AsyncState;
            int byteread = handler.EndReceive(ar);
            if (byteread > 0)
            {
                content += Encoding.Unicode.GetString(buffer, 0, byteread);
                if (content.LastIndexOf("<TheEnd>") > -1)
                {
                    Console.WriteLine("прочтено {0} байтов; мессага\n{1}", content.Length, content);
                    byte[] byteData = Encoding.Unicode.GetBytes(content);
                    handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(Sendcallback), handler);
                }
                else
                {
                    handler.BeginReceive(buffer, 0, buffer.Length, 0, new AsyncCallback(Receivecallback), handler);
                }
            }
        }
        public static void Sendcallback(IAsyncResult ar)
        {
            Console.WriteLine("идентификатор потока Send ID: " + AppDomain.GetCurrentThreadId());
            Socket handler = (Socket)ar.AsyncState;
            int byteSend = handler.EndSend(ar);
            Console.WriteLine("отправлено {0} байт клиенту",byteSend);
            handler.Shutdown(SocketShutdown.Both);
            handler.Close();
            SocketEvent.Set();
        }
    }
}



клиент
Код

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;

namespace AsyncClient
{
    class Program
    {
        public static string theResponse = "";
        public static byte[] bufer = new byte[1024];

        public static ManualResetEvent ConnectDone = new ManualResetEvent(false);
        public static ManualResetEvent SendDone = new ManualResetEvent(false);
        public static ManualResetEvent ReceiveDone = new ManualResetEvent(false);
        static void ConnectCallBack(IAsyncResult ar)
        {
            Thread thr = Thread.CurrentThread;
            Console.WriteLine("состояние потока в калбеке Connect: " + thr.ThreadState);
            Socket sClient = (Socket)ar.AsyncState;
            sClient.EndConnect(ar);
            Console.WriteLine("сокет подсоеденился к удалённой точке: " + sClient.RemoteEndPoint.ToString());
            ConnectDone.Set();
        }

        static void SendCallBack(IAsyncResult ar)
        {
            Thread thr = Thread.CurrentThread;
            Console.WriteLine("состояние потока в калбеке Send: " + thr.ThreadState);
            Socket sClient = (Socket)ar.AsyncState;
            int bytesend = sClient.EndSend(ar);
            Console.WriteLine("было отправлено: " + bytesend.ToString()+" байт");
            SendDone.Set();
        }

        static void ReceiveCallBack(IAsyncResult ar)
        {
            Thread thr = Thread.CurrentThread;
            Console.WriteLine("состояние потока в калбеке Receive: " + thr.ThreadState);
            Socket sClient = (Socket)ar.AsyncState;
            int receivebyte = sClient.EndReceive(ar);
            if (receivebyte > 0)
            {
                theResponse += Encoding.Unicode.GetString(bufer, 0, receivebyte);
                sClient.BeginReceive(bufer, 0, bufer.Length, 0, new AsyncCallback(ReceiveCallBack), sClient);
            }
            else
            {
                ReceiveDone.Set();
            }
        }

        static void Main(string[] args)
        {
            try
            {
                Thread thr = Thread.CurrentThread;
                Console.WriteLine("состояние главного потока: ", thr.ThreadState);
                IPHostEntry ipHost = Dns.Resolve("127.0.0.1");
                IPAddress ipAdd = ipHost.AddressList[0];
                IPEndPoint endPoint = new IPEndPoint(ipAdd, 11000);
                Socket sClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                sClient.BeginConnect(endPoint, new AsyncCallback(ConnectCallBack), sClient);
                ConnectDone.WaitOne();
                string data = "Это тест";
                for (int i = 0; i < 72; i++)
                {
                    data += i.ToString() + ":" + (new string('=', i));
                }
                byte[] byteData = Encoding.Unicode.GetBytes(data + "<TheEnd>");
                sClient.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallBack), sClient);
                for (int i = 0; i < 5; i++)
                {
                    //типа тут мы пожираем ресурсы пока ждём ответа от сервера
                    Console.WriteLine(i.ToString());
                    Thread.Sleep(10);
                }
                SendDone.WaitOne();
                sClient.BeginReceive(bufer, 0, bufer.Length, 0, new AsyncCallback(ReceiveCallBack), sClient);
                ReceiveDone.WaitOne();
                Console.WriteLine("было принято: "+ theResponse);
                sClient.Shutdown(SocketShutdown.Both);
                sClient.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            Console.ReadLine();
        }
    }
}



вроде всё smile 
PM MAIL   Вверх
kosterorc
Дата 15.2.2007, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 7.2.2007

Репутация: нет
Всего: нет



-Mikle-, 
С использованием многопоточности задача решается только частично: после запуска процесса приложение живет и реагирует на др. события, но если мы вызовем метод потока Abort поток не останавливается. При этом если сделать thr.Join, то приложение зависает насмерть.
Код

namespace NetTread
{
    public partial class Form1 : Form
    {
        static NetThread nt = new NetThread();

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            nt.BeginReciving();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            nt.AbortReciving(true);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            nt.AbortReciving(MessageBox.Show("Wanna join?", "Join request", MessageBoxButtons.YesNo) == DialogResult.Yes);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            MessageBox.Show("App: I'm alive!");
            if (nt.thr.IsAlive)  MessageBox.Show("NetThread.thr: I'm alive!");
        }
    }

    class NetThread
    {
        public Thread thr;
        Socket skt;
        Socket askt;

        public delegate void onRecive(byte[] b);

        public event onRecive Recv;

        public void Accept()
        {
            byte[] addr = { 127, 0, 0, 1 };
            byte[] b = new byte[10];
            IPAddress ipa = new IPAddress(addr);
            IPEndPoint ep = new IPEndPoint(ipa, 12589);
            skt.Bind(ep);
            skt.Listen(0);

            askt = skt.Accept();

            if (askt != null && askt.Available > 0)
            {
                lock (askt) askt.Receive(b);
                if (Recv != null)
                    Recv(b);
            }
            Listen();
        }

        public NetThread()
        {
            skt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            askt = null;
            thr = new Thread(Accept);
            thr.IsBackground = true;
        }

        public void BeginReciving()
        {
            thr.Start();
        }

        public void AbortReciving(bool w8)
        {
            thr.Abort();
            if (w8) thr.Join();
            MessageBox.Show("Aborted!");
        }

        void Listen()
        {
            Socket s = askt == null ? skt : askt;
            byte[] b = new byte[10];

            while (s.Connected)
            {
                if (s.Available > 0)
                {
                    lock (s) s.Receive(b);
                    if (Recv != null) Recv(b);
                }
                Thread.Sleep(0);
            }
        }
    }
}



PM MAIL   Вверх
-Mikle-
Дата 19.2.2007, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Невидимка Vingrad'а
***


Профиль
Группа: Экс. модератор
Сообщений: 1672
Регистрация: 22.6.2003
Где: Казахстан, Астана

Репутация: 1
Всего: 59



Щас не работает голова, чтобы сообразить почему не работает Abort, но в любом случае такой способ не хорош для завершения работы потока. Посмотри еще раз внимательнее, как в моем примере я организовал цикл потока и как я его завершаю. Этот способ считается стандартным.


--------------------
Если тебе плюют в спину, значит ты впереди...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
cully
mr.DUDA
Exception

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, cully, mr.DUDA, Exception.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Распределённые приложения и сеть | Следующая тема »


 




[ Время генерации скрипта: 0.0542 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.