поток не был доступен для записи при попытке записи в Networkstream

Я новичок в сокетах и ​​пытаюсь написать клиент-серверное приложение. Мое приложение имеет два основных метода:

СЕРВЕР работает в отдельном потоке:

    public void socketListener()
    {
        byte[] StreamMessage = new byte[9632];
        Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        IPEndPoint localEndPoint =new IPEndPoint(IPAddress.Any , ControlLayer.GlobalParam.PEER2PEER_PORT);
            listener.Bind(localEndPoint);
            listener.Listen(10);

            while (true)
            {
                Socket Handler = listener.Accept();
                //int ByteRec = Handler.Receive(StreamMessage);

                int MessageLength;
                MessageLength = Handler.Receive(StreamMessage, 0, StreamMessage.Length, SocketFlags.None);
                //return MessageLength;

               // string message = System.Text.Encoding.Default.GetString(StreamMessage);
                string message = System.Text.Encoding.UTF8.GetString(StreamMessage);

                OnDataRecievedFromRemotePeer(this, message, "TcpServer");//send data to screen
                Task.Run(() => { ParseMessage(message, Handler); });
            }
    }

как только данные поступят, я буду собирать данные и отправлять их с помощью Client CLIENT:

    public void Write(string message)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(CreateClient), message);
    }

    private void CreateClient(object message)
    {
        try
        {
            peerClient = new TcpClient();
            peerClient.Connect(remoteIP, 6001/*TODO remove this */);
            netStream = peerClient.GetStream();//<- Exception 
            StreamWriter sw = new StreamWriter(netStream);
            sw.Write((string)(message));
            netStream.Close();
            peerClient.Close();
        }
        catch(Exception ex)
        {
            //TODO :
        }
    }

Каждая станция симметрична и имеет эти два метода

Я могу сказать, что сервер работает и принимает сокет и данные, но как только я хочу ответить, я получаю исключение в строке, отмеченной в потоке CreateClient
, недоступной для записи, и при просмотре netStream написано, что у меня есть ObjectDisposed Исключение . Что может быть тому причиной?

Также, пожалуйста, сообщите мне, если требуется больше кода


person LordTitiKaka    schedule 09.07.2014    source источник


Ответы (1)


У вас здесь классическая гонка между сервером, закрывающим соединение до того, как клиент обработает ответ сервера.
TCP является «вежливым» протоколом, что означает, что вы не можете выполнить действие «выстрелил и забыл» на сервере. Соединение должно быть активным на обоих концах, пока обе стороны не обработают все сообщения. Таким образом, либо клиент должен отправить подтверждение/выход из системы, чтобы сервер мог закрыть соединение, либо, по крайней мере, сервер должен подождать x секунд, прежде чем закрыть его.

person weismat    schedule 09.07.2014
comment
Извините за глупый вопрос, а где на сервере закрыть соединение? Кроме того, как вы думаете, моя логика является хорошей практикой для этого типа приложений? - person LordTitiKaka; 09.07.2014
comment
Классический способ — иметь один поток или задачу для каждого клиента на сервере. В настоящее время ваше клиентское соединение существует только во время одной итерации цикла while. Обычно я использую sth следующим образом: while (true) { TcpClient client = _tcpListener.AcceptTcpClient(); Log.Info(Новый клиент подключен); var clientThread = новый поток (HandleClientComm) {IsBackground = true}; clientThread.Start(клиент); } - person weismat; 09.07.2014
comment
не могли бы вы опубликовать короткий код, чтобы я мог шаг за шагом вывести его из жизни? :) - person LordTitiKaka; 09.07.2014
comment
Вы смотрите на гонку/многопоточность, поэтому вам нужно быть осторожным шаг за шагом. Взгляните на codeproject.com/Articles/ 1415/ если вы хотите шаг за шагом/минимальный код. - person weismat; 09.07.2014
comment
Большое спасибо за вашу помощь, но пример, который вы привели, выглядит очень идентично моему коду, не могли бы вы уточнить, что вам нужно было сделать, и, возможно, короткий (даже псевдо) код, чтобы дать мне правильное направление - person LordTitiKaka; 09.07.2014
comment
В примере есть ответное сообщение от сервера к клиенту. Мне не хватает этой части в вашем коде. - person weismat; 09.07.2014
comment
Давайте продолжим обсуждение в чате. - person weismat; 09.07.2014
comment
пожалуйста, не забывай обо мне! у моего босса будет моя голова - person LordTitiKaka; 09.07.2014