Начните слушать снова с Socket после отключения - PullRequest
2 голосов
/ 30 ноября 2010

Я пишу небольшое приложение для сокетов C #. На самом деле у меня есть два, сервер и клиент.

Пользователь запускает клиент, вводит IP-адрес и порт для сервера, нажимает «подключиться», а затем, после подключения, он может ввести текст в текстовое поле и отправить его на сервер.

Сервер просто отображает «Нет соединения» или «Соединение с [ip]: [порт]», а последнее полученное сообщение внизу.

Сервер успешно принимает сообщения и даже нормально обрабатывает клиентское отключение. Теперь я пытаюсь снова прослушать его после того, как клиент отключился, но по какой-то причине ничто из того, что я пробую, не позволит ему снова начать слушать.

Вот часть моего кода:

    Socket socket;
    private void listen()
    {
        socket = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);
        socket.Bind(new IPEndPoint(IPAddress.Any, 12345));
        socket.Listen(10);
        socket.BeginAccept(new AsyncCallback(acceptAsync), socket);
    }

и

    private void receiveAsync(IAsyncResult res)
    {
        Socket socket = (Socket)res.AsyncState;

        try
        {
            int nBytes = socket.EndReceive(res);
            if (nBytes > 0)
            {
                Invoke(new MethodInvoker(delegate()
                {
                    lMessage.Text = encoder.GetString(buffer);
                }));
                setupReceiveAsync(socket);
            }
            else
            {
                Invoke(new MethodInvoker(delegate()
                {
                    lConnections.Text = "No Connections.";
                    lMessage.Text = "No Messages.";
                    socket.Shutdown(SocketShutdown.Both);
                    socket.Close();
                    listen();
                }));
            }
        }
        catch { }
    }

Последняя строка: listen (); это то, что выдает ошибку. Я попытался просто вызвать socket.BeginAccept () снова, но это также вызывает исключение.

Я получаю сообщение:

Обычно разрешено только одно использование каждого адреса сокета (протокола / сетевого адреса / порта)

Если я не вызываю свою функцию listen () и вместо этого просто вызываю socket.BeginAccept (), тогда я получаю «Сначала вы должны вызвать socket.listen ()»

Если я вызываю функцию socket.listen (), она сообщает, что она уже подключена, и корзина начинает слушать.

Как только я установил асинхронное соединение и получил несколько асинхронных сообщений, как мне снова начать получать?

Ответы [ 2 ]

2 голосов
/ 30 ноября 2010

In async Begin* всегда сопровождается End*.См. Использование асинхронного серверного сокета .Ваш метод accept должен быть примерно таким:

try {
        listener.Bind(localEP);
        listener.Listen(10);

        while (true) {
            allDone.Reset();

            Console.WriteLine("Waiting for a connection...");
            listener.BeginAccept(
                new AsyncCallback(SocketListener.acceptCallback), 
                listener );

            allDone.WaitOne();
        }
    } catch (Exception e) {

Server, означает, что приложение, которое прослушивает указанный порт / ip.Обычно всегда в режиме прослушивания - поэтому он называется сервером.Он может подключать и отключать клиента, но всегда находится в режиме прослушивания .

Это означает, что когда сервер отключает клиента - даже тогда - это в режиме прослушивания;Это означает, что он может принимать и входящие соединения.

Хотя запрос на отключение может исходить от клиента или принудительно применяться сервером.

Процесс для сервера:

  1. Привязка к сокету
  2. Прослушивание
  3. Прием соединений

Процесс для клиента:

  1. Подключение к серверу
  2. Отправка / получение сообщений

Сервер может обрабатывать входящие клиенты несколькими способами:

  • Входящие соединения поддерживаются всписок, например, внутри List<TcpClient>.
  • . Один из способов обработки входящих клиентов - через потоки.Например, для каждого входящего клиента создайте поток, который будет обрабатывать связь между сервером и клиентом.Например, оформить заказ в этом примере .

_

private  void ListenForClients()
{
  this.tcpListener.Start();

  while (true)
  {
    //blocks until a client has connected to the server
    TcpClient client = this.tcpListener.AcceptTcpClient();

    //create a thread to handle communication
    //with connected client
    Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
    clientThread.Start(client);
  }
}
  • Использовать один поток и использовать переключение контекста для управления связью клиента (TX / RX).
2 голосов
/ 30 ноября 2010

Ваша переменная socket уже имеет сокет прослушивания, назначенный ей во второй раз, когда вы вызываете listen(), поэтому она сообщает, что разрешено только одно использование. Все, что вам нужно повторить, это звонок socket.BeginAccept(new AsyncCallback(acceptAsync), socket). Поэтому попробуйте заменить вызов listen() в вашем методе receiveAsync(...) на socket.BeginAccept(new AsyncCallback(acceptAsync), socket).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...